In Objective-C, I'd sort an array of people as follows:
CFArraySortValues(mutablePeople,
CFRangeMake(0, CFArrayGetCount(mutablePeople)),
(CFComparatorFunction) ABPersonComparePeopleByName,
kABPersonSortByFirstName)
I'm struggling to figure out how to do the same in Swift. The following:
let ctx = UnsafeMutablePointer<Void>.alloc(kABPersonSortByFirstName)
CFArraySortValues(mutablePeople,
CFRangeMake(0, CFArrayGetCount(mutablePeople)),
ABPersonComparePeopleByName,
ctx)
Gives compilation error:
Cannot invoke 'CFArraySortValues' with an argument list of type '(CFMutableArray!, CFRange, (ABRecord!, ABRecord!, ABPersonSortOrdering) -> CFComparisonResult, UnsafeMutablePointer)'
The problem looks to be with the ABPersonComparePeopleByName
which would be cast to a CFComparatorFunction
in Objective-C.
Here are two alternatives that avoid CFArraySortValues
altogether:
Use ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering
to retrieve the contacts already sorted:
let people = ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, nil, ABPersonSortOrdering(kABPersonSortByFirstName)).takeRetainedValue() as [ABRecordRef]
If you use nil
for the source, it uses all sources (though that behavior is not documented).
Alternatively, if you have a Swift array of ABRecordRef
, you can then use the standard Swift sort routine, using ABPersonComparePeopleByName
for the comparison:
var people = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() as [ABRecordRef]
people.sort() { ABPersonComparePeopleByName($0, $1, ABPersonSortOrdering(kABPersonSortByFirstName)) != .CompareGreaterThan }
Both of these approaches return a Swift Array<ABRecordRef>
, which is a nice native Swift collection. For example, to print the list of the names:
for record in people {
let name = ABRecordCopyCompositeName(record).takeRetainedValue()
println(name)
}