In my watch app, I wish to display list of events. When the view is opened, I send a request to iPhone app to send the events list. This is working so far and I am getting the events list back to Watch. However when I try to display the data on the list, I am getting errors due to custom object type. What I want is to display the events list when the data is available or just show a text on the view when there are no events.
Note: Watch connectivity to transfer data between devices/OS's does not allow custom data types, so have to conform to Codable and convert the data from CustomDataModel to Data type before transferring and then convert from Data to CustomDataModel in my Watch project.
Below is the code and error that I see:
CustomDataModel
import Foundation
struct CustomDataModel: Codable {
var startEndDate: String?
var startEndTime: String?
var locationDetails: String?
var actions: Dictionary<String, String> = [:]
var title: String?
// Has more properties
func encodeIt() -> Data {
let data = try! PropertyListEncoder.init().encode(self)
return data
}
static func decodeIt(_ data:Data) -> CustomDataModel {
let customDataModel = try! PropertyListDecoder.init().decode(CustomDataModel.self, from: data)
return customDataModel
}
}
CustomViewModel
import Foundation
import Combine
class CustomViewModel: ObservableObject, SessionCommands {
@Published var eventsList:[CustomDataModel] = []
init() {
NotificationCenter.default.addObserver(forName: Notification.Name("eventsListReady"), object: nil, queue: nil, using: self.processEventsList(_:))
}
@objc func processEventsList(_ notification: Notification) {
if let response = (notification.object as! CommandStatus).response as? [Data] {
response.forEach { event in
eventsList.append(CustomDataModel.decodeIt(event))
}
}
}
func getEventsList() {
self.eventsList = []
sendMessage(["functionality": Functionality.events.rawValue, "notificationName": Notification.Name("requestEventsList")])
}
}
CustomView
import SwiftUI
struct CustomView: View {
@ObservedObject var viewModel: CustomViewModel
var body: some View {
VStack {
if !viewModel.eventsList.isEmpty {
List(viewModel.eventsList) { item in
let _ = print("##### !viewModel.eventsList.isEmpty")
NavigationLink(destination: EventsDetailsView(eventItem: item)) {
EventRowView(eventItem: item)
}.navigationViewStyle(StackNavigationViewStyle())
}
} else {
let _ = print("##### viewModel.eventsList.isEmpty")
VStack {
Text("No events to display")
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}.navigationBarTitle("Back").onAppear() {
self.viewModel.getEventsList()
}
}
}
Error I get on "List(viewModel.eventsList)" in CustomView : Initializer 'init(_:rowContent:)' requires that 'CustomDataModel' conform to 'Identifiable'
I am getting data in eventList object in CustomViewModel, but am not able to display it.
CodePudding user response:
Give your type an id and make it identifiable and if you don’t need decidable don’t add it.
struct MyType: Encodable, Identifiable {
let id = UUID()
// other properties
}
Using Codable
is just shorthand for adding Encodable
and Decodable
. So if you don’t need both, then just use the one you need.