06iyz
@06iyz

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Listのカウント

Swift初心者です
初めての開発なので見にくかったらすいません:pray_tone1:

Playgroundsを参考に在庫管理アプリを作ろうとしています。

実行したいこと

TaskViewにあるListの数をカウントし、ItemRowで表示させたい
どこを直したらいいのか曖昧なので下にコードほぼ全部載っけています、、、

Item

struct Item: Identifiable, Hashable, Codable {
    
   
   
    var id = UUID()
    var title = ""
 
    static var delete = Item()
 
}

// 遷移先のBack文字を消す
struct NavigationBarBackButtonTextHidden: ViewModifier {
  @Environment(\.presentationMode) var presentaion
  
  func body(content: Content) -> some View {
    content
      .navigationBarBackButtonHidden(true)
      .toolbar {
        ToolbarItem(placement: .navigationBarLeading) {
          Button(action: { presentaion.wrappedValue.dismiss() }) {
            Image(systemName: "chevron.backward")
          }
        }
      }
  }
}

extension View {
  func navigationBarBackButtonTextHidden() -> some View {
    return self.modifier(NavigationBarBackButtonTextHidden())
  }
}




ItemData


import SwiftUI

    class ItemData: ObservableObject {
        
        @Published var items: [Item] = [
            
            
            Item(
                
                title: "洗剤"
              
            ),
            
        ]
        
        var itemTaskData = [Item: TaskData]()

        
        func add(_ item: Item) {
            items.append(item)
        }
        
        func remove(_ item: Item) {
            items.removeAll { $0.id == item.id}
        }
        
        func getBindingToItem(_ item: Item) -> Binding<Item>? {
            Binding<Item>(
                get: {
                    guard let index = self.items.firstIndex(where: { $0.id == item.id }) else { return Item.delete }
                    return self.items[index]
                },
                set: { item in
                    guard let index = self.items.firstIndex(where: { $0.id == item.id }) else { return }
                    self.items[index] = item
                }
            )
        }

ItemRow

struct ItemRow: View {
    
    @ScaledMetric var imageWidth: CGFloat = 40

    let item: Item
    let taskData: TaskData
  
    var body: some View {
        HStack {
            Label {
                VStack(alignment: .leading, spacing: 5) {
                    Text(item.title)
                    
                }
            } icon: {
                Image(systemName: "pencil.circle")
                
                                        .padding(.trailing, 15)
            }
      
        }//H
        .badge(taskData.remainingTaskCount)
    }
}

Task



import Foundation

struct Task: Identifiable, Hashable, Codable {
   
    var id = UUID()
    var text = ""
    var count: Int = 0
    var memo = ""
    var isCompleted = false
    var date = Date.now
    
    
}

TaskData

import SwiftUI

class TaskData: ObservableObject {
    
    @Published var tasks: [Task] = [
        
        
        Task(
            text: "洗剤",
            memo: "",
            date: Date.roundedHoursFromNow(60 * 60 * 22)
        ),
        
    ]
    
    var remainingTaskCount : Int {
        tasks.filter { !$0.isCompleted && !$0.text.isEmpty }.count
    }
    
    func add(_ task: Task) {
        tasks.append(task)
    }
    
    
    func sortedTasks(period: Period) -> Binding<[Task]> {
        
        Binding<[Task]>(
            get: {
                self.tasks
                   
                    .sorted { $0.date < $1.date }
            },
            set: { tasks in
                for task in tasks {
                    if let index = self.tasks.firstIndex(where: { $0.id == task.id }) {
                        self.tasks[index] = task
                    }
                }
            }
        )
    }
    
   
}

enum Period: String, CaseIterable, Identifiable {
    case nextSevenDays = "Next 7 Days"
    
    
    var id: String { self.rawValue }
    var name: String { self.rawValue }
}

extension Date {
    static func roundedHoursFromNow(_ hours: Double) -> Date {
        let exactDate = Date(timeIntervalSinceNow: hours)
        guard let hourRange = Calendar.current.dateInterval(of: .hour, for: exactDate) else {
            return exactDate
        }
        return hourRange.end
    }
}



TaskRow



import SwiftUI

struct TaskRow: View {
    @Binding var task: Task
   

    var body: some View {
        HStack {
            Button {
                task.isCompleted.toggle()
            } label: {
                Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
            }
            .buttonStyle(.plain)
            
            
            VStack {
                
                TextField("Task Description", text: $task.text, axis: .vertical)
                TextField("memo", text: $task.memo).font(.subheadline).foregroundColor(.gray)
            }
            .opacity(task.isCompleted ? 0.5 : 1.0)
         
            Spacer()
            
            VStack {
                Text("消費期限").font(.subheadline)
                DatePicker("", selection: $task.date, displayedComponents: [.date])
                    .environment(\.locale, Locale(identifier: "ja_JP"))
            }.opacity(task.isCompleted ? 0.5 : 1.0)
        }
    }
}


TaskView



import SwiftUI

struct TaskView: View {
    @ObservedObject var taskData: TaskData
    @Binding var item: Item
    @State private var newTask = Task()
    

    var body: some View {
        NavigationStack {
            List {
                ForEach(Period.allCases) { period in
                    
                Section(content: {
                    
                    ForEach(taskData.sortedTasks(period: period)) { $task in
                        TaskRow(task: $task)
                            
                    }//for
                    
                    Button {
                        let newTask = Task(text: "", memo: "¥")
                        taskData.tasks.append(newTask)
                    } label: {
                        HStack {
                            Image(systemName: "plus")
                            Text("Add Task")
                        }
                    }//Button
                    
                    
                }//section
                        
                       )
                    
                   
                .disabled(taskData.sortedTasks(period: period).isEmpty)
                        }
                
               
                
            }//List
            
        }//Navi
            
        
        
    }//var
    
    
}//st
0

1Answer

enum Periodの定義が見当たりません・・・。他にもコードの漏れはありませんか。

0Like

Comments

  1.         ForEach(taskData.sortedTasks(period: period)) { $task in
                TaskRow(task: $task)
                
            }//for
    

    taskData.sortedTasksのコードが見当たりません。

  2. @06iyz

    Questioner

    TaskDataコピペミスしてました、、、
    更新したので見ていただけると助かります。

  3. TaskViewにあるListの数をカウントし、ItemRowで表示させたい

    現状のコードは、TaskViewにあるTaskData内のTaskリストをTaskRowで表示しています。
    その上部に、TaskDataをItemRowで表示させたいということでしょうか?

  4. @06iyz

    Questioner

    コメント頂いたにも関わらず返信が遅くなってしまい申し訳ありません。
    Simulator Screenshot - iPhone 16 Pro - 2025-03-01 at 12.08.43.png
    画面下半分(TaskView)にあるリストの数を右上部(ItemaRow)にある(現在1と表示されている)ところに表示したいです

  5. メインビュー(ContentView ?)のコードを見ないと画面全体の構成が分かりません。

  6. @06iyz

    Questioner

    
    import SwiftUI
    
    struct EventView: View {
        
        @ObservedObject var eventData: EventData
        
        @State private var isAddingNewEvent = false
        @State private var isEventEditor = false
        @State private var isShowLackView = false
        @State private var newEvent = Event()
        @State private var selection: Event?
      
        
        var body: some View {
    
                    NavigationSplitView {
                         
                            List(selection: $selection) {
                                      
                                
                                ForEach(eventData.events) { event in
                                    
                                    EventRow(event: event)
                                        .tag(event)
                                    
                                        .swipeActions {
                                            Button(role: .destructive) {
                                                selection = nil
                                                eventData.remove(event)
                                            } label: {
                                                Label("Delete", systemImage: "trash")
                                            }
                                        }//swipe
                                }//ForEach
                            }//List
                        
                        .toolbar {
                            ToolbarItem {
                                Button {
                                    newEvent = Event()
                                    isAddingNewEvent = true
                                } label: {
                                    Image(systemName: "plus")
                                }
                            }
                        }
                        .sheet(isPresented: $isAddingNewEvent) {
                            NavigationStack {
                                EventEditor(event: $newEvent)
                                    .toolbar {
                                        ToolbarItem(placement: .cancellationAction) {
                                            Button("Cancel") {
                                                isAddingNewEvent = false
                                            }
                                        }
                                        ToolbarItem {
                                            Button {
                                                eventData.add(newEvent)
                                                isAddingNewEvent = false
                                            } label: {
                                                Text("Add" )
                                            }
                                            .disabled(newEvent.title.isEmpty)
                                        }
                                    }
                            }
                        }
                        
                        
                    } detail: {
                        ZStack {
                            if let event = selection, let eventBinding = eventData.getBindingToEvent(event) {
                                ItemView(itemData: getItemData(event),event: eventBinding)
                            } else {
                                Text("Select an Event")
                                    .foregroundStyle(.secondary)
                            }
                        }
                        
                    }
                   
           
        }
        
        func getItemData(_ event: Event) -> ItemData {
                if let itemData = eventData.eventItemData[event] { return itemData }
                eventData.eventItemData[event] = ItemData()
                return eventData.eventItemData[event]!
            }
        
    }
    
    
  7. 次の、クラス/ストラクト、ビューの定義が見つかりません。

    EventData
    Event
    EventRow
    EventEditor

    それとも、TaskXXX を EventXXX にリネームしました?

  8. @06iyz

    Questioner

    Event

    import SwiftUI
    
    struct Event: Identifiable, Hashable, Codable {
       
        var id = UUID()
        var symbol: String = EventSymbols.randomName()
        var color: RGBAColor = ColorOptions.random().rgbaColor
        var title = ""
    
        static var delete = Event(symbol: "trash")
    }
    
    

    EventData

    import SwiftUI
    
    class EventData: ObservableObject {
        
        @Published var events: [Event] = [
            
                 
            Event(symbol: "bathtub.fill",
                  color: Color.yellow.rgbaColor,
                  title: "お風呂"
                 ),
            
           
        ]
        
        var eventItemData = [Event: ItemData]()
    
        
        
        func add(_ event: Event) {
            events.append(event)
        }
            
        func remove(_ event: Event) {
            events.removeAll { $0.id == event.id}
        }
        
        
        
        func getBindingToEvent(_ event: Event) -> Binding<Event>? {
            Binding<Event>(
                get: {
                    guard let index = self.events.firstIndex(where: { $0.id == event.id }) else { return Event.delete }
                    return self.events[index]
                },
                set: { event in
                    guard let index = self.events.firstIndex(where: { $0.id == event.id }) else { return }
                    self.events[index] = event
                }
            )
        }
        
    
        private static func getEventsFileURL() throws -> URL {
            FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
                .appendingPathComponent("events.data")
        }
       
    }
    

    EventEditor

    
    
    import SwiftUI
    
    struct EventEditor: View {
        @Binding var event: Event
        @State private var isPickingSymbol = false
    
        var body: some View {
            List {
               
                HStack {
                    
                    Button {
                                       isPickingSymbol.toggle()
                                   } label: {
                                       Image(systemName: event.symbol)
                                           .imageScale(.large)
                                           .foregroundColor(Color(event.color))
                                   }
                                   .buttonStyle(.plain)
                                   .padding(.horizontal, 5)
                   
                    TextField("New List", text: $event.title)
                        .font(.title2)
                }
                
                
            }
    
            .sheet(isPresented: $isPickingSymbol) {
                        SymbolPicker(event: $event)
                    }
            
        }
    }
    
    
    

    EventRow

    import SwiftUI
    
    struct EventRow: View {
        
        @ScaledMetric var imageWidth: CGFloat = 40
        
        let event: Event
        
        var body: some View {
            VStack {
                Spacer()
                Label {
                        Text(event.title)
                            .fontWeight(.bold)
                } icon: {
                    Image(systemName: event.symbol)
                        .foregroundStyle(Color(event.color))
                        .padding(.trailing, 15)
                }
                .labelStyle(CustomLabelStyle())
                Spacer()
            }
            
        }
    }
    
    
    
  9. 次の、class/struct、func/extensionが見つかりません。
    (堂々巡りになってきました)

    EventSymbols.randomName()
    RGBAColor
    ColorOptions.random().rgbaColor

    Color.rgbaColor

    CustomLabelStyle()

  10. @06iyz

    Questioner

    何度も何度もすみません、、、
    EventSymbols

    struct EventSymbols {
        static func randomName() -> String {
            if let random = symbolNames.randomElement() {
                return random
            } else {
                return ""
            }
        }
        
        static func randomNames(_ number: Int) -> [String] {
            var names: [String] = []
            for _ in 0..<number {
                names.append(randomName())
            }
            return names
        }
            
        static var symbolNames: [String] = [
            "house.fill",
            "ticket.fill",
            "gamecontroller.fill",
            "theatermasks.fill",
            "books.vertical.fill",
            "toilet",
            
            "moon.zzz.fill",
            "bathtub.fill",
            "paintbrush.pointed.fill",
            "leaf.fill",
            "globe.americas.fill",
            "clock.fill",
            
            "building.2.fill",
            "gift.fill",
            "refrigerator.fill",
            "heart.rectangle.fill",
            "phone.bubble.left.fill",
            "frying.pan",
            
            "star.fill",
            "crown.fill",
            "briefcase.fill",
            "speaker.wave.3.fill",
            "tshirt.fill",
            "tag.fill",
            
            "airplane",
            "pawprint.fill",
            "case.fill",
            "creditcard.fill",
            "infinity.circle.fill",
            "dice.fill",
            
            "heart.fill",
            "camera.fill",
            "bicycle",
            "radio.fill",
            "car.fill",
            "flag.fill",
            
            "map.fill",
            "figure.wave",
            "mappin.and.ellipse",
            "heart.text.square.fill",
            "eyeglasses",
            "tram.fill",
            
            
        ]
    }
    

    ColorOption

    import SwiftUI
    
    struct ColorOptions: Codable {
        static var all: [Color] = [
            .primary,
            .gray,
            .red,
            .orange,
            .yellow,
            .green,
            .mint,
            .cyan,
            .indigo,
            .purple,
        ]
        
        static var `default` : Color = Color.primary
        
        static func random() -> Color {
            if let element = ColorOptions.all.randomElement() {
                return element
            } else {
                return .primary
            }
            
        }
    }
    
    struct RGBAColor: Codable, Hashable {
        var r: CGFloat
        var g: CGFloat
        var b: CGFloat
        var a: CGFloat
    }
    
    extension Color {
        var r: CGFloat { UIColor(self).colorComponents.red }
        var g: CGFloat { UIColor(self).colorComponents.green }
        var b: CGFloat { UIColor(self).colorComponents.blue }
        var a: CGFloat { UIColor(self).colorComponents.alpha }
        
        var rgbaColor: RGBAColor {
            RGBAColor(r: self.r, g: self.g, b: self.b, a: self.a)
        }
        
        init(_ rgbaColor: RGBAColor) {
            self.init(red: rgbaColor.r, green: rgbaColor.g, blue: rgbaColor.b, opacity: rgbaColor.a)
        }
    }
    
    extension UIColor {
        var colorComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
            var r: CGFloat = 0
            var g: CGFloat = 0
            var b: CGFloat = 0
            var a: CGFloat = 0
            getRed(&r, green: &g, blue: &b, alpha: &a)
    
            return (r, g, b, a)
        }
    }
    
    

    CustomButtonView

    import SwiftUI
    
    struct CustomButton: View {
       
        
        var title: String
       
        var body: some View {
            
           
            // ラベル部分
            Text(title)
                .font(.footnote)
                .foregroundColor(.white)
                .padding(.bottom, 8)
             //   .frame(maxWidth: .infinity, alignment: .leading) // 左揃え
           
            // ボタンの背景
            .frame(width: 150, height: 70) // サイズ調整
            .background(Color.secondary)
            .cornerRadius(12) // 角丸
    //.shadow(color: .gray.opacity(0.2), radius: 4, x: 0, y: 2)
        }
    }
    
    

    CustomLabelStyle

    
    import SwiftUI
    
    struct CustomLabelStyle: LabelStyle {
      @ScaledMetric private var iconWidth: Double = 40
      func makeBody(configuration: Configuration) -> some View {
        HStack(spacing: 0) {
          configuration.icon
            .imageScale(.large)
            .frame(width: iconWidth)
          configuration.title
        }
      }
    }
    
    

    SymbolPicker

    import SwiftUI
    
    struct SymbolPicker: View {
        @Binding var event: Event
        @State private var selectedColor: Color = ColorOptions.default
        @Environment(\.dismiss) private var dismiss
        @State private var symbolNames = EventSymbols.symbolNames
        @State private var searchInput = ""
        
        var columns = Array(repeating: GridItem(.flexible()), count: 6)
    
        var body: some View {
            VStack {
                HStack {
                    Spacer()
                    Button {
                        dismiss()
                    } label: {
                        Text("Done")
                    }
                    .padding()
                }
                HStack {
                    Image(systemName: event.symbol)
                        .font(.title)
                        .imageScale(.large)
                        .foregroundColor(selectedColor)
    
                }
                .padding()
    
                HStack {
                    ForEach(ColorOptions.all, id: \.self) { color in
                        Button {
                            selectedColor = color
                            event.color = color.rgbaColor
                        } label: {
                            Circle()
                                .foregroundColor(color)
                        }
                    }
                }
                .padding(.horizontal)
                .frame(height: 40)
    
                Divider()
    
                ScrollView {
                    LazyVGrid(columns: columns) {
                        ForEach(symbolNames, id: \.self) { symbolItem in
                            Button {
                                event.symbol = symbolItem
                            } label: {
                                Image(systemName: symbolItem)
                                    .imageScale(.large)
                                    .foregroundColor(selectedColor)
                                    .padding(5)
                            }
                            .buttonStyle(.plain)
                        }
                    }
                    .drawingGroup()
                }
            }
            .onAppear {
                selectedColor = Color(event.color)
            }
        }
    }
    
    //struct SFSymbolBrowser_Previews: PreviewProvider {
    //    static var previews: some View {
    //        SymbolPicker(event: .constant(Event.example))
    //    }
    //}
    
    

Your answer might help someone💌