问题
I try to filter some contacts from address book with a set of existing phone numbers. CNContactPickerViewController
should disable selection of these contacts when they have matching phone number from existing phone numbers.
I need to use phone number as a filter because these phone number can be from other app platforms. And the service should not allow user to use contact with same phone number that is already existed. I don't want to create my own contact picker for just this quick action.
Here is what I've tried so far.
NSArray<CNPhoneNumber *> *existingPhoneNumbers = @[@"1111", @"2222"];
CNContactPickerViewController *contactPicker = [[CNContactPickerViewController alloc] init];
contactPicker.delegate = self;
contactPicker.displayedPropertyKeys = @[CNContactNamePrefixKey,
CNContactGivenNameKey,
CNContactFamilyNameKey,
CNContactOrganizationNameKey,
CNContactPhoneNumbersKey];
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"NOT (ANY phoneNumbers.value.stringValue IN %@)", existingPhoneNumbers];
contactPicker.predicateForEnablingContact = predicates;
Error message:
[CNUI ERROR] Error when showing picker: Error Domain=CNErrorDomain Code=300 "(null)" UserInfo={CNValidationErrors=(
"Error Domain=CNErrorDomain Code=400 \"Invalid Predicate\" UserInfo={CNKeyPaths=(\n \"phoneNumbers.value.stringValue\"\n), NSLocalizedDescription=Invalid Predicate, NSLocalizedFailureReason=The operation couldn't be completed because its predicate is invalid.}")}
With SUBQUERY
it is still not working.
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(phoneNumbers, $CNLabeledValue,$CNLabeledValue.value.stringValue IN %@).@count == 0"];
Error message:
[CNUI ERROR] Error when showing picker: Error Domain=CNErrorDomain Code=300 "(null)" UserInfo={CNValidationErrors=(
"Error Domain=CNErrorDomain Code=400 \"Invalid Predicate\" UserInfo={CNKeyPaths=(\n \"value.stringValue\"\n), NSLocalizedDescription=Invalid Predicate, NSLocalizedFailureReason=The operation couldn't be completed because its predicate is invalid.}")}
Also tried with predicateWithBlock:
. It doesn't support block-based predicate at all.
From WWDC 2015 Introducing the Contacts Framework for iOS and OS X session.
They said predicateForEnablingContact
is evaluated on 'CNContact'. The document doesn't say that predicate must be from CNContact+Predicates
like CNContactFetchRequest
does.
回答1:
Already found the issue. My hair almost fell out when I encoutered this problem. The solution is to add apostrophe to value. Like this
let predicate = NSPredicate(format: "ANY self.phoneNumbers.'value'.'digits' BEGINSWITH %@", "+420"
I hope this helps you.
回答2:
I hope you've found the solution you were looking for. I'm going to share how I've dealt with this kind of issue. It may help others.
I wanted to limit the CNContactPickerViewController to show only contacts, let's say the only contacts(phone numbers) I have in a set. So basically, unlike your case, I wanted to show only existing users. So, In viewDidLoad...
let exsitingNumbers = Set(["1111", "2222"])
let predicate = NSPredicate(format: "SUBQUERY(phoneNumbers, $x, $x.'value'.'stringValue' IN %@).@count > 0", exsitingNumbers)
self.contactPicker.predicateForEnablingContact = predicate
For more details about SUBQUERY in NSPredicate, take a look at it.
来源:https://stackoverflow.com/questions/37481483/how-to-filter-contacts-using-a-set-of-phone-numbers-with-cncontactpickerviewcont