# \[Accepted\] SE-0261: Identifiable Protocol

**URL:** <https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358>\
**Category:** Announcements\
**Created:** [July 26, 2019, 10:38pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358 "2019-07-26T22:38:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [July 26, 2019, 10:38pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/1 "2019-07-26T22:38:39Z")

</div>

The review for [SE-0261](https://github.com/apple/swift-evolution/blob/master/proposals/0261-identifiable.md) has ended and the proposal has been [accepted](https://forums.swift.org/t/se-0261-identifiable-protocol/26602/184).

The proposal was positively received as addressing a common need for which a standard protocol is appropriate.

During review, there were some concerns about the use of the property `id`, with some preferring `identifier` to avoid clashes with existing properties, while others stated they would have the same problem with `id`. The core team feels that `id`, as the term of art, is the better choice. Future [language features](https://forums.swift.org/t/se-0261-identifiable-protocol/26602/166) should provide a path to resolve clashes.

The other concern raised was regarding the default implementation using `ObjectIdentifier` for classes. Some felt this would lead to issues since object identifiers can be re-used if stored beyond the lifetime of the object. The core team believes this is a specific case of a more general class of problem: that the protocol leaves the duration of the identity unspecified. Identities could be guaranteed always unique (UUIDs), persistently unique but only per environment (database record keys), per-process unique within limits (Combine's identifiers are like this), for the lifetime of the object (object identifiers) or just unique within the current collection. It is up to both the conformer and the receiver of the protocol to document the nature of the identity. There is future potential to refine the protocol further if other guarantees prove useful in future.

While providing a default implementation could lead to bugs from conformances where it isn't appropriate, the documentation will be clear on the default implementation's limitations, and encourage conformers to replace it with a more appropriate ID if one is available. As ever, to conform to a protocol you must read the documentation to ensure you understand the requirements. In this respect `Identifiable`'s default for classes is similar to `RandomAccessCollection`, which imposes no compile-time requirements over `BidirectionalCollection` but does require you adhere to other requirements.

Thanks to everyone for participating in the review, and to @anandabits and @kylemacomber for proposing this such that it can make it into the ABI for Swift 5.1.

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [August 1, 2019, 11:57am UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/2 "2019-08-01T11:57:30Z")

</div>

I am still concerned about the default implementation for classes.

> [@ben-cohen](#):
>
> The other concern raised was regarding the default implementation using `ObjectIdentifier` for classes. Some felt this would lead to issues since object identifiers can be re-used if stored beyond the lifetime of the object. The core team believes this is a specific case of a more general class of problem: that the protocol leaves the duration of the identity unspecified.

That is one way to look at the problem, but I think it is over-simplifying the issue.

The kind of identity we are talking about in this protocol is record identity - i.e. that you can have two _independent_ instances (of a class, struct or anything), with arbitrarily-different values for their fields, except for the `id` property. It remains stable when other properties change, allowing you to correlate those instances as referring to the same modelled 'thing'.

For instance, you might have two (or more) `Person` instances, with different surnames, say, but the same id/SSN because they refer to the same person.

In that context, a class's address is completely meaningless. You will never have two live instances with the same address, so they will never have the same `id`. The only case where the memory address would actually fit the semantics of record identity is when your model classes are universal singletons (only ever one instance per row, even across threads); and in that very rare case, you don't even need a stable `id` because all mutations will be visible via all references (because that's how classes work). This has nothing to do with lifetime. Again, I would encourage looking closely at `NSManagedObjectID` and how that type is used.

Taken together with the severe potential for confusion, I do not think this convenience pulls its weight. If there is some bizarre, rare data model where this actually makes sense, it is trivial to implement it yourself.

I would urge the core team to reconsider this aspect of the proposal.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [August 1, 2019, 1:22pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/3 "2019-08-01T13:22:58Z")

</div>

> [@Karl](#):
>
> The kind of identity we are talking about in this protocol is record identity

This is incorrect. The kind of identity is intentionally unspecified. Record identity is _often_ used with this protocol but it is also possible to use the protocol with other notions of identity, object identity being one. As a concrete example, I have already written some SwiftUI code that uses object identity, not record identity.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [August 1, 2019, 1:40pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/4 "2019-08-01T13:40:40Z")

</div>

> [@anandabits](#):
>
> This is incorrect. The kind of identity is intentionally unspecified. Record identity is _often_ used with this protocol but it is also possible to use the protocol with other notions of identity, object identity being one. As a concrete example, I have already written some SwiftUI code that uses object identity, not record identity.

Well now I am confused. I thought it had been well settled on the basis of the review discussion that this protocol was about record identity. If it is about intentionally unspecified identity, then what kinds of useful generic algorithms are enabled by a protocol that guarantees often-but-not-always-record-identity?

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [August 1, 2019, 2:03pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/5 "2019-08-01T14:03:13Z")

</div>

> [@anandabits](#):
>
> This is incorrect. The kind of identity is intentionally unspecified. Record identity is _often_ used with this protocol but it is also possible to use the protocol with other notions of identity, object identity being one. As a concrete example, I have already written some SwiftUI code that uses object identity, not record identity.

From the proposal:

> [@](#):
>
> Snapshots of a `Contact` , like `john` and `johnny` , refer to the same logical person, even though that person may change their name over time and at any moment, may share any number of other details with distinct persons. Being able to determine that two such snapshots belong to the same logical entity is a broadly useful capability.

So yes, in fact, it is absolutely about record identity and nothing else. To use that terminology, if the identity is the same as the memory address, there is no concept of having two "snapshots" with the same id (i.e. same memory address), but with different values. Again, that's not how classes work.

I mentioned that there is one pattern where the two are equivalent: in the case of singleton model instances, where every "logical entity" is represented by one, and only one, object. I'll bet $20 that that's what your "concrete example" is doing.

That's a very specific and rare pattern which does not justify having a default implementation for all classes. But if that is really what you want to do, I don't think it's too onerous to implement the single requirement yourself. Default implementations are a convenience, but this one just isn't.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [August 1, 2019, 3:44pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/6 "2019-08-01T15:44:22Z")

</div>

> [@Karl](#):
>
> That's a very specific and rare pattern which does not justify having a default implementation for all classes. But if that is really what you want to do, I don't think it's too onerous to implement the single requirement yourself. Default implementations are a convenience, but this one just isn't.

Maybe the ship has sailed. As the review rationale says:

> While providing a default implementation could lead to bugs from conformances where it isn't appropriate, the documentation will be clear on the default implementation's limitations, and encourage conformers to replace it with a more appropriate ID if one is available. As ever, to conform to a protocol you must read the documentation to ensure you understand the requirements.

But I also agree that the default implementation can lead to this nasty scenario:

1. User defines a record class that _should_ be identified from, say, its uuid property.
2. User adds Identifiable conformance and does not provide the customized id because the compiler does not require it.
3. The record class is now identified by instance instead of uuid.
4. The user injects those records into a tool that uses Identifiable in order to optimize some algorithm. It happens that this algorithm provides the same output despite the "wrong" implementation of Identifiable by our example record class. But the way to build the result is impacted. Consider, say, table view diff. Because of the "wrong" implementation of Identifiable, the diff may be bigger than necessary, leading to various unwanted side effects, from increased memory consumption to missed opportunities to reuse views.
5. Nothing warns the user that he sub-optimally uses the tool.

---

<div class="post-metadata">

**Author:** ![Jean-Daniel](https://avatars.discourse-cdn.com/v4/letter/j/977dab/32.png) [@Jean-Daniel](https://forums.swift.org/u/Jean-Daniel)\
**Post date:** [August 1, 2019, 3:56pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/7 "2019-08-01T15:56:55Z")

</div>

> [@Karl](#):
>
> In that context, a class's address is completely meaningless. You will never have two live instances with the same address, so they will never have the same `id` . The only case where the memory address would actually fit the semantics of record identity is when your model classes are universal singletons (only ever one instance per row, even across threads)

The identity must define a uniq record only in the context they are used. You may have as many instances representing the same record as long as they are not part of the same set of identifiable objects.

In such context, using the ObjectDescriptor as default value will not be an issue and will almost always be right.

If your record has a special meaning for Identity (SSN, …), there is no reason it uses the default implementation and expect the system to do the right thing. This is true for all protocols like Equatable.

---

<div class="post-metadata">

**Author:** ![gwendal.roue](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gwendal.roue/32/13992_2.png) [@gwendal.roue](https://forums.swift.org/u/gwendal.roue)\
**Post date:** [August 1, 2019, 4:02pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/8 "2019-08-01T16:02:35Z")

</div>

> [@Jean-Daniel](#):
>
> If your record has a special meaning for Identity (SSN, …), there is no reason it uses the default implementation and expect the system to do the right thing. This is true for all protocols like Equatable.

There is a difference between Identifiable and pervasive protocols like Equatable, though, so I'm not sure this reasoning is 100% valid.

That difference is that in many occasions, users will not declare Identifiable for their own consumption (where bugs are easily spotted - by tests or usage), but in order to feed tools that require Identifiable conformance (where bugs are much less easy to spot, as I tried to explain in my previous post).

Identifiable is not a fundamental protocol like Equatable and Hashable, but a convenience support protocol for algorithms that are often written by somebody else. There are consequences.

---

<div class="post-metadata">

**Author:** ![QuinceyMorris](https://avatars.discourse-cdn.com/v4/letter/q/d26b3c/32.png) [@QuinceyMorris](https://forums.swift.org/u/QuinceyMorris)\
**Post date:** [August 1, 2019, 4:12pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/9 "2019-08-01T16:12:51Z")

</div>

We could avoid having to, you know, _fight_ about this by simply withdrawing the default implementation for now, and letting the protocol stand on its own.

If, in the future, someone can make a case for the appropriateness of this — or another — default implementation, then there will naturally be a further proposal that can be discussed in light of actual experience.

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [August 2, 2019, 1:54am UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/10 "2019-08-02T01:54:15Z")

</div>

> [@xwu](#):
>
> I thought it had been well settled on the basis of the review discussion that this protocol was about record identity.

There was plenty of discussion of this in the review thread, but that semantic requirement was not proposed. Accepting a default implementation of `ObjectIdentifier` is not consistent with that semantics either, so I'm not sure why you would think it was settled in that manner.

> [@Karl](#):
>
> it is absolutely about record identity and nothing else

No it isn't. _The example you quoted_ is about record identity. But record identity was not proposed as a _semantic requirement_ of the protocol.

> [@gwendal.roue](#):
>
> the default implementation can lead to this nasty scenario

Default implementations are not bulletproof. They are a convenience. It is the responsibility of the author of the conforming type to provide a correct conformance.

The default in this case doesn't save a lot of code, but the implementation is somewhat non-obvious. There are many Swift programmers who haven't encountered `ObjectIdentifier` before.

I haven't seen any new arguments against it today and I don't think it's a good idea to re-litigate core team decisions without _at least_ bringing some new information, examples, or perspective to the table.

> [@xwu](#):
>
> what kinds of useful generic algorithms are enabled by a protocol that guarantees often-but-not-always-record-identity?

Here is an example of SwiftUI code that uses object identity instead of record identity. This is not how I would normally write SwiftUI code but it serves to demonstrate that SwiftUI's use of `Identifiable` does not depend on record identity. I don't see a compelling reason to prevent this example from being valid code.

```swift
final class Counter: Identifiable, ObservableObject {
    @Published var count = 0
    @Published private var child: Counter? = nil

    func presentChild() {
        precondition(child == nil)
        child = Counter()
    }
    var presentedChild: Binding<Counter?> {
        Binding(
            get: { self.child },
            set: {
                precondition(self.child != nil)
                precondition($0 == nil, "Presentation bindings should only ever set their value to nil")
                self.count += self.child!.count
                self.child = nil
            }
        )
    }
}

struct CounterView: View {
    @ObservedObject var counter = Counter()
    var body: some View {
        VStack {
            HStack {
                Text("\(self.counter.count)")
                Button("++", action: { self.counter.count += 1 })
            }
            Button("More", action: { self.counter.presentChild() })
        }
        .sheet(item: counter.presentedChild) {
            CounterView(counter: $0)
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![Mordil](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mordil/32/5840_2.png) [@Mordil](https://forums.swift.org/u/Mordil)\
**Post date:** [August 2, 2019, 2:50am UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/11 "2019-08-02T02:50:09Z")

</div>

> [@anandabits](#):
>
> Here is an example of SwiftUI code that uses object identity instead of record identity. This is not how I would normally write SwiftUI code but it serves to demonstrate that SwiftUI's use of `Identifiable` does not depend on record identity. I don't see a compelling reason to prevent this example from being valid code.

Because if I didn't follow SE-0261, I'd be sitting there scratching my head going "How is this object `Identifiable`? Is it by the `child`?" and then proceed to dig into `Identifiable`.

With `Equatable` it's easy to reason about what the potential compiler implementation would be without really knowing the semantics of the protocol.

It's about _clarity at the point of use_.

In addition, given Swift's ABI stability, I'd very much like to err on the side of being conservative on what we put into the stdlib.

> [@anandabits](#):
>
> I haven't seen any new arguments against it today and I don't think it's a good idea to re-litigate core team decisions without _at least_ bringing some new information, examples, or perspective to the table.

I do agree with this, though. Just thought I'd present a counter to your example.

---

<div class="post-metadata">

**Author:** ![trs](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/trs/32/2038_2.png) [@trs](https://forums.swift.org/u/trs)\
**Post date:** [August 2, 2019, 5:29am UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/12 "2019-08-02T05:29:05Z")

</div>

I also had the distinct impression that the overwhelming feedback regarding the default implementation was negative, e.g. [SE-0261: Identifiable Protocol - #35 by Lantua](https://forums.swift.org/t/se-0261-identifiable-protocol/26602/35)

It is unfortunate that this has been completely ignored and the proposal has not even been extended with these objections in the alternatives section.

Now stating that this was discussed but not proposed is a bit of a cyclic argument... it has certainly been proposed by the community.

I also don‘t understand the strong desire to keep this default implementation as weiting it for the rare cases where it is needed is trivial (I don‘t share the view that ObjectIdentifier is obscure knowledge).

---

<div class="post-metadata">

**Author:** ![anandabits](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anandabits/32/355_2.png) [@anandabits](https://forums.swift.org/u/anandabits)\
**Post date:** [August 2, 2019, 1:50pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/13 "2019-08-02T13:50:59Z")

</div>

> [@trs](#):
>
> It is unfortunate that this has been completely ignored and the proposal has not even been extended with these objections in the alternatives section.

The core team was able to consider this feedback and addressed it in the rationale for their decision.

> [@trs](#):
>
> I don‘t share the view that ObjectIdentifier is obscure knowledge

It's not exactly obscure (I didn't say it is), but it is definitely not common knowledge either.

---

<div class="post-metadata">

**Author:** ![nonsensery](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nonsensery/32/4317_2.png) [@nonsensery](https://forums.swift.org/u/nonsensery)\
**Post date:** [August 5, 2019, 5:34pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/14 "2019-08-05T17:34:07Z")

</div>

> [@ben-cohen](#):
>
> It is up to both the conformer and the receiver of the protocol to document the nature of the identity.  
> …  
> As ever, to conform to a protocol you must read the documentation to ensure you understand the requirements.

FWIW, when I read this, it feels like an argument _against_ having a default implementation.

The default implementation makes `Identifiable` conformance _mandatory_ for every class type, regardless of whether the author understands the requirements of the protocol.

* * *

On a separate note: One thing I really like about Swift is that the standard library doesn't "pollute" types with a bunch of properties/methods. In Swift, the author of a type is in complete control of what members that type has. I worry that the default `Identifiable` conformance, which adds an `id` property to _all_ class types, sets a bad precedent.

---

<div class="post-metadata">

**Author:** ![Lantua](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lantua/32/8868_2.png) [@Lantua](https://forums.swift.org/u/Lantua)\
**Post date:** [August 5, 2019, 5:35pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/15 "2019-08-05T17:35:45Z")

</div>

> [@nonsensery](#):
>
> The default implementation makes `Identifiable` conformance _mandatory_ for every class type

You still need to explicitly conform to `Identifiable` to get the default implementation, like `Equatable`.

---

<div class="post-metadata">

**Author:** ![nonsensery](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nonsensery/32/4317_2.png) [@nonsensery](https://forums.swift.org/u/nonsensery)\
**Post date:** [August 5, 2019, 5:38pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/16 "2019-08-05T17:38:43Z")

</div>

🤦‍♂️ Give me a minute to wipe the egg off my face 😬

---

<div class="post-metadata">

**Author:** ![svanimpe](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/svanimpe/32/38963_2.png) [@svanimpe](https://forums.swift.org/u/svanimpe)\
**Post date:** [August 9, 2019, 9:03am UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/17 "2019-08-09T09:03:36Z")

</div>

@ben-cohen

> [@ben-cohen](#):
>
> Some felt this would lead to issues since object identifiers can be re-used if stored beyond the lifetime of the object.

If reused identifiers are not an issue for default implementations, can I ask why there is no similar default implementation for `Equatable`?

```swift
extension Equatable where Self: AnyObject {
    
    static func ==(lhs: Self, rhs: Self) -> Bool {
         ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }
}

```

If objects are identical (object identity), they have the same state and therefore should also be equatable, no?

(Note that I'm not proposing we add this implementation, I'm only playing devil's advocate here)

---

<div class="post-metadata">

**Author:** ![Jean-Daniel](https://avatars.discourse-cdn.com/v4/letter/j/977dab/32.png) [@Jean-Daniel](https://forums.swift.org/u/Jean-Daniel)\
**Post date:** [August 9, 2019, 9:39pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/18 "2019-08-09T21:39:34Z")

</div>

Maybe because it was not possible to declare such conditional conformance when Equatable was introduced ?

---

<div class="post-metadata">

**Author:** ![David\_Sweeris](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/david_sweeris/32/31302_2.png) [@David\_Sweeris](https://forums.swift.org/u/David_Sweeris)\
**Post date:** [August 9, 2019, 10:59pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/19 "2019-08-09T22:59:07Z")

</div>

> [@svanimpe](#):
>
> ```swift
> extension Equatable where Self: AnyObject {
>     
> static func ==(lhs: Self, rhs: Self) -> Bool {
> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> }
> }
> 
> ```
> 
> If objects are identical (object identity), they have the same state and therefore should also be equatable, no?
> 
> (Note that I'm not proposing we add this implementation, I'm only playing devil's advocate here)

Probably because objects having the same identifier isn't the only way for them to be considered "equal". I mean, I'm aware of the arguments in favor of that approach, and I might even be convinced that in a vacuum it's the correct approach. It'd make Obj-C interop a real pain, though, since `class` doesn't have that semantic attached to it in Obj-C. If there was a `AnySwiftObject` constraint, it could be a _very_ interesting conversation.

---

<div class="post-metadata">

**Author:** ![Jon\_Shier](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jon_shier/32/921_2.png) [@Jon\_Shier](https://forums.swift.org/u/Jon_Shier)\
**Post date:** [August 9, 2019, 11:25pm UTC](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358/20 "2019-08-09T23:25:54Z")

</div>

> [@David\_Sweeris](#):
>
> It'd make Obj-C interop a real pain, though, since `class` doesn't have that semantic attached to it in Obj-C.

Doesn't it though? `objc1 == objc2` is evaluated using pointer equality, as is `[objc1 isEqual: objc2]`, AFAIK.

Personally, I prefer not having this default for `Equatable`, as it's almost never useful, and already covered by `===`.

[Next page](https://forums.swift.org/t/accepted-se-0261-identifiable-protocol/27358.md?page=2)
