I came across the NSCopying attribute when working with URLSession and URLSessionConfiguration.

From first glance I would expect any value that is prefixed with the @NSCopying attribute to return a new copy and any changes would not affect the initial value. Although that does work in theory, there is a scenario where this can be a little confusing.

To start off with, let me explain how @NSCopying works, with URLSessionConfiguration in URLSession.

Swift

URLSession has a variable called config, which is of type URLSessionConfiguration. Unlike all other variables within URLSession, configuration is prefixed with @NCopying. This stops you from changing a configuration which is already tied to a session. For example

Swift

So far this is exactly what we would expect to happen. A new copy of configuration is returned when we retrieve the value.

I thought I would then start to use this for my own classes so I started to write the code.

Swift

So if we apply the same logic that we did with URLSessionConfiguration, you will see where the confusion lies.

Swift

Well that is confusing. In the URLSessionConfiguration example the object was copied, however when creating a custom class which has a variable prefixed with @NSCopying the value is not copied, and we are just returned the original. I found this very confusing, but after some research online and trying to figure out why, I finally found where the issues lies.

When you assign a value in swift through an initialiser, it sets the value directly, and does not go though the setter. Unlike Objective C, where you have the option to go through the setter when initialising. This means that when we set the value, it never goes through the setter, and the value is never copied.

There is currently a swift proposal open with a proposed fix so I recommenced taking a look.

Proposal 153 – Compensate for the inconsistency of @NSCopying‘s behaviour