evermeer / EVCloudKitDao

Simplified access to Apple's CloudKit
Other
644 stars 67 forks source link

Crash when complex predicate #91

Closed foolbear closed 6 years ago

foolbear commented 6 years ago
(lldb) po filter
"url == \'http://m.yikxshuo.com/book/418314/\' || url == \'http://m.26543xs.com/info-408745/\' || url == \'http://m.yikxshuo.com/book/211002/\' || url == \'http://m.yikxshuo.com/book/432666/\' || url == \'http://m.yikxshuo.com/book/432693/\'"
var filter: String = ""
for item in SHELFMANAGER().shelf {
    if item is Book {
        let book = item as! Book
        for bookFS in book.bookFSs {
            filter += "url == '\(bookFS.url!)' || "
        }
    }
}
filter = String(filter.dropLast(4))
guard filter.isEmpty == false else { return }

EVCloudData.publicDB.connect(CKBookFS(), 
       predicate: NSPredicate(format: filter), filterId: "TraceReaderCount", completionHandler: { [weak self] results, status in
...
evermeer commented 6 years ago

An OR predicate is not supported by CloudKit. See the documentation: https://developer.apple.com/documentation/cloudkit/ckquery

But... It should not crash.... Does it also crash when you just create the NSPredicate? Or does it crash in the .connect? At what line does it crash? What is the crash message?

foolbear commented 6 years ago

So how to solved this solution? subscript each url?

crash at "let query: CKQuery = CKQuery(recordType: recordType, predicate: predicate)"

@discardableResult
    open func query<T: CKDataObject>(_ type: T, predicate: NSPredicate, orderBy: OrderBy = Descending(field: "creationDate"), completionHandler: @escaping (_ results: [T], _ isFinished: Bool) -> Bool, errorHandler:((_ error: Error) -> Void)? = nil) -> CKQueryOperation {
        let recordType = EVReflection.swiftStringFromClass(type)
        **let query: CKQuery = CKQuery(recordType: recordType, predicate: predicate)**
        query.sortDescriptors = orderBy.sortDescriptors()
        return queryRecords(type, query:query, completionHandler: completionHandler, errorHandler: errorHandler)
    }
evermeer commented 6 years ago

Since its the same field you could create an ‘IN’ query.

evermeer commented 6 years ago

You don't have to. You could use an 'in' query. There is a sample of that in the demo app. See the predicate:

NSPredicate(format: "From_ID in %@ AND To_ID in %@", [recordIdMeForConnection, recordIdOtherForConnection], [recordIdOtherForConnection, recordIdMeForConnection]) Here it even uses an 'in' for 2 fields. You can make the arrays as large as you like (with the url's)

let array = SHELFMANAGER().shelf.filter { $0 is Book }.flatMap { $0.bookFs.url }
let predicate = NSPredicate(format: "url in %@", array)

p.s. Above is untested. I hope I have the filter flatMap right... :-)

foolbear commented 6 years ago

yeah, thanks!