Home > Software design >  MacOS swiftUI table select a single item
MacOS swiftUI table select a single item

Time:03-29

I followed the example from here: SwiftUI 3 MacOs Table single selection and double click open sheet

But it's not working well for me.

I have a structure like this:

struct Response: Codable {
    var items: [Repository]
}

struct Repository: Codable, Identifiable {
    var number = UUID()
    var id: Int = 0
    let name: String
    let updated_at: String
    let owner: Owner
    let stargazers_count: Int
    let forks_count: Int
    let language: String?
    let description: String?

    struct Owner: Codable {
        let login: String
    }

    enum CodingKeys: String, CodingKey {
        case name, updated_at, owner, stargazers_count, forks_count, language, description
    }
}

class Api : ObservableObject{
    func loadData(query: String = "javascript", completion:@escaping ([Repository]) -> ()) {
        guard let url = URL(string: "https://api.github.com/search/repositories?q=\(query)") else {
            print("Invalid url...")
            return
        }
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data!) {
                var id = 0
                let results = decodedResponse.items.map { (repo: Repository) -> Repository in
                    var copyRepo = repo
                    copyRepo.id = id
                    id  = 1
                    return copyRepo
                }
                print(results)
                DispatchQueue.main.async {
                    completion(results)
                }
            }
        }.resume()

    }
}


...

    @State var repositories = [Repository]()

    @State private var sortOrder = [KeyPathComparator(\Repository.name)]
    @State private var selectedRepository: Repository.ID?

    public var body: some View {

         if(selectedRepository != nil)//null??
         Text(repositories[selectedRepository!].name)

Table(repositories, selection: $selectedRepository, sortOrder: $sortOrder) {
                    TableColumn("Name") {
                        Text($0.name)
                            .frame(
                                maxWidth: .infinity,
                                maxHeight: .infinity,
                                alignment: .leading
                            )
                            .contentShape(Rectangle())
                            .contextMenu {
                                Button(action: {}) { Text("Action") }
                            }
                            /*.gesture(TapGesture(count: 2).onEnded {
                                print("pr", selectedRepository )
                            })*/
                    }

                    TableColumn("Last updated"){
                        Text($0.updated_at)
                    }
                    TableColumn("Owner", value: \.owner.login)
                }
                .onAppear() {
                    Api().loadData { (repositories) in
                        self.repositories = repositories
                        self.isLoading = false
                    }
                }
                .onChange(of: sortOrder) {
                    print($0)
                    repositories.sort(using: $0)
                }

    }

I would like to make sure that when the user clicks on an element of the table, then activates the selection to show the data of the selected element in a Text field, I have tried to have the name printed but it is not working.

It gives me the following error after starting the app: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

Can you give me a hand?

CodePudding user response:

May be some missing character :

if(selectedRepository != nil)//null?? <- missing '{'
    Text(repositories[selectedRepository!].name)

Also be writing like :

if let selectedRepository = selectedRepository {
    Text(repositories[selectedRepository!].name)
    ...
}

Even if not necessary I always prefer to initialise properties (It is more an habit that something useful) :

@State private var selectedRepository: Repository.ID? = nil
  • Related