UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: RandomAccessCollection conformance

Forums > 100 Days of SwiftUI

Based on the 100 Days projects I started on a custom project, but in the class definitions below the RegattaList does not conform to RandomAccessCollection so I cannot use it in a ForEach. I cannot see what the issue is as it is an array of Regatta which has a UUID?

import Foundation
import SwiftUI

class Regatta: Identifiable, Codable {
    var id : UUID = UUID()
    var name = "Sample Regatta"
    var scoreType: ScoreMethod = .Lowpoint
    var startDate: Date = Date()
    var endDate: Date = Date()
    var contact = "Me"
    var boatClass: BoatClass = .DF95
    var skippers: [Skipper]
    //var scores :
}

@MainActor class RegattaList: ObservableObject, RandomAccessCollection {

    @Published  var regattas: [Regatta]

    let savePath = FileManager.documentsDirectory.appendingPathComponent("SavedRegattas")

    init() {
        do {
            let data = try Data(contentsOf: savePath)
            regattas = try JSONDecoder().decode([Regatta].self, from: data)
        } catch {
            regattas = []
            // why doesnt this work?
            //regattas = [Regatta(name: "Getting Started", scoreType: ScoreMethod.Lowpoint, startDate: Date(), endDate: Date(), contact: "You!")]
        }
    }
    private func save() {
        do {
            let data = try JSONEncoder().encode(regattas)
            try data.write(to: savePath, options: [.atomic, .completeFileProtection])
        } catch {
            print("Unable to save data.")
        }

    }
    func add(_ regatta: Regatta) {
        regattas.append(regatta)
        save()
    }

    let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .short
        //formatter.timeStyle = .medium
        return formatter
    }()
}

class Skipper: Codable {
    var id: UUID
    var firstName: String
    var lastName: String
    var boatNum: Int
    var sailNum: Int
    static func ==(lhs: Skipper, rhs: Skipper) -> Bool {
        return lhs.lastName == rhs.lastName && lhs.sailNum == rhs.sailNum
    }
}

2      

RegattaList is not an an array of Regatta. It is an ObservableObject that contains an array of Regatta. The regattas property is the array of Regatta. Use that in the ForEach.

2      

Codable will only work if ALL the elements are codable. In the Regatta class you have, Skipper,ScoreMethod and BoatClass. You have given the Skipper class and see that it is Codable, however the other two (which is assume are enums) these also need to confrom to Codable

If you remove them you will see that the code should work!

struct Regatta: Identifiable, Codable {
    var id = UUID()
    var name: String
//    var scoreType: ScoreMethod = .Lowpoint
    var startDate: Date
    var endDate: Date
    var contact: String
//    var boatClass: BoatClass = .DF95
    var skippers: [Skipper]
}

class RegattaList: ObservableObject {

    @Published  var regattas: [Regatta]

    let savePath = FileManager.documentsDirectory.appendingPathExtension("SavedRegattas")

    init() {
        do {
            let data = try Data(contentsOf: savePath)
            regattas = try JSONDecoder().decode([Regatta].self, from: data)
        } catch {
            regattas = []
            // why doesnt this work?
            //regattas = [Regatta(name: "Getting Started", scoreType: ScoreMethod.Lowpoint, startDate: Date(), endDate: Date(), contact: "You!")]
        }
    }

    private func save() {
        do {
            let data = try JSONEncoder().encode(regattas)
            try data.write(to: savePath, options: [.atomic, .completeFileProtection])
        } catch {
            print("Unable to save data.")
        }

    }

    func add(_ regatta: Regatta) {
        regattas.append(regatta)
        save()
    }

    let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .short
        //formatter.timeStyle = .medium
        return formatter
    }()

}

struct Skipper: Codable {
    var id: UUID
    var firstName: String
    var lastName: String
    var boatNum: Int
    var sailNum: Int

    static func ==(lhs: Skipper, rhs: Skipper) -> Bool {
        return lhs.lastName == rhs.lastName && lhs.sailNum == rhs.sailNum
    }
}

extension FileManager {
    static var documentsDirectory: URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0]
    }
}
struct ContentView: View {
    @StateObject private var regattaList = RegattaList()

    var body: some View {
        List {
            ForEach(regattaList.regattas) { regatta in
                Text(regatta.name)
            }
        }
    }
}

2      

Thanks for the input Guys. After correcting the ForEach I found the issue to be that Regatta was not hashable but could fix that with a hash func definition. Good learning experience

2      

Not sure why you would need to conform Regatta to Hashable. Identifiable should be sufficient for the ForEach to work, unless something else is going on in the code you haven't shown us.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.