Use NSCopy() to Duplicate Objects in Swift

That is copy, not reference

Image for post
Image for post
Photo by Duy Pham on Unsplash

Copying objects (reference types) is quite often challenging. How are you supposed to make sure they copy properly if you are using Boxing?

Enter NSCopy()

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

  • Coding in Swift Playgrounds (guide HERE)
  • A good understanding of value and reference types (guide HERE)

This article leans rather substantially on my Boxing article, although the basics are repeated here. I’ve also assumed understanding of the equatable protocol.

Terminology

Boxing: The process of converting a value type to a reference type

Class: An object that defines properties and methods in common, using pass by reference semantics

Reference: A pointer to a variable or object

Reference type: A type that means instances have a single copy of data

Struct: An object defined in Swift, using pass by value semantics

Value: The something that would be stored in a variable

Value type: A type that means each instance has a copy of data

The Motivation

When you are using boxing to use reference semantics for a value type you risk coming unstuck — when copying objects. This can lead to rather difficult to identify bugs.

Want to go there? No? Read on…

For the means of this article I am creating a rather perfunctory PersonClass that conforms to the Equatable protocol. Yes, I know that two people with the same name aren’t necessarily the same person — but this is an example.

Our box is a class so works with reference semantics, and conforms to Equatable.

Our PersonStruct is going to go into a lightly sealed box.

The structBox then reference semantics have been brought to the Person Struct. Awesome.

Now what is happening in the code is creating a copy of the box using the (rather secretly added) copy method on box.

func copyBox() -> Box<T> {
let newElement = element
let newBox = Box(element: newElement)
return newBox
}

This takes our element, and places it into a new box (and then returns the box).

It all seems fine…but how is that element being copied?
Are we sure that it is using value semantics for the element? What if the underlying element type (represented by T) were a class?

Now you’re talking. To ensure this you would want to have a a protocol that guarantees you are copying all levels of your struct properly. NSCopying is just that protocol.

This involves a little bit of Protocol Composition, and of course updating our PersonStruct to conform to NSCopying.

then the box will conform to the same protocol (you see that the protocol means that we need to conform to it for each level of the class — great.)

Now we have adopted the NSCopying protocol so we can copy-me-do.

And each level of the class is adequately copied. Awesome!

The NSZone? Well, Apple say that you can ignore it. Ok, thanks Apple, I’ll do just that!

Conclusion

When you copy objects you need to be careful if all of the layers of the class are copied. If not you might be doing some sort of surface copy and have unwanted side-effects under the hood.

Do you want that?

No, no you don’t.

So I hope I’ve helped you out a little bit with the article above, explaining not just NSCopy() but NSZone and such good stuff in between.

Got a question? Just forward it to me on Twitter and I’ll get to it!

Extend your knowledge

  • I’ve a rather basic example around boxing that might be helpful to you

The Twitter contact:

Any questions? You can get in touch with me HERE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store