2

I'm looking to use predicateForEnablingContact inside a CNContactPickerViewController to only enable contacts that have phoneNumbers that match the following regular expression ^\\+1[2-9]\\d{9}$.

This will mean looking at a contacts phoneNumbers and checking to see if at least one or more matches the following expression.

I started small by using the following trying to following the NSPredicate docs here:

let predicate = NSPredicate(format: "ANY self.phoneNumbers.'value'.'stringValue' BEGINSWITH %@", "1111")
contactPicker.predicateForEnablingContact = predicate

However, I'm unable to get past this part. I always seem to get the following error in my logs when running:

2023-06-11 21:31:15.703957+0100 Test2[9610:702640] [CNUI ERROR] Error when showing picker: Error Domain=CNErrorDomain Code=300 "(null)" UserInfo={CNValidationErrors=(
"Error Domain=CNErrorDomain Code=400 \"Invalid Predicate\" UserInfo={NSLocalizedDescription=Invalid Predicate, NSLocalizedFailureReason=The operation couldn\U2019t be completed because its predicate is invalid.}"

Does anyone have any ideas as to how I'd write a NSPredicate that matches the ruleset above please?

Edit:

I have also tried using

NSPredicate(format: "phoneNumbers.@count > 0 AND SUBQUERY(phoneNumbers, $phoneNumber, $phoneNumber.value.stringValue != nil).@count > 0"` 

But get the following...

predicate is invalid., CNKeyPaths=(\n \"value.stringValue\"\n)}"
Fudgey
  • 3,793
  • 7
  • 32
  • 53
  • 1
    This is odd. If you have an `NSArray` of `CNContact`, then using `array.filtered(using: predicate)` where `predicate` is `NSPredicate(format: "SUBQUERY(phoneNumbers, $phoneNumber, $phoneNumber.value.stringValue CONTAINS %@).@count > 0", "555")` then you get the correct results. But the same predicate for `predicateForEnablingContact` yields the frustrating "The operation couldn\U2019t be completed because its predicate is invalid." message you are seeing. – HangarRash Jun 15 '23 at 03:45
  • @HangarRash Nice idea to try using array.filtered - although the fact the same predicate works there but not on the contact picker makes me even more confused now… – Fudgey Jun 16 '23 at 22:38
  • 1
    What's really strange is that you can't use, for example, `CNContact.predicateForContacts(matching:)` with `predicateForEnablingContact`. The contact picker won't even appear. So it seems that the contact picker is doing some really strange non-standard stuff with the predicate you give it. – HangarRash Jun 16 '23 at 22:58
  • 1
    Try this - let phoneNumberRegex = "^\\+1[2-9]\\d{9}$" let predicate = NSPredicate(format: "SUBQUERY(phoneNumbers, $phoneNumber, $phoneNumber.value.stringValue MATCHES %@).@count > 0", phoneNumberRegex) contactPicker.predicateForEnablingContact = predicate – teja_D Jun 19 '23 at 07:09
  • Thanks @teja_D, unfortunately with that example I still get the predicate as invalid: `Code=400 \"Invalid Predicate\" UserInfo={NSLocalizedDescription=Invalid Predicate, NSLocalizedFailureReason=The operation couldn\U2019t be completed because its predicate is invalid., CNKeyPaths=(\n \"value.stringValue\"\n)}` The documentation simply references NSPredicate (and there's no indication that this is a special case) so why would it be seen as invalid when passed to the picker ...really confusing. – Fudgey Jun 19 '23 at 18:29

0 Answers0