0

我对 Swift 完全陌生。我需要遍历一个数组,并根据数据是什么,构建一个自定义的树结构。我会分享我的代码,但它太笨重而且太可怕了,无法在公共场合看到。它甚至不接近工作。所以这里有一些伪代码:

pass in an array of ScheduleCell models (data for a scheduled tv program) to a SwiftUI View.

Each ScheduleCell contains:
   Date of broadcast
   Channel
   Starttime
   Program title, subtitle, etc

in the view body, loop over each ScheduleCell
   if ScheduleCell is new day then
      display new date
      go down one line
   end
      
   if ScheduleCell is new channel then
      display ScheduleCell.channel but do NOT drop down a line
   end

   display ScheduleCell.title, also on same line as channel

   Keep going on the same horizontal line till you hit the next channel

end

最终效果应该是这样的:

11-16-2021

CNN         News Program 1    News Program 2    News Program 3        Etc.
NBC         Late Show         Infomercial       Barney Miller Rerun.  Etc.

11-17-2021

CNN         News Program 1    News Program 2    News Program 3        Etc.
NBC         Late Show         Infomercial       Barney Miller Rerun.  Etc.

看起来这样做应该很简单。我尝试设置树结构,但 SwiftUI View 协议遇到问题。我尝试在视图主体之外的函数中构建树结构,但我无法弄清楚如何将该结构放入视图主体。

或者,我已经放弃了所有这些,只是试图通过跟踪数组索引来通过视图内部的蛮力使其工作,如下所示:

struct ScheduleDisplayView: View {
    
    var schedule: [SchedSlot]
    let dfdo = DateFormatter.dateOnly
    let dfto = DateFormatter.timeOnly

    let chanwidth: CGFloat = 45.0
    let fontsize: CGFloat = 10.0

    var body: some View {
        
        List {
            ForEach(schedule.indices,id:\.self) { idx in
                let ssDay: String = dfdo.string(from: schedule[idx].startTime!)
                let ssChan: Int32 = schedule[idx].channel!.channelID
                if idx == 0 ||
                    ssDay != dfdo.string(from: schedule[idx-1].startTime!)
                {
                    VStack {
                        Text(ssDay)
                            .frame(maxWidth: 200 + chanwidth, alignment: .leading)
                    }
                }
                HStack {
                    if idx == 0 ||
                        ssChan != schedule[idx-1].channel!.channelID
                    {
                        VStack {
                            Text(String(schedule[idx].channel!.channelID))
                                .frame(maxWidth: chanwidth, alignment: .center)
                            //.font(.system(size: fontsize))
                            Text(schedule[idx].channel!.callSign!)
                                .frame(maxWidth: chanwidth, alignment: .center)
                            //.font(.system(size: fontsize))
                        }
                    }
                    Text(schedule[idx].program!.title!)
                        .frame(maxWidth: 200, alignment: .leading)
                        .border(Color.black)
                }
                
            }
        }
    }
}

但上述方法不起作用,因为 HStack 不能将程序标题保持在同一行。

提前感谢您的任何意见。

附加材料:

下面是一些基于 CoreData 实体的随机切片:

SchedCell
stationID   starttime   programID   duration    endtime isUsed channel  program
34916   2021-09-29 19:09:00.000 EP000045050088  PT00H09M    2021-09-29 19:18:00.000 0
12131   2021-09-29 19:15:00.000 EP022222100024  PT00H15M    2021-09-29 19:30:00.000 0
34916   2021-09-29 19:18:00.000 EP000045050208  PT00H09M    2021-09-29 19:27:00.000 0

Program
series  programID   title   subtitle    fulldescription genre isUsed 
EP00000066  EP000000660001  A Pup Named Scooby-Doo  Night of the Living Burger  After a quarrel, a burgerlike creature haunts Shaggy and Scooby.    Children    0
EP00000066  EP000000660002  A Pup Named Scooby-Doo  For Letter or Worse The ghost of a long-dead gangster haunts a TV studio.   Children    0
EP00000066  EP000000660003  A Pup Named Scooby-Doo  A Bicycle Built for Boo!    A green monster steals Shaggy's bike.   Children    0
EP00000066  EP000000660004  A Pup Named Scooby-Doo  The Baby Sitter From Beyond The baby sitter for Shaggy's little sister appears to be a monster. Children    0

Channel
stationID callSign  fullName channelID isUsed
15722   WCIX    WCIX    2   0
11345   WCIA    WCIA    3   0
11278   WAND    WAND    4   0
10685   KSDK    KSDK    5   0
10269   HSN Home Shopping Network   6   0
11824   WRSP    WRSP    7   0
11069   QVC QVC 8   0

至于我尝试在视图之外构建树结构的代码示例,我没有工作代码。这只是产生各种错误消息的片段。这是节点结构。我仍在制定将它们组装成工作树的例程,一旦我有值得一看的东西就会发布:

class RootNode {
    var children: [DayNode] = []
    
    func add(child: DayNode) {
      children.append(child)
      child.parent = self
    }
}

class DayNode {
    var parent: RootNode
    var date: String
    var children: [ChannelNode] = []
    
    init(date: String) {
        self.date = date
    }
    
    func add(child: ChannelNode) {
      children.append(child)
      child.parent = self
    }
}

class ChannelNode {
    var parent: DayNode
    var channel: String
    var children: [SchedSlot] = []
    
    init(channel: String) {
        self.channel = channel
    }
    
    func add(child: SchedSlot) {
      children.append(child)
      //child.parent = self
    }
}
4

1 回答 1

0

正如我在评论中提到的,我认为这更多的是数据组织/排序问题,而不是 SwiftUI 布局问题。如果您的数据被正确分组和排序,则布局会变得更简单(例如,您不必尝试决定是否因为新通道而换行)。

在以下示例中,我将大部分代码用于对数据进行分组和排序。那么,布局本身就比较简单了。

重要的是要注意,为了简洁起见,我在这里做了一些不安全的事情,比如first!在实际代码中使用你想要测试或有意外情况的东西。

struct SchedCell {
    var stationID: Int
    var startTime: Date
    var programID: String
    var channel: String
}

func generateSampleCells() -> [SchedCell] {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
    return [
        ("2021-09-29 19:09:00.000",34916,"EP000045050088","PT00H09M"),
        ("2021-09-29 19:09:00.000",34917,"EP000045050088","PT00H09M"),
        ("2021-09-29 19:15:00.000",12131,"EP022222100024","PT00H15M"),
        ("2021-09-29 19:18:00.000",34916,"EP000045050208","PT00H09M"),
        ("2021-09-30 19:09:00.000",34916,"EP000045050088","PT00H09M"),
        ("2021-09-30 19:15:00.000",12131,"EP022222100024","PT00H15M"),
        ("2021-09-30 19:18:00.000",34916,"EP000045050208","PT00H09M"),
        ("2021-09-30 19:15:00.000",12132,"EP022222100024","PT00H15M"),
        ("2021-09-29 19:09:00.000",4916,"EP000045050088","PT00H09M"),
        ("2021-09-29 19:09:00.000",4917,"EP000045050088","PT00H09M"),
        ("2021-09-29 19:15:00.000",2131,"EP022222100024","PT00H15M"),
    ].map {
        SchedCell(stationID: $0.1, startTime: formatter.date(from: $0.0)!, programID: $0.2, channel: $0.3)
    }
}

struct ContentView: View {
    
    private var data = generateSampleCells()
    private var formatter = DateFormatter()
    
    struct ScheduleDay {
        var dateStamp: String
        var date : Date
        var channels: [ChannelLineup]
    }

    struct ChannelLineup {
        var channelName: String
        var programs: [SchedCell]
    }

    struct DateStampedSchedCell {
        var dateStamp: String
        var cell: SchedCell
    }
    
    var sortedData : [ScheduleDay] {
        formatter.dateFormat = "MM-dd-yyyy"

        let dateStamped = data
            .map { item -> DateStampedSchedCell in
            DateStampedSchedCell(dateStamp: formatter.string(from: item.startTime), cell: item)
        }

        let days = Dictionary(grouping: dateStamped, by: { $0.dateStamp} ).values

        let channelMappedDays = days.map { day in
            ScheduleDay(dateStamp: day.first!.dateStamp,
                        date: day.first!.cell.startTime,
                        channels: Dictionary(grouping: day, by: { $0.cell.channel }).map { ChannelLineup(channelName: $0.key, programs: $0.value.map(\.cell))}
            )
        }.sorted(by: {a,b in a.date < b.date})

        return channelMappedDays
    }
    
    var body: some View {
        ScrollView(.horizontal) {
            ForEach(sortedData, id: \.dateStamp) { day in
                VStack(alignment: .leading) {
                    Text("Day: \(day.dateStamp)")
                        .bold()
                    ForEach(day.channels, id: \.channelName) { channel in
                        HStack {
                            Text("Channel: \(channel.channelName)")
                                .foregroundColor(.red)
                            ForEach(channel.programs, id: \.programID) { program in
                                Text(program.programID)
                            }
                        }
                    }
                }.frame(maxWidth: .infinity, alignment: .leading)
            }
        }
    }
}

在此处输入图像描述

于 2021-11-17T07:40:50.457 回答