How to use weak self in Swift | Continued Learning #18

Swiftful Thinking
18 Apr 202120:33

Summary

TLDRIn this educational video, Nick from Swiftly Thinking dives into the concept of 'weak self' in Swift programming, a crucial topic often overlooked in beginner courses. He explains the importance of understanding Automatic Reference Counting (ARC) for efficient app development. Through a practical example, Nick illustrates how to avoid creating strong references that can lead to memory issues, especially during asynchronous tasks like internet data downloads. He emphasizes the use of 'weak self' to allow classes to de-initialize properly, ensuring app efficiency and performance.

Takeaways

  • πŸ“š The video is an educational resource on 'Swiftly Thinking', focusing on Swift and SwiftUI development.
  • πŸ”‘ The main topic of the video is 'weak self', explaining its importance in Swift development, especially with asynchronous tasks.
  • πŸ€” The concept of 'weak self' is often overlooked in beginner courses and can lead to memory inefficiencies if not properly understood.
  • πŸ”„ 'Automatic Reference Counting (ARC)' is fundamental to understanding 'weak self', as it manages the lifetime of objects in Swift.
  • πŸ“‰ Keeping the reference count low improves app efficiency and performance by allowing de-initialization of objects not in use.
  • πŸ”— 'Weak self' is used to prevent strong reference cycles, which can occur when asynchronous tasks are performed and the object should not stay alive.
  • πŸ‘ The presenter, Nick, emphasizes the importance of 'weak self' for efficient app development and to avoid memory leaks.
  • πŸ› οΈ The video provides a practical example of creating a navigation view with two screens to demonstrate the use of 'weak self'.
  • πŸ“ It illustrates the use of 'weak self' in the context of a ViewModel to handle data asynchronously without retaining a strong reference to the view.
  • ⏱️ A simulated long task is used to show how 'weak self' allows a view to de-initialize even when an asynchronous task is pending.
  • πŸ”‘ The video concludes with the advice to use 'weak self' in asynchronous operations to maintain app efficiency and prevent slowdowns.

Q & A

  • What is the main topic of the video?

    -The main topic of the video is explaining the concept of 'weak self' in the context of Swift programming, particularly when dealing with asynchronous tasks and automatic reference counting (ARC).

  • Why is understanding ARC important for app development?

    -Understanding ARC is important for app development because it helps manage memory efficiently, making the app run faster and more smoothly by keeping the reference count of objects as low as possible.

  • What is a strong reference in the context of ARC?

    -A strong reference in ARC is a regular reference to an object that keeps the object alive in memory. It prevents the object from being de-initialized until the reference is removed or the object is no longer needed.

  • What is the purpose of using 'weak self' in Swift?

    -The purpose of using 'weak self' in Swift is to create a weak reference to the current class or object, allowing it to be de-initialized when it's no longer in use, which helps prevent memory leaks and improve app efficiency.

  • Why is 'weak self' particularly important when downloading data from the internet?

    -'Weak self' is particularly important when downloading data from the internet because it ensures that the memory associated with the current screen or view can be freed up if the user navigates away while the download is in progress.

  • What does the term 'de-initialize' mean in the context of this video?

    -In the context of this video, 'de-initialize' refers to the process where an object or screen is removed from memory when it's no longer needed or when the user navigates away from it.

  • How does the video demonstrate the use of 'weak self'?

    -The video demonstrates the use of 'weak self' by creating a simple app with two screens and a view model, then simulating a long-running task to show how 'weak self' allows the app to de-initialize objects that are no longer in use.

  • What is the potential issue with using 'self.' instead of 'weak self' in asynchronous tasks?

    -The potential issue with using 'self.' instead of 'weak self' in asynchronous tasks is that it creates a strong reference to the current class or object, preventing it from being de-initialized until the task is completed, which can lead to increased memory usage and decreased app performance.

  • How does the video simulate a long-running task?

    -The video simulates a long-running task by using a delay within a DispatchQueue.main.async block, setting it to 500 seconds, to mimic the time it might take to download data from the internet.

  • What is the significance of the 'count' variable in the app's user interface?

    -The 'count' variable in the app's user interface is used to track the number of view models that have been initialized. It helps visualize the impact of using 'weak self' versus 'self.' on the number of objects kept in memory.

Outlines

00:00

πŸ“š Introduction to 'Weak Self' in Swift

Nick, the host of 'Swiftly Thinking', introduces the concept of 'weak self' in Swift programming. He emphasizes its importance, especially for beginners, which is often overlooked in learning materials. The video aims to clarify what 'weak self' means and its role in app development. The explanation begins with Automatic Reference Counting (ARC), discussing how it manages object references for efficiency. Nick illustrates the issue of inadvertently creating strong references that prevent screen de-initialization, which 'weak self' helps to resolve. The tutorial is set to prepare viewers for upcoming videos on downloading data from the internet, where understanding 'weak self' is crucial.

05:01

πŸ›  Building a Navigation View with 'Weak Self'

The tutorial proceeds to a practical demonstration within Xcode, creating a simple navigation view with two screens. Nick guides viewers through setting up a 'SwiftUI View' and a 'ViewModel' for the second screen, which conforms to the 'ObservableObject' protocol. He explains the significance of the 'init' and 'deinit' methods in the lifecycle of a view. The example serves to show how 'weak self' can be implemented in a real-world scenario, with a focus on the ViewModel's role in handling data asynchronously.

10:03

πŸ”„ Simulating Asynchronous Tasks and 'Weak Self'

Nick simulates a long-running asynchronous task using a delay to mimic downloading data from the internet. He demonstrates the problem of creating strong references to 'self' within closures, which can prevent the de-initialization of a view. This results in increased memory usage and potential performance issues. The example shows how the count of initialized views increases without de-initializing, highlighting the inefficiency caused by not using 'weak self'.

15:03

πŸ”‘ Solving Memory Issues with 'Weak Self'

The solution to the memory issue is presented by modifying the closure to use 'weak self' instead of 'self'. This change allows the system to de-initialize the view even when asynchronous tasks are running, preventing memory leaks and improving app performance. Nick shows how this adjustment keeps the count of initialized views stable, even when navigating back and forth between screens, demonstrating the efficiency of using 'weak self' in asynchronous operations.

20:04

πŸŽ“ Conclusion on the Importance of 'Weak Self'

In conclusion, Nick wraps up the tutorial by reiterating the importance of using 'weak self' in Swift development, especially when dealing with asynchronous tasks like internet data downloads. He emphasizes that understanding and correctly implementing 'weak self' can lead to more efficient and professional code, preventing unnecessary memory usage and keeping the app running smoothly.

Mindmap

Keywords

πŸ’‘Weak Self

Weak self is a concept in Swift programming used to prevent strong reference cycles, particularly in closures. In the context of the video, weak self is crucial when dealing with asynchronous tasks that might take a long time to complete, such as downloading data from the internet. By using 'weak self', the presenter demonstrates how to allow a view controller to be de-initialized even if there are still ongoing tasks. This prevents memory leaks and ensures the app remains efficient. The script uses 'weak self' in the example where a long task is simulated with a delay, and it's shown that without 'weak self', the view controller stays alive unnecessarily.

πŸ’‘Automatic Reference Counting (ARC)

Automatic Reference Counting is a memory management feature in Swift that automatically handles the memory lifecycle of objects. It keeps a count of references to an object and deallocates it when the count reaches zero. The video explains that understanding ARC is fundamental to grasping why weak references, like 'weak self', are necessary. ARC is mentioned as the system that holds references to objects, and the video emphasizes the importance of keeping this count as low as possible for app efficiency.

πŸ’‘Strong Reference

A strong reference is a relationship between two objects in Swift where the first object maintains a reference to the second, preventing it from being deallocated. In the video, the presenter explains that creating a strong reference to a screen or object can prevent it from de-initializing when it's no longer needed, which can lead to inefficiency and memory issues. The script illustrates this with an example where a strong reference to 'self' in a closure causes the view model to stay alive unnecessarily.

πŸ’‘De-initialize

De-initialization in Swift refers to the process of cleaning up an object's resources when it's no longer needed. The video uses the term in the context of view controllers and screens that are no longer visible to the user. The script demonstrates that without proper management of references, such as using 'weak self', de-initialization might not occur as expected, leading to increased memory usage and potential performance issues.

πŸ’‘Swift UI

Swift UI is a framework for building user interfaces across all Apple platforms. It's mentioned in the video as the environment in which the coding examples are being developed. The script uses Swift UI to create views and navigation between them, showcasing the practical application of concepts like 'weak self' in building efficient and responsive user interfaces.

πŸ’‘ViewModel

A ViewModel is a design pattern often used in app development to separate the UI from the business logic. In the video, the presenter creates a ViewModel to handle data for a screen. The ViewModel is used to demonstrate how 'weak self' can prevent memory leaks when asynchronous tasks are involved. The script shows the ViewModel being initialized and de-initialized as the user navigates between screens.

πŸ’‘Closure

A closure in Swift is a self-contained block of functionality that can be passed around and used in the code. They can capture and store references to any constants and variables from the context in which they are defined. The video discusses how closures can create strong references to 'self' if not handled properly, leading to memory leaks. The script includes an example where a closure is used to simulate a long-running task, and 'weak self' is introduced to prevent strong reference issues.

πŸ’‘Dispatch Queue

A dispatch queue in Swift is a concept used for managing the execution of tasks in a concurrent program. The video mentions the use of 'DispatchQueue.global.async' for simulating long-running tasks, such as network requests. The script uses dispatch queues to demonstrate how tasks that take a significant amount of time can prevent view controllers from de-initializing if 'weak self' is not used.

πŸ’‘Navigation View

A navigation view in Swift UI is used to manage the navigation hierarchy of an app, allowing users to move between different views or screens. The video script describes creating a navigation view and adding a navigation link to it. This is part of setting up the example app to demonstrate the concepts of 'weak self' and de-initialization in the context of user navigation.

πŸ’‘Observable Object

An Observable Object in Swift UI is a class or struct that can notify the system when its properties change, allowing the UI to update automatically. The video script includes the creation of a ViewModel that conforms to 'ObservableObject', which is used to manage data and update the UI in response to changes. This concept is integral to the reactive programming model used in Swift UI.

πŸ’‘User Defaults

User Defaults is a mechanism in iOS for storing small amounts of data, such as user preferences. In the video, the presenter uses 'UserDefaults' to track the number of initialized view models as a way to demonstrate the impact of 'weak self' on memory management. The script shows how 'UserDefaults' can be accessed and modified to reflect changes in the app's state.

Highlights

Introduction to 'weak self' concept in Swift programming.

Explanation of why 'weak self' is crucial for efficient app development.

Overview of Automatic Reference Counting (ARC) in Swift.

Importance of minimizing reference count for app efficiency.

Discussion on the unintended creation of strong references in app development.

Solution to strong reference issues by using 'weak self'.

Upcoming tutorial on downloading data from the internet and its relation to 'weak self'.

Creating a 'Weak Self Boot Camp' project in Xcode.

Explanation of Navigation View and its setup in Swift.

Demonstration of creating a simple two-screen navigation app.

Introduction of ViewModel and its role in app architecture.

Explanation of 'init' and 'dinit' functions in ViewModel.

Integration of ViewModel with the 'Second View' in the app.

Simulating the impact of asynchronous tasks on app memory.

Illustration of memory inefficiency with strong references during async tasks.

Implementation of 'weak self' to allow de-initialization during long tasks.

Demonstration of efficient memory management with 'weak self'.

Highlighting the professional use of 'weak self' in asynchronous operations.

Conclusion on the importance of 'weak self' for efficient and professional app development.

Transcripts

play00:01

[Music]

play00:07

what's up everyone

play00:08

welcome back i'm nick this channel is

play00:10

swiftly thinking where we cover all

play00:12

things

play00:12

swift and swift ui related and in this

play00:15

exciting video

play00:16

we're going to look at weak self we're

play00:18

going to learn

play00:19

what exactly weak self means and why we

play00:22

use it

play00:23

and i'm super excited to share this

play00:25

because this is something that i

play00:26

wish someone had stressed and explained

play00:29

to me more

play00:30

when i was learning app development it's

play00:32

often overlooked as people start to

play00:34

learn app development

play00:35

and a lot of beginner courses don't even

play00:37

touch on it but it is

play00:39

very important in order to get into

play00:41

excel we first have to understand

play00:43

automatic reference counting and you can

play00:46

google this

play00:46

arc automatic reference counting and

play00:49

apple probably has a bunch of articles

play00:50

on exactly what it is

play00:52

but basically every time you make an

play00:54

object or a screen

play00:56

the system is holding a reference to

play00:59

that object

play01:00

so reference counting by itself is

play01:01

pretty simple

play01:03

but as developers we want to keep this

play01:05

count as low as possible

play01:06

because it makes our app more efficient

play01:08

and faster and often times in your app

play01:11

when users are moving around the app

play01:13

behind the scenes

play01:14

the app is actually de-initializing

play01:17

screens and views

play01:18

that the user is no longer using so this

play01:21

is efficient so if they go to the screen

play01:22

and then

play01:23

press it back that screen might get

play01:25

de-initialized so any objects that were

play01:27

created on that screen

play01:28

would then be removed from our account

play01:31

and this is great

play01:32

but sometimes in our app we end up

play01:34

writing code

play01:35

that doesn't allow that screen to

play01:37

de-initialize when we actually want it

play01:39

to

play01:40

and you might not even realize you're

play01:42

doing this but you basically are

play01:43

creating a

play01:44

strong reference to that screen or that

play01:47

object

play01:48

and the solution is to basically create

play01:51

a weak reference instead of a strong

play01:52

reference

play01:53

and that's kind of what weak self is now

play01:56

i'm covering it right now because in the

play01:58

next bunch of videos

play01:59

we're going to start downloading data

play02:01

from the internet because

play02:02

when we have these functions that are

play02:04

going to the internet and then coming

play02:06

back

play02:07

it becomes super important to understand

play02:09

these strong and weak references

play02:11

and you're probably going to want to use

play02:12

a weak self a lot of times

play02:14

so i hope this doesn't get too confusing

play02:16

for some of you guys leave a comment

play02:18

below if you are still confused

play02:19

but i think the example we're going

play02:20

gonna go through uh really helps to

play02:22

explain it

play02:23

all right and if you are enjoying this

play02:25

content please don't forget to hit the

play02:27

like button and the subscribe button to

play02:29

stay up to date with all of these videos

play02:31

and this playlist

play02:34

all right welcome back everyone i'm back

play02:37

in xcode as always

play02:39

in this video we're looking at the week

play02:41

self call

play02:42

and we're going to do that in a new file

play02:44

so let's right click on the navigator

play02:46

create a new file

play02:49

it's going to be a swift ui view and

play02:50

let's call this week

play02:52

self boot camp go ahead and click create

play02:57

once you're inside click resume on the

play03:00

canvas

play03:01

and this again is something that i wish

play03:03

someone had talked to me a little more

play03:04

about when i was learning to code

play03:06

because

play03:07

because this is very important when you

play03:08

actually make applications

play03:10

and i don't think a lot of beginners

play03:12

even think about

play03:13

something like this so some of what

play03:15

we're doing here is a little bit

play03:16

abstract

play03:17

so i try to find the simplest way to

play03:19

explain this to you guys

play03:21

and what we're going to do is create a

play03:23

navigation view on our screen

play03:25

we'll add a navigation view open the

play03:28

brackets inside the navigation view

play03:30

is going to be a very simple navigation

play03:32

link

play03:33

open the parentheses we're going to use

play03:35

the uh let's use the

play03:38

string protocol and destination the

play03:41

title will say

play03:42

maybe navigate nothing important

play03:46

here and then the destination we're

play03:47

going to change in a second

play03:49

but let's just make it a text right now

play03:51

with a blank string

play03:52

and let's create a second screen here so

play03:54

underneath this struct

play03:56

i'm going to create a new struct let's

play03:59

call it weak

play04:00

self second screen

play04:04

it will conform to view just like our

play04:06

main view

play04:07

and every view needs a body and we'll

play04:09

open the brackets

play04:11

the body here is gonna be very simple

play04:12

just gonna be a text that says second

play04:14

view let's give it a font of large title

play04:17

and a foreground color of

play04:19

red let's add this into our destination

play04:23

so we'll do weak

play04:24

self second screen

play04:28

let's click resume in the canvas just to

play04:29

make sure it all works

play04:31

let's also add a navigation title here

play04:34

screen one all right so on screen one

play04:38

we can press play here on the sim

play04:41

on the canvas click navigate and it

play04:43

should bring us to the second view

play04:46

alright so this is a very simple app if

play04:48

you're confused at this point

play04:50

you should probably go check out some

play04:51

more beginner videos on my

play04:53

youtube channel because this should not

play04:55

be anything new to you guys this should

play04:56

be very simple

play04:57

we have two screens in a navigation view

play04:59

we can navigate

play05:00

we can press back and here we are all

play05:04

right

play05:04

this second screen is going to have a

play05:06

view model so we're going to create

play05:07

that now we'll do it underneath this

play05:09

struct we'll say

play05:11

class let's call it weak

play05:14

self second screen

play05:18

view model i know it's really long to

play05:21

type here

play05:22

the name doesn't really matter let's

play05:23

make it conform to observable object as

play05:26

always

play05:26

open the brackets and we're going to

play05:28

create a at published in here

play05:31

this will be a var we'll call it data

play05:34

and it'll be of type a string we're

play05:37

going to make it optional with a

play05:38

question mark

play05:38

we're going to set it equal to nil for

play05:40

now

play05:42

inside this view model we're then going

play05:43

to create an init

play05:45

open and close parentheses open the

play05:46

brackets in this init

play05:49

let's print out initialize now

play05:53

and we're going to call function to get

play05:55

data so let's create a func

play05:56

get data open close parenthesis open the

play05:58

brackets

play06:00

from in the init we'll call get data so

play06:03

as soon as it loads

play06:04

and in get data we're just going to call

play06:07

uh data equals new data

play06:12

before we leave here let's also create a

play06:14

d init

play06:15

which is pretty much the opposite of an

play06:17

init this happens when the screen gets

play06:19

initialized

play06:20

this happens when the screen gets

play06:21

de-initialized and let's just print

play06:24

here we'll print d initialize

play06:27

now all right

play06:30

the last thing i actually want to do is

play06:32

put this data this string

play06:35

onto the second screen so on the second

play06:38

screen

play06:38

let's first add the view model we'll do

play06:40

in at

play06:42

state object var vm for view model

play06:45

equals the weak self second screen view

play06:49

model

play06:51

and let's hold the command button click

play06:53

on this text

play06:54

let's embed it in a v stack and below

play06:57

the second view text we'll just add

play07:00

we'll say if let data

play07:03

equals vm.data open brackets

play07:06

so if this is data so if this is

play07:09

actually a value and not equal to nil

play07:11

we'll then add a text here and we'll put

play07:14

in the data

play07:17

all right if i click resume on the

play07:18

canvas let's first check that this data

play07:21

is loading in let's click navigate

play07:24

and it says new data perfect and now

play07:27

let's run this on a simulator so i'm

play07:28

going to take this

play07:30

so i'm going to take the first screen

play07:31

here which is our weak self boot camp

play07:34

i'm going to jump into our app.swift

play07:35

file i'm going to make this the first

play07:38

file in our app

play07:40

make sure we're on an iphone 12 you can

play07:42

do it on whatever simulator you would

play07:43

like i'm going to do an iphone 12

play07:45

and let's run it on a simulator

play07:48

i'm going to jump back into our file

play07:50

here as well i'm going to close the

play07:56

canvas

play07:59

and you can ignore some of these

play08:00

warnings that that are coming through

play08:02

right now

play08:03

it's just some swift ui uh stuff that

play08:06

apple's probably working to get rid of

play08:08

and i'm gonna

play08:09

and i'm gonna actually just scroll down

play08:11

here and

play08:12

just press enter a bunch of times to

play08:14

break this out

play08:16

but when i click navigate it should

play08:18

initialize a view model so let's click

play08:19

navigate

play08:21

initialize now i'm gonna go back and i'm

play08:23

gonna press

play08:24

navigate one more time and we clicked it

play08:27

the second time it initialized the new

play08:29

one and de-initialized the first one

play08:32

and i'm going to press back and forward

play08:36

and back and forward and you can see

play08:39

here every time we go to this screen

play08:41

it is de-initializing one and

play08:43

initializing a new one

play08:45

okay so let's create a quick little

play08:47

variable

play08:48

on our screen just to track how many are

play08:51

initialized at a time

play08:52

so we're going to do a quick kind of

play08:54

little hack here we're just going to

play08:55

create a user default

play08:57

so on our first screen here

play09:01

let's do it um let's do it on top of the

play09:04

navigation view so on

play09:06

at the bottom of the navigation view i'm

play09:08

going to add in dot overlay

play09:12

and let's add a text for the number one

play09:15

for a second

play09:16

let's see if we see it let's go to

play09:18

background of color.green

play09:22

uh sorry let's open up the canvas so we

play09:24

can see what we're doing

play09:30

all right we can see our number here

play09:32

let's give it a font of

play09:33

large title

play09:38

let's add some padding and let's give

play09:40

this overlay a

play09:42

we'll use the comma and we'll add

play09:43

alignment of maybe

play09:45

top trailing

play09:49

just so it's on the top right here at

play09:51

all times let's give that background a

play09:52

corner radius

play09:55

10. all right so this is how many are

play09:58

initialized right now

play10:00

so this number one let's make it track

play10:03

and a user default and i covered user

play10:05

defaults in another video so i'm not

play10:06

going to go over how they work

play10:08

in this one you can check out my other

play10:10

videos on app storage

play10:11

but let's create an app storage we're

play10:14

going to use a key here

play10:15

and this will be uh let's just call it

play10:17

count

play10:19

this will be a var and we'll we'll call

play10:22

it count

play10:24

and this will be of type int and it will

play10:26

be optional in case it's not set yet

play10:29

and we're just going to put this count

play10:30

into the text here so we'll do a

play10:32

backslash open close parenthesis

play10:35

put the count and because it's optional

play10:36

if there is none let's do two question

play10:38

marks and have it be

play10:39

zero if i click resume

play10:42

it should

play10:46

work we got zero and now

play10:49

every time we initialize very simply

play10:52

let's first get the current counts we'll

play10:54

say let

play10:55

currentcount equals

play10:58

userdefaults.standard.com

play11:01

int integer for key and the key is count

play11:05

remember this key is the same as the key

play11:07

that we just did up here

play11:10

and remember we're using user defaults

play11:11

down here because we are not in a view

play11:13

but because we're in a view we can use

play11:15

app storage up here

play11:17

i covered this all in the app storage

play11:19

video so i'm not going to cover that

play11:20

again

play11:21

right now but this will be the current

play11:22

count and then we're just going to set

play11:26

userdefault.standard.com

play11:28

set and we're gonna look for the integer

play11:30

and we're gonna set

play11:32

current count plus uh

play11:35

one and this will of course be four key

play11:38

count and when we go to d initialize

play11:43

let's copy these two lines

play11:45

and we're just going to do minus one on

play11:47

the d initialize

play11:49

okay so every time we initialize we add

play11:52

one every time we de-initialize well

play11:54

minus one so these should be equaling

play11:56

each other out

play11:58

and the last thing i want to do here is

play12:00

actually

play12:01

on that first view every time we load

play12:03

the app

play12:04

let's just start the count back at zero

play12:06

so we'll do init

play12:08

and here we'll just set the count equal

play12:10

to zero

play12:12

all right let's run the app on a

play12:13

simulator quick

play12:19

our count is zero and when i go to

play12:23

navigate

play12:24

count goes up to one and if i go back

play12:28

we can see our prints are coming through

play12:29

our initialize now if i go to do another

play12:31

one

play12:32

we initialize the new one but we also

play12:33

de-initialize the old one

play12:35

so the count is still one if i go back

play12:38

and i go forward and i go back and i go

play12:40

forward i can do this a whole bunch of

play12:41

times

play12:42

and the count is always one so this is

play12:44

great and this is efficient right

play12:46

because

play12:46

if this count kept going up it would be

play12:49

saving the memory of all of those old

play12:51

screens

play12:52

but right now our count remains at one

play12:53

and this is perfect

play12:55

the problem comes into play here when

play12:57

you are running asynchronous tasks

play12:59

so right now this is just happening

play13:01

immediately when we call getdata and if

play13:03

everything is working fine

play13:05

and we're all happy so if you watch my

play13:07

last video

play13:08

we were going on the background thread

play13:09

we were using a dispatch

play13:12

queue.global.async

play13:14

and when we put our call into that call

play13:18

we got this error message that the

play13:20

reference to data required explicit

play13:22

of self and to fix it we went self

play13:25

period

play13:27

and this was creating a strong reference

play13:30

to this class

play13:34

and when you're doing this creating a

play13:35

strong reference basically what you're

play13:37

telling the system

play13:39

is that while these tasks are running

play13:41

this

play13:42

self so this class absolutely needs to

play13:45

stay

play13:46

alive because we need that self

play13:49

when we come back and right now this is

play13:52

a very

play13:53

quick task so it wouldn't actually be a

play13:55

problem

play13:56

but if you were downloading like a lot

play13:58

of data from the internet

play13:59

the code in this async task might take a

play14:02

couple seconds it could take like 10

play14:04

seconds

play14:06

and during that time the user could be

play14:08

doing something on the app

play14:10

like maybe pressing the back button and

play14:12

by the time the call comes back

play14:14

you might not actually need this self to

play14:17

be alive because

play14:18

maybe the user's already gone they're on

play14:20

a different screen they don't need this

play14:22

data anymore

play14:24

to so to simulate a very long task we're

play14:27

going to use dispatch

play14:28

q dot main dot async after

play14:32

this just creates a delay and we'll do

play14:34

dot now

play14:35

plus let's do something absurd like

play14:38

maybe

play14:38

500 seconds and then we're going to

play14:41

press

play14:42

enter on here and we're gonna take our

play14:44

code and put it in here

play14:47

we're gonna get rid of this first call

play14:49

and basically what we're simulating here

play14:50

is a very long

play14:52

uh background task so this task will

play14:55

take

play14:56

500 seconds that's a very long time

play14:59

and when you're downloading data from

play15:00

the internet it's not going to take 500

play15:02

seconds

play15:03

but it will take some time and that's

play15:05

kind of what we're simulating with this

play15:06

line of code here

play15:07

so after 500 seconds the data should

play15:10

then update

play15:12

so let's click play on the simulator one

play15:16

more time

play15:19

let's we're at zero let's navigate to

play15:22

that second screen

play15:24

and it goes to one so we're looking good

play15:26

and now we're gonna go

play15:28

back and we go to navigate again it goes

play15:31

to

play15:31

two we haven't seen it go to two before

play15:34

and if we look at our printouts the

play15:35

initialize was called twice

play15:37

but d initialize was never called and

play15:40

the reason

play15:40

the d initialize was never called is

play15:42

because we had this

play15:44

strong reference to self here and when

play15:47

we had the strong reference to self we

play15:49

told the code

play15:50

that that class could not be

play15:53

de-initialized

play15:55

until this closure completes so after

play15:58

this 500 seconds

play16:00

this will then call this will then be

play16:03

complete

play16:03

and then it will de-initialize but until

play16:06

this 500 second completes

play16:08

this self will always stay alive in our

play16:11

code

play16:12

so for some things that could be good if

play16:14

we absolutely needed this line of code

play16:16

to happen

play16:18

but a lot of times in your app like what

play16:19

we just did

play16:21

within that time frame that 500 seconds

play16:23

the user navigated away they went to

play16:25

another screen

play16:27

and so once they did that we didn't

play16:29

really need to update that original

play16:31

screen that they were on right

play16:33

because they're gone they've moved on

play16:35

they're doing other things in the app

play16:37

so the fact that we keep this alive is

play16:39

actually not efficient

play16:41

and we can see here that if i keep on

play16:43

navigating

play16:44

back and forth our count is going to

play16:47

keep going up

play16:48

because we're creating all these strong

play16:50

references

play16:52

and what's happening behind the scenes

play16:53

here in the second view we're creating

play16:54

these view models

play16:56

and right now there are eight of these

play16:59

view models

play16:59

alive in the background of our app

play17:03

and the fact that we're only on the

play17:05

screen here on one of them

play17:07

just proves that this is not efficient

play17:09

because we now have eight classes in the

play17:11

background

play17:12

and we only really need one right we

play17:14

only need the one that we're on right

play17:15

now we're never going to get back to

play17:17

that old screen

play17:19

so you could imagine that if you created

play17:21

these strong references all around your

play17:22

application when you're using this

play17:24

self dot you're going to get a ton of

play17:27

objects all around your app

play17:28

that are alive that don't need to be

play17:30

alive and when you have all this extra

play17:32

stuff in your app it is just going to

play17:34

basically weigh down the app and it

play17:36

could slow things down

play17:38

so as the developer this is very

play17:39

important because this could definitely

play17:40

slow down your app

play17:42

so the solution here is basically

play17:44

instead of calling itself with this

play17:46

strong reference

play17:47

which means we absolutely need this

play17:50

class to stay alive

play17:52

we could instead add a square bracket

play17:55

and say weak self and then add the word

play17:58

in and this weak self basically just

play18:01

makes this self instead of being a

play18:03

strong reference

play18:05

it turns into a weak reference and we're

play18:07

gonna get a quick error message here

play18:09

that it is now optional so we can fix it

play18:12

with the question mark

play18:14

and basically this code is the exact

play18:16

same as we had

play18:18

except self is now optional so we still

play18:21

have

play18:21

reference to this data that we can

play18:23

update but we're telling the code here

play18:25

that

play18:26

we don't absolutely need this class to

play18:28

stay alive

play18:29

so if this class for whatever reason

play18:31

gets de-initialized

play18:33

it's okay and we can just ignore

play18:35

whatever

play18:36

these calls are so if i run my app one

play18:39

more time

play18:43

and i start clicking forward and back

play18:46

you'll see that the

play18:47

you'll see that the number stays at one

play18:49

again because even though this call

play18:51

didn't come back

play18:53

this reference to self was weak it

play18:55

wasn't strong

play18:56

so because it was weak we allowed it to

play18:59

de-initialize

play19:00

and we got our de-initialized calls back

play19:02

here so generally speaking in your app

play19:04

when you have these long tasks that

play19:06

you're like downloading data for the

play19:07

user

play19:08

it's very important to add this weak

play19:11

self

play19:12

because if you're downloading data for

play19:14

the second screen

play19:15

and then the user goes away to another

play19:18

screen

play19:19

you don't really need that first screen

play19:21

to stay alive anymore

play19:22

and if you kept that screen alive it

play19:24

would stay in the memory it would start

play19:26

to slow down your application

play19:27

and it just wouldn't be very efficient

play19:30

alright guys i hope that wasn't too

play19:31

confusing

play19:32

um basically the bottom line here is by

play19:35

using weak self we can make references

play19:37

to classes and to self optional

play19:40

so that we're telling xcode it's okay if

play19:42

this class de-initializes because if we

play19:45

have a strong reference

play19:46

it's telling xcode that we absolutely

play19:48

need the class to stay alive

play19:50

and in that scenario you would run into

play19:52

situations where this number keeps going

play19:54

up

play19:55

and you can imagine in your app if you

play19:56

had tons of calls all over your app

play19:58

and all these extra classes and objects

play20:01

were staying in the memory

play20:02

it could definitely weigh down your app

play20:04

and slow things down

play20:05

so to be professional efficient expert

play20:08

developers

play20:08

we use weak self a lot of the times when

play20:11

we're doing things

play20:13

that are asynchronous tasks such as

play20:16

downloading data from the internet

play20:18

alright guys i hope you enjoyed this

play20:20

video uh

play20:21

as always i'm nick this is swiffle

play20:23

thinking

play20:24

and i'll see you in the next video

Rate This
β˜…
β˜…
β˜…
β˜…
β˜…

5.0 / 5 (0 votes)

Related Tags
Swift UIARCWeak SelfApp EfficiencyiOS DevelopmentStrong ReferenceAsync TasksMemory ManagementXcode TipsDeveloper Tutorial