Reference Property inside a Struct in Swift

Boudhayan Biswas
Jun 11, 2019 ยท 4 min read

๐Ÿ’ฅ๐Ÿ’ฅ๐Ÿ’ฅA value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.๐Ÿ’ฅ๐Ÿ’ฅ๐Ÿ’ฅ

In Swift, we have to deal with both reference type and value type property. If the property is a pure value type or reference type, then we should not worry as everything works as per your expectation.๐Ÿค˜

But what if we mix those properties together?๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง What will happen? ๐Ÿง

Letโ€™s try to find out in this article.๐Ÿ”Ž

โœ… Value types can hold reference type property, and vice-versa is also true.โœ…

If you add a reference type property inside a value type, then you are not doing anything wrong or breaking anything related to rules or principles.๐Ÿ˜Ÿ

Donโ€™t get scared brother!!๐Ÿ˜”

If you add like that, then you are just making a value type with a property that has reference semantics. But

๐Ÿ˜ฑ๐Ÿ˜ฑ๐Ÿ˜ฑ A reference type will always be a reference type ๐Ÿ˜ฑ๐Ÿ˜ฑ๐Ÿ˜ฑ

Now you can be sure that a reference type of property will always behave like a reference type. ๐Ÿค˜

Reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used.๐Ÿ’โ€โ™‚๏ธ

So now I am confused!! ๐Ÿ˜ข If reference type does not change behaviour though it is inside a value type, then what is going to happen?๐Ÿ˜ณ๐Ÿ˜ณ

Letโ€™s take a simple example and try to find what will be the behaviour and is there any way we can change that behaviour?๐Ÿ˜Ž

Company is reference type and Employee is value type. Employee contains one reference type property employer inside it.

In the above after creating instances of Employee , we have written below the line

gary.employer = peter.employer

gary.employer and peter.employer are pointing to the same object in the memory. So if we print for both the instances, they print Facebook which is perfect.

Now, letโ€™s tweak gary and change the โžก๏ธ = "Google"

When we print for peter and gary , they print Google . So they are behaving like reference types as a change in one instance is reflecting into another. We can assume that they are somehow connected to each other๐Ÿค”

print( //prints "Google"
print( //prints "Google"

No wonder, this is the classic behaviour of reference type and this is exactly how it should be.๐Ÿ’ช๐Ÿ’ช๐Ÿ’ช

So if a value type contains reference type property, then the reference type property always behaves like a reference type. But we may want them to behave like value type because they are inside a value type. ๐ŸŽฏ

Yes!!! You have to behave like a value type. ๐Ÿ˜ก๐Ÿ˜ก๐Ÿ˜ก๐Ÿ˜ก

You are living inside a value type, so you have to behave also like same.๐Ÿ˜ก๐Ÿ˜ก

Letโ€™s try to find a solution for this

Before jumping into the solution, letโ€™s get some information about a very special function in Swift๐Ÿ˜Ž

func isKnownUniquelyReferenced<T>(_ object: inout T?) -> Bool where T : AnyObject

This function returns a Boolean value depending upon whether the object has a single strong reference. So if your object has only one strong reference then it returns true โœ… otherwise false โŽ.

Letโ€™s get back to the main problem

If we simply write peter.employer.copy() then it throws compile time error Company has no member copy. To support copy feature in the existing Company class, letโ€™s change the implementation a little bit and adopt NSCopying protocol๐Ÿคฉ

This is not the end, we have to do a little more changes in the Employee struct.๐Ÿ˜ฉ

First, we have introduced a new _employer variable which is private variable. We will use this variable inside the initializer and getter. We have also declared one computed property employer of type Company which has a mutating getter & setter ๐Ÿ˜Ÿ.

Why do we need to implement getter method as mutating getter ?๐Ÿค”๐Ÿค”

Because Employee is a struct and _employer is a stored property of the struct, we are changing the value of _employer inside the getter, that is why the getter is mutating .

But we have added a special checking inside mutating getter. What is that?๐Ÿ˜ณ

That is a simple check to identify if there is more than one strong reference for _employer , if exists then we are making a copy of _employer and assigning it to the _employer which a completely new object in the memory. ๐Ÿ˜ฒ ๐Ÿ˜ฒ ๐Ÿ˜ฒ

If there is only one strong reference for _employer then simply we are returning _employer without doing any changes. ๐Ÿคซ๐Ÿคซ๐Ÿคซ

Now letโ€™s print the employer name for peter & gary

print( //prints "Facebook"
print( //prints "Google"

Cool!! ๐Ÿ˜Ž๐Ÿค˜ It prints two different employerโ€™s name for two different instances. This time changes in employer is not reflecting into otherโ€™s employer .

At last, breathe a sigh of relief๐Ÿ˜

So employer behaves just like a value type though internally it is a reference type. Every time we change it goes through the mutating getter and finds that it is not uniquely referenced at all that means it has more than one strong reference, so it takes a copy of _employer before moving forward and returns that copied _employer โœŒ๏ธ

๐Ÿ™๐Ÿ™๐Ÿ™Thank you for reading!!๐Ÿ™๐Ÿ™๐Ÿ™

Swift India

Boudhayan Biswas

Written by

Swift Developer. In love with Python & Machine Learning.

Swift India

Swift Developer Community in India ๐Ÿ‡ฎ๐Ÿ‡ณ

More From Medium

More from Swift India

More from Swift India

Functional Swift: Closures { }

Jun 27, 2018 ยท 7 min read


More from Swift India

More from Swift India

More from Swift India

Learn about Struct in Swift

May 20, 2018 ยท 4 min read


Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and weโ€™ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium โ€” and support writers while youโ€™re at it. Just $5/month. Upgrade