Automatic Reference Counting (ARC) in class instances
Tags: swift, ios
Published: 2019-04-07 23:00:49

---
title: Automatic Reference Counting (ARC) in class instances
published: true
description: Track and manage your app's memory usage.
tags: swift, ios 
---

## An introduction to ARC

![Automatic Reference Counting Image](https://thepracticaldev.s3.amazonaws.com/i/mtohx0ju0k471p4myywx.png)

In [Swift language](https://developer.apple.com/swift/) memory management works out of the box and you don't need even to think about it yourself.

In this article i'll share the basic about ARC. ARC just works! It's frees up the memory used by your class instances when their no longer needed.

**By Apple words:**

  > Every time you create a new instance of a class, ARC allocates a chunk of memory to store information about instance. Addictionally, when an instance is no longer needed, ARC frees up the memory used by that instance so that the memory can be used for other purposes insted.

## Let's practice!!!

Let's see how this works with our previous music app idea example.

You have a `class` called `Artist`. We will play a little bit with code now.

```swift
class Artist {
	let name: String

	init(name: String) {
		self.name = name
		print("Artist \(name) is being initialized")
	}

	deinit {
		print("Artist \(name) is being deinitialized")
	}
}
```

We will now create an `Artist` instance and assign it to some variables.

```swift
var artist1: Artist?
var artist2: Artist?
var artist3: Artist?

artist1 = Artist(name: "Taylor Swift")

artist2 = artist1
artist3 = artist1

artist1 = nil
artist2 = nil
```

Because the instance in `artist3` it wasn't `nil`, `Artist` instance it's never deallocated. You can check this by seeing the number of `"Artist \(name) is being deinitialized"` printed in the result in your console. And this happens because there is now a strong reference from `artist1` to the new `Artist` instances. The third `strong reference` never was deallocated and so, the instance it's broken. So you need to change the line to `artist3 = nil` in order to fix the last strong reference.

Now lets learn about new references than `strong`, `weak` and `unowned`, by understanding how it's possible sometimes to have instance of a class that never gets to the point where it has zero `strong references` and this is known as `strong reference cycle`.

Here is where we defined some of our relationships between `class`es as `weak` or `unowned` insted of `strong references`.

## A practical example about weak.

We have one `class` called `Artist` and other called `Label`.
```swift
class Artist {
	let name: String
	var label: Label?

	init(name: String) {
		self.name = name
		print("Artist \(name) is being initialized")
	}

	deinit {
		print("Artist \(name) is being deinitialized")
	}
}
```

The second `class` called `Label`.

```swift
class Label {
	let name: String
	weak var artist: Artist?

	init(name: String) {
		self.name = name
		print("Label \(name) is being initialized")
	}

	deinit {
		print("Label \(name) is being deinitialized")
	}
}
```

Let's play with some `initialization`. Below is the result!

```swift
var artist: Artist?
var label: Label?

artist = Artist(name: "Taylor Swift")
label = Label(name: "Sonic Music")

artist!.label = label
label!.artist = artist

artist = nil
label = nil
```

As you can see, when we pass nil to both variables, the `strong reference` not drop to zero and the instance it's not deallocated. Neither `deinitializer` was called and nothing it's printed in console. This can cause memory leak and other problems to your apps. I see this happening a lot while people work with instances of `UITableView` delegate methods or when try to capture values inside `Clocure`s. We will expand more about these topics in future articles.

So, how we break this?

## weak weak weak!

In this case because we can have an `Artist` without a `Label` or `Label` without an `Artist`, it's possible to use `weak`reference. Because the lifetime of `Label` can finish first than the `Artist` in this context, we use `weak references`.

> We use `weak references` when the other instance has a shorter lifetime, this mean, when the other instance can be deallocated first.

In the previous example we just need to change our class by adding the `weak reference` before the `Artist` declaration.

```swift
weak var artist: Artist?
```

The `Artist` instance still has a `strong reference` to the `Label` instance, but the `Label` instance has now a `weak reference` to the `Artist` instance.

Now, if in our test we add `artist = nil`, we will see a different result in console and instances being deallocated. **Try yourself a litle bit!**

## So when to use the `unowned reference` then?!

We use it when the other instance has the same lifetime or longer lifetime.

In the below quick example, you can see two `class`es and understand their relationship. An `Artist` can have zero or more `Album`s but an `Album` can't exists without an `Artist`.

```swift
class Artist {
	let name: String
	var album: Album?

	init(name: String) {
		self.name = name
		print("Artist \(name) is being initialized")
	}

	deinit {
		print("Artist \(name) is being deinitialized")
	}
}
```

```swift
class Album {
	let title: String
	unowned let artist: Artist

	init(title: String, artist: Artist) {
		self.title = title
		self.artist = artist
		print("Album \(title), Artist \(artist.name) is being initialized")
	}

	deinit {
		print("Album \(title) is being deinitialized")
	}
}
```

This is a great scenario to use the `unowned reference`. Because an `Album` will always have an `Artist`, we use the `unowned reference` to avoid `strong reference cycle` in the defined property. You can just update the `Album` class with

```swift
unowned let artist: Artist
```

See some results and please try different inputs to test diferrent outputs to better understanding.

**Always check wether the `deinitializer` was called or not.**

```swift
var artist: Artist?
var album: Album?

artist = Artist(name: "Taylor Swift")
artist!.album = Album(title: "Fearless", artist: artist!)

artist = nil
```

**That's it.**

## Resources
While there is a lot to find on the internet about ARC, I mainly used the Apple Swift Book and it is very clear and complete.

- https://docs.swift.org/swift-book/

**I hope you enjoyed the post and if so, please follow me because more content will come soon. I'll write more about memory management in the next articles.**

Also consider following me on **[Twitter](http://twitter.com/amarildulucas)**? 😬 **@amarildulucas**

**Note:** Please, english isn't my native language, so feel free to send me any feedback about typos or anything.