Hacking the iOS Interview

Swift — Structs and Classes — Part II

Shivam Pandey
Hash Coding
Published in
4 min readFeb 18, 2021

--

Swift struct vs class interview questions
Photo by Fotis Fotopoulos on Unsplash

In this post, I will continue with some advanced questions related to structs vs classes in Swift. These become important topics in the iOS interviews as if we are not careful using these, then this can unintentionally lead to memory leaks as well as crashes in the app.

In case you missed the previous part, you can find it here: Swift — Structs and Classes — Part I.

Explain the lifecycle of struct vs class in Swift?

Understanding the lifecycle of structs and particularly classes become very important as the interviewer can ask about those scenarios which can lead to unintentional performance bottlenecks and crashes in the app.

Structs

Structs are value types, and so they don’t have multiple owners and therefore their lifecycle is relatively easier to maintain. Their lifetime is bounded to the lifetime of the variable containing the struct. The struct’s memory will be freed when the variable goes out of scope.

Classes

Classes can have multiple owners, therefore Swift uses ARC to keep track of the number of references to a particular instance. The Swift runtime calls the object’s deinit when the reference count becomes zero and the memory is freed.

Explain strong reference cycles in Swift

Reference cycles occur when two objects hold strong references to each other, and because of which both the objects never get deallocated, and thus cause memory leaks. Structs do not face this problem because being value types, there are no references to structs. But while dealing with classes we need to be careful about creating unintentional reference cycles.
We can see the example of a strong reference cycle in the below example, where there is a Parent-Child relationship.

Parent-child relationship depicting reference cycle

You can be asked to write some code similar to the above example to show a scenario in which a reference cycle can happen.

In line 27 and 28 even after setting both parent and child to nil, the deinit’s of both the objects are not called denoting that there is a memory leak. This happens because the reference count of both parent and child never goes down to 0.

To solve this problem, Swift has provided us with two options —
weak and unowned.

Weak vs Unowned in Swift?

Explain weak references

In the above example, we can break the reference cycle by making the child’s reference to the parent as weak. Assigning an object to a weak variable doesn't change its reference count.

Weak references must always be optional as the variable will automatically be set to nil once the referred object gets deallocated. We can correct the above code by making the parent property in the Child class as weak.

Swift strong reference cycle example
Both the deinits are called when using weak reference

The weak references are generally used in delegate patterns in iOS.

Explain Unowned References

There can be certain situations where we want a non-strong reference that is not optional. For example, the child should always have a parent associated with it. Here, we can use the unowned keyword.

In the Child class, the parent reference has been changed to be unowned

When using unowned, we have to ensure that the parent outlives the child. If the parent gets deallocated before the child, and the unowned variable is tried to be accessed, the program will crash.

This is because the Swift runtime keeps a second reference count in the object to keep track of unowned references. When all the strong references are gone, the object will release all of its resources (for example, any references to other objects). However, the memory of the object itself will still be there until all unowned references are gone too. The memory is marked as invalid ( also called zombie memory), and any time we try to access an unowned reference, a runtime error will occur.

What to choose between unowned vs weak?

  • If we can ensure the parent is going to outlive the child, then we can choose the unowned reference. This will also give us the option to use that unowned reference as a let-constant as with weak reference we can only use an optional-var.
  • If we cannot guarantee the lifetime of both or either of the references then we should use a weak reference, as unowned can cause the program to crash if we try to access that reference that has no other strong reference attached to it.

These are the major concepts and questions which can be asked in interviews. For additional information, you can always refer to the official Swift documentation for structures and classes.

If you like the content, save it on medium and share it with your iOS community and help us reach a larger audience who could use this. You can appreciate it as well. Clap or Claps. 👏 👏

Get notified every time we post a new story to our publication. Follow us now

We are dedicated to our goal to help every iOS developer grow and give their best in the interview. Every week we’ll be coming up with newer topics. Don’t miss them. Signup Now. ✉️

--

--

Shivam Pandey
Hash Coding

Lead Engineer iOS @airtelxlabs | Editor: Hash Coding