Boxing to share data in Swift

Not a sport, sharing value types as reference types

As ever with more advanced features of Swift, some thought needs to go into whether this is the right feature for the situation you are currently seeing.

Value types are copied when an instance is copied, meaning that we don’t need to deal with references — making our code easy to debug. But what if we wanted to share a value type — that is deal with a reference to it in a specific situation, to share value types in several places in your App?

Welcome to boxing!

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

  • Be able to produce a “Hello, World!” iOS application (guide HERE)
  • Know when to use Class or Structs within your given situations (guide HERE)

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

Simple structs

Structs are value types which means that they are typically chosen over classes (which are reference types) as their use means code is likely to be easier to maintain as well as easier to debug.

Value types aren’t shared in several places in your App, rather they are copied. The following demonstration explains how a struct can be copied.

Using a Struct

One possible value type is a struct and we can store data within the properties of this data type

struct Person {
var name: String
var age: Int
}

and we can declare an individual person that

let steve = Person(name: "Steve", age: 22)

now this is, as mentioned above, a value type.

We can, therefore, create a copy of the struct and then change that struct without changing the original instance. This looks something like the following:

var secondSteve = steve
secondSteve.age = 33

When we print the two instances (steve and secondSteve) indeed do have different ages — 22 and 33 respectively.

print (steve) // Person(name: "Steve", age: 22)
print (secondSteve) // Person(name: "Steve", age: 33)

The mini-conclusion of this is that when we pass a value type around (view controllers or wherever) a copy is made — and we might not want our struct to have the properties of a value type — temporarily and in the situation where we want to share the Struct across an iOS app.

Using a Class container

Wrapping a Person within a Class would mean that you can share the Class (called below PersonBoxed) and it will be treated as a class (and by that, specifically we mean this will be treated as a reference type)

class PersonBoxed {
var person: Person
init(person: Person) {
self.person = person
}
}

Creating an instance of PersonBoxed can then be created and instantiated with the Person Struct:

let personBoxed = PersonBoxed(person: steve)

So as before we create a second instance of personBoxed and choose a different age for that person. It is a tricky to access the person within the box, and then the age within that box but the syntax should be fairly clear:

var secondPersonBoxed = personBoxed
secondPersonBoxed.person.age = 33

As we are using reference semantics this secondPersonBoxed actually points to the same instance

print (personBoxed.person) // Person(name: "Steve", age: 33)
print (secondPersonBoxed.person) // Person(name: "Steve", age: 33)

So indeed our Struct is now being teated as a Class, which is what might be expected as we wrapped our Struct into a Class. In terms of reference semantics, well it is this set of rules that are being followed.

Conclusion

Boxing essentially allows us to treat value types as reference types. The difference may seem rather technical and irrelevant to many programmers.

However, if you want to use reference semantics, and you might want to do that for a model in your application (for example — taking a copy of a model for each and every view controller would be a disaster), imagine having a simple switch that could enable reference semantics.

This is exactly it. We are enabling reference semantics on those value types that we choose; when and where we choose to do it.

Fantastico.

The code

This is quite short, so here is the whole playground copy-pasta to to this article in the form of a GIST:

Extend your knowledge

  • The Swift Evolution proposals for Data are proposed HERE

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