Home > Enterprise >  In SwiftUI,how to "Foreach" nodes in a LinkedList?
In SwiftUI,how to "Foreach" nodes in a LinkedList?

Time:10-21

I tried to use LinkedList in Foreach in SwiftUI, but I met some problem. The code following can work(Foreach) in playground, but it doesn't work in SwiftUI. I want to draw my UI by CORE (which is node), so I have to make it work with Foreach. I know it has something to do with the hashable protocol, but I'm not sure how to do it.

import Foundation

struct CPU:Sequence{
    public var head:Core?
    

    func makeIterator() -> CPUCoreIterator { 
        return CPUCoreIterator(self)
    }
    mutating func insert(tmp:Float,clocks:Float,load:Float,_ i:Int){
        if head == nil && i == 0 {
            head = Core(tmp, clocks,load,id: i)
            return
        }
        var count:Int = 0
        var current = head
        while(current?.nextCore != nil && count<i){
            current = current?.nextCore
            count =1
        }
        //add core to the CpuCoreList
        if current?.nextCore == nil && count<i {
            current?.nextCore = Core(tmp,clocks,load,id: i)
            return
        }
        //change the core
        if current != nil {
            current?.load = load
            current?.clocks = clocks
            current?.tmp = tmp
            return
        }
        
    }
    func listAll(){
        if head == nil {
            print("No item")
            return
        }
      var current = head
        while(current != nil){
            print(current!.tmp)
            current = current?.nextCore
        }
    }
    
}
class Core:Identifiable {
    public var id:Int
    public var tmp:Float
    public var clocks:Float
    public var load:Float
    public var nextCore:Core?
    
    init(_ tmp:Float,_ clocks:Float,_ load:Float,id:Int){
        self.clocks = clocks
        self.tmp = tmp
        self.load = load
        self.id = id
        self.nextCore = nil
    }
}

struct CPUCoreIterator:IteratorProtocol {
    let cpucorelist:CPU
    var current:Core?
    init(_ cpucorelist:CPU){
        self.cpucorelist = cpucorelist
        current = cpucorelist.head
    }
    mutating func next() -> Core? {
        defer {
            current = current?.nextCore
        }
        guard current != nil
        else { return nil }
        return current
    }
}

Code in View:

    class Test:ObservableObject {
    @Published var cpu = CPU()
}

struct ContentView: View {
    @ObservedObject var test = Test()
    var body: some View {
        VStack{
            ForEach(test.cpu,id: \.self) { core in
                Text("")
            }
        }
    }
}

enter image description here

CodePudding user response:

Making class Core: Identifiable, Hashable, Equatable and using Array in ForEach as shown, works well for me.

struct ContentView: View {
    @ObservedObject var test = Test()
    var body: some View {
        VStack{
            ForEach(Array(test.cpu)) { core in   // <--- here
                Text("id: "   String(core.id)   " tmp: "   String(core.tmp))
            }
        }
        .onAppear {
            test.cpu.head = Core(1.1, 2.2, 3.3, id: 1)
            test.cpu.insert(tmp: 9.2, clocks: 8.2, load: 7.2, 2)
            test.cpu.insert(tmp: 5.3, clocks: 4.3, load: 6.3, 3)
        }
    }
}

class Core: Identifiable, Hashable, Equatable {  // <--- here
    public var id:Int
    public var tmp:Float
    public var clocks:Float
    public var load:Float
    public var nextCore:Core?
    
    static func == (lhs: Core, rhs: Core) -> Bool { // <--- here
        lhs.id == rhs.id
    }
    func hash(into hasher: inout Hasher) { // <--- here
        hasher.combine(id)
    }
    
    init(_ tmp:Float,_ clocks:Float,_ load:Float, id:Int){
        self.clocks = clocks
        self.tmp = tmp
        self.load = load
        self.id = id
        self.nextCore = nil
    }
}
  • Related