iOS开发:CloudKit搜索功能遇String转Event类型转换错误求助
解决CloudKit搜索国家列表的类型转换错误
遇到的错误
Cannot convert value of type 'String' to expected argument type Event
错误根源
错误出在RowView_Previews的预览代码里:RowView(city: Event.Country)。Event.Country是字符串类型,但RowView的city参数要求传入完整的Event实例,类型不匹配导致报错。
分步修复方案
1. 修复预览代码
给Event结构体添加一个用于预览的便捷初始化方法,生成测试用的Event实例:
struct Event: Identifiable{ let record: CKRecord let id: CKRecord.ID let Country: String let dateTime : Date init(record: CKRecord){ self.record = record self.id = record.recordID self.Country = record["Country"] as? String ?? "" self.dateTime = record["dateTime"] as? Date ?? Date.now } // 添加预览专用的初始化方法 static func previewSample() -> Event { let testRecord = CKRecord(recordType: "Event") testRecord["Country"] = "中国" testRecord["dateTime"] = Date.now return Event(record: testRecord) } }
然后修改RowView的预览代码:
struct RowView_Previews: PreviewProvider { static var previews: some View { RowView(city: Event.previewSample()) .previewLayout(.sizeThatFits) } }
2. 修复CloudKit异步更新UI问题
fetchEvent里的CloudKit查询是异步操作,直接修改events会导致UI线程异常,必须切换到主线程更新:
func fetchEvent(){ events.removeAll() let predicate = NSPredicate(value: true) let query = CKQuery(recordType:"Event", predicate: predicate) let operation = CKQueryOperation(query: query) operation.recordMatchedBlock = {recordID, result in switch result{ case .success(let record): let event = Event(record: record) // 回到主线程更新UI数组 DispatchQueue.main.async { self.events.append(event) } case .failure(let error): print("Error:\(error.localizedDescription)") } } CKContainer.default().publicCloudDatabase.add(operation) }
3. 修复搜索逻辑的数据源丢失问题
当前搜索逻辑会直接过滤events数组,导致原数据丢失,应该保留一份完整的原始数据源:
struct NewCity: View { @State private var searchText = "" @State private var showingNatio = false @State private var showingNotifi = false @State var allEvents :[Event] = [] // 存储从CloudKit获取的所有数据 @State var events :[Event] = [] // 存储过滤后的展示数据 var body: some View { NavigationView { VStack{ Text("Search for a country") .font(.title.weight(.bold)) .foregroundColor(Color.gray) .searchable(text: $searchText){ ForEach(events) { city in RowView(city: city) } }.onChange(of: searchText) { text in // 根据搜索文本过滤原始数据 if text.isEmpty { events = allEvents } else { events = allEvents.filter { event in event.Country.lowercased().contains(text.lowercased()) } } } .navigationTitle("Countries") Text("Start searching for a country \n to add it to your list") .foregroundColor(Color.gray) .multilineTextAlignment(.center) } .frame(maxWidth: .infinity, maxHeight: .infinity) .onAppear { // 页面加载时自动获取CloudKit数据 fetchEvent() } } } func fetchEvent(){ allEvents.removeAll() let predicate = NSPredicate(value: true) let query = CKQuery(recordType:"Event", predicate: predicate) let operation = CKQueryOperation(query: query) operation.recordMatchedBlock = {recordID, result in switch result{ case .success(let record): let event = Event(record: record) DispatchQueue.main.async { self.allEvents.append(event) self.events = self.allEvents } case .failure(let error): print("Error:\(error.localizedDescription)") } } CKContainer.default().publicCloudDatabase.add(operation) } }
内容的提问来源于stack exchange,提问作者Maymoonah Bashir
相关产品推荐
相关产品推荐

