Object identity
In the previous code sample, it’s easy to see that john and homeOwner are pointing to the same object. The code is short and both references are named variables.
What if you want to see if the value behind a variable is John?
You might think to check the value of firstName, but how would you know it’s the John you’re looking for and not an imposter? Or worse, what if John changed his name again?
In Swift, the === operator lets you check if the identity of one object is equal to the identity of another:
john === homeOwner // true
Jut as the == operator checks if two values are equal, the === identity operator compares the memory address of two references. It tells you whether the value of
the references are the same; that is, they point to the same block of data on the heap.
That means this === operator can tell the difference between the John you’re looking for and an imposter-John.
let imposterJohn = Person(firstName: "Johnny", lastName: "Appleseed")
john === homeOwner // true john === imposterJohn // false
imposterJohn === homeOwner // false
// Assignment of existing variables changes the instances the variables reference.
homeOwner = imposterJohn john === homeOwner // false
homeOwner = john
john === homeOwner // true
This can be particularly useful when you cannot rely on regular equality (==) to compare and identify objects you care about:
// Create fake, imposter Johns. Use === to see if any of these imposters are our real John.
var imposters = (0...100).map { _ in Person(firstName: "John", lastName: "Appleseed")
}
// Equality (==) is not effective when John cannot be identified by his name alone
imposters.contains {
$0.firstName == john.firstName &&
$0.lastName == john.lastName
}
By using the identity operator, you can verify that the references themselves are equal, and separate our real John from the crowd:
// Check to ensure the real John is not found among the imposters. imposters.contains {
$0 === john
} // false
// Now hide the "real" John somewhere among the imposters. John can now be found among the imposters
imposters.insert(john, at: Int(arc4random_uniform(100)))
imposters.contains {
$0 === john
} // true
// Since Person
is a reference type, you can use === to grab the real John out of the list of imposters and modify the value.
// The original john
variable will print the new last name! if let whereIsJohn = imposters.index(where: { $0 === john }) {
imposters[whereIsJohn].lastName = "Bananapeel"
}
john.fullName // John Bananapeel
You may actually find that you won’t use the identity operator === very much in your day-to-day Swift. What’s important is to understand what it does, and what it demonstrates about the properties of reference types.