Currently I have this code :
if let myPhoneNumbers = person.phoneNumbers?.allObjects as? [PhoneNumber] {
for myPhoneNumber in myPhoneNumbers {
mainPhoneNumber = myPhoneNumber.number
break
}
}
Is this the correct way of coding this. I know that NSSet
is unordered and probably is the reason it does not have its own implementation of .first
such as:
person.phoneNumbers.first
But I'm thinking my code is not the most elegant code and maybe not proper Swift code.
In your code, myPhoneNumbers
is an array, so you could use myPhoneNumbers.first
instead of looping.
if let myPhoneNumbers = person.phoneNumbers?.allObjects as? [PhoneNumber] {
mainPhoneNumber = myPhoneNumbers.first
}
However, as has been pointed out, you should impose some sort of order on your set, so that the result of executing this code is the same for any given set. Arbitrary results are usually bad.
Since you mentioned you are using Core Data, I suggest adding a convenience property on your Person entity to return the phone numbers as a sorted array.
If your entities look something like this...
class PhoneNumber: NSManagedObject {
@NSManaged var number: String
}
class PersonEntity: NSManagedObject {
@NSManaged var phoneNumbers: NSSet?
}
...you could create a convenience property like this:
class PersonEntity: NSManagedObject {
@NSManaged var phoneNumbers: NSSet?
// Arrays are often easier to work with than sets,
// so provide a convenience property that returns
// phone numbers sorted
var phoneNumbersArray: [PhoneNumber] {
get {
if let phoneNumbers = phoneNumbers {
return (phoneNumbers.allObjects as! [PhoneNumber]).sorted() {
// here, sorting by phone number, but
// you can sort on whatever you want
$1.number > $0.number
}
}
// return empty array if set is nil
return [PhoneNumber]()
}
}
}
Finally, get the first number with one line of code like this:
mainPhoneNumber = person.phoneNumbersArray.first
I like to add this type of convenience array property to all my entities that have sets. Arrays are easier to work with, in my opinion. Here I chose to return an empty array instead of a nil array, when the set is nil. This works if you are OK with treating nil and empty phone sets the same.
Also note that .first
returns nil if phoneNumbersArray
is empty.