2

Swift 4.2 iOS 11.x

Trying to read the records in a iCloud database that have a lineOwner field set, but struggling to create an NSPredicate that works!

This looks ok, but doesn't parse.

let predicate = NSPredicate(format: remoteAttributes.lineOwner + " != %@",0)

I get an invalid predicate error message [and a nasty crash into the bargain]. Spend a couple of hours on this and losing the will to live.

If I print out the database I see this.

enter image description here

user3069232
  • 8,587
  • 7
  • 46
  • 87
  • 1
    The crash is because you are having a placeholder `%@` but use an `Int` instead. Use a String (`""`) and not `0`: https://stackoverflow.com/questions/23610509/exc-bad-access-when-building-nspredicate/27566124#27566124 – Larme Sep 28 '18 at 15:09

1 Answers1

3

You can simply compare to the empty String, "". The %@ placeholder represents a String, so the crash happens because you supply an Int to the NSPredicate instead of a String.

You should also use the %K placeholder for variable names instead of appending strings.

let predicate = NSPredicate(format: " %K != %@", remoteAttributes.lineOwner, "")

If you also want to filter out nil values, you can use a compound predicate:

let predicate = NSPredicate(format: " %K != %@ AND %K != nil", remoteAttributes.lineOwner, "")
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • 1
    The crash shouldn't appear because of/during the comparison, but rather in the construction of the `NSPredicate`, through the `String(format:)` because of a mismatch between the placeholder and the value for it. – Larme Sep 28 '18 at 15:10
  • This works, at least compiles and doesn't crash. The value I am getting back is a nil, not an empty string it seems. Tried substituting NULL and nil, neither work. – user3069232 Sep 28 '18 at 16:10
  • 1
    @user3069232 check my updated answer, that filters out `nil` values as well – Dávid Pásztor Sep 28 '18 at 16:13
  • Sorry David, that produces a runtime crash! With this error message -[__NSCFNumber rangeOfString:]: unrecognized selector sent to instance 0xbadd2041a6bcbead – user3069232 Sep 28 '18 at 16:19
  • 1
    @user3069232 are you sure `remoteAttributes.lineOwner` is `Optional` and can actually be `nil`? – Dávid Pásztor Sep 28 '18 at 16:21
  • I edited the question, and printed out the contents of the iCloud database. So I want the records with a lineOwnerfield only. – user3069232 Sep 28 '18 at 16:25
  • 1
    @user3069232 could you also add the definition of your class so that I can see against what data (type) should the predicate actually filter? – Dávid Pásztor Sep 28 '18 at 16:27
  • 1
    `-[__NSCFNumber rangeOfString:]: ` Wait. What is `remoteAttributes.lineOwner` exactly? Is a Number? It should be a `String` indicating the KeyPath of your object attributes. Could you show update your model in your question? – Larme Sep 28 '18 at 16:28
  • It is defined as a String, and as you can see in one of the values is set to "Yahoo". I want the record with "Yahoo" and I don't want the other one. – user3069232 Sep 28 '18 at 16:29
  • 2
    No, the value to construct the predicate. It has to be a String, your are misunderstanding how is constructed a `NSPredicate`. The first part is a key path, not a value. From the log, replace `remoteAttributes.lineOwner` with `"lineOwner"`. – Larme Sep 28 '18 at 16:30
  • I got this to work by making sure lineOwner field is created; and than use the original "" format suggested! THANKS guys!! – user3069232 Sep 28 '18 at 16:38