How to use escaping closures in Swift | Continued Learning #20

Swiftful Thinking
20 Apr 202121:55

Summary

TLDRIn this informative video by Swiffle Thinking, Nick dives into the concept of closures in Swift, with a focus on escaping closures. He explains the difference between synchronous and asynchronous code, demonstrating how regular functions work with immediate returns versus the delayed execution of asynchronous tasks. Nick illustrates the use of escaping closures to handle data retrieval from a database or the internet, showcasing how to implement them in Swift UI with practical examples. The video is designed to clarify a potentially confusing topic, making it accessible for developers new to asynchronous programming.

Takeaways

  • πŸ“š The video is an educational resource on Swift and Swift UI, focusing on closures and specifically escaping closures.
  • πŸ”„ Nick, the presenter, explains the transition from synchronous to asynchronous code, which is necessary for tasks like downloading data from the internet.
  • πŸ•ŠοΈ Synchronous code executes line by line immediately, whereas asynchronous code involves waiting for operations like data retrieval to complete.
  • πŸ”‘ Escaping closures are introduced as a solution to handle asynchronous code, allowing a function to be called after an operation completes.
  • πŸ› οΈ The script demonstrates building up to escaping closures by first creating a simple ViewModel and View in a Swift UI project.
  • πŸ“ A ViewModel with an observable object pattern is used to bind data to the UI, starting with a simple 'text' variable.
  • πŸ” The presenter illustrates the concept of closures by adding a 'get data' function that simulates downloading data asynchronously.
  • πŸ”„ An example of a non-escaping closure is shown, which leads to the introduction of the '@escaping' keyword to handle the delay in asynchronous operations.
  • πŸ”’ The use of 'self.' is explained to maintain a strong reference to the class within the closure to prevent deinitialization before the closure executes.
  • πŸ”“ The video also covers using 'weak self?' to allow the class to be deinitialized if not needed, addressing potential memory management issues.
  • ✨ The presenter concludes by showing how to improve code readability with struct models and type aliases for completion handlers in closures.

Q & A

  • What is the main topic of the video?

    -The main topic of the video is about closures in Swift, with a focus on escaping closures, which are used in asynchronous code.

  • What is the difference between synchronous and asynchronous code as explained in the video?

    -Synchronous code runs from top to bottom immediately and then executes, allowing functions to return immediately. Asynchronous code, on the other hand, involves operations that do not complete immediately, such as downloading data from the internet, and requires special handling with escaping closures.

  • What is an escaping closure in Swift?

    -An escaping closure in Swift is a closure that is called after the function in which it is defined returns. It allows the function to handle asynchronous code by executing the closure at a later time, such as after data has been fetched from a database or the internet.

  • Why are escaping closures necessary when downloading data from the internet?

    -Escaping closures are necessary because the data does not return immediately. They enable the function to perform actions after the data has been received, even if that happens after the function has returned.

  • What is the purpose of the 'completion handler' in the context of the video?

    -The completion handler is a parameter of a function that is a closure itself. It is called when the asynchronous task, such as data downloading, is completed, allowing the code to execute subsequent actions with the returned data.

  • How does the video demonstrate the transition from synchronous to asynchronous code?

    -The video demonstrates this by initially showing a simple synchronous function that returns a string immediately. It then modifies the function to simulate an asynchronous task with a delay, which requires the use of an escaping closure to handle the delayed return of data.

  • What is the issue with using regular returns in asynchronous functions?

    -Regular returns cannot be used in asynchronous functions because they expect to return immediately, which is not possible when the operation involves a delay or is waiting for external data.

  • Why is 'self' used with a dot in front of a property when using an escaping closure?

    -Using 'self.' before a property within an escaping closure ensures that the instance of the class remains alive until the closure is executed, as it creates a strong reference to the class instance.

  • What alternative to using 'self.' is suggested in the video to avoid potential issues with keeping the class instance alive?

    -The video suggests using 'weak self' to make the reference to the class instance optional and allow the class to be de-initialized if necessary, thus avoiding potential memory management issues.

  • How does the video simplify the code when using escaping closures?

    -The video simplifies the code by introducing a 'download result' struct to encapsulate the data being returned, and by using a type alias called 'download completion' to represent the completion handler, making the code cleaner and more readable.

Outlines

00:00

πŸ“š Introduction to Swift Closures and Asynchronous Code

Nick introduces the topic of closures in Swift, specifically focusing on escaping closures. He explains that while most functions they've covered so far have synchronous return types, upcoming lessons will involve asynchronous code for downloading data from the internet. Nick outlines the difference between synchronous and asynchronous code, emphasizing the need for escaping closures to handle functions that return data after a delay, such as from a database. He promises to guide viewers through the concept, which is crucial for building production applications.

05:02

πŸ”„ Understanding Synchronous vs. Asynchronous Code

The paragraph delves into the specifics of synchronous code execution, which is immediate and line-by-line, versus asynchronous code, which involves delays and does not execute immediately. Nick demonstrates this with a simple 'downloadData' function that simulates a database call with a two-second delay. He points out the limitations of regular return statements in asynchronous functions and introduces the concept of a completion handlerβ€”a closure used to handle the result of an asynchronous task.

10:02

πŸ“ Implementing a Completion Handler in Swift

Nick shows how to implement a completion handler within a function that simulates asynchronous data retrieval. He modifies the 'downloadData2' function to accept a completion handler as a parameter and explains how this allows the function to return data after a delay. He also discusses the error that arises when trying to use a non-escaping closure in an asynchronous context and how to resolve it by using 'self' to maintain a strong reference to the class.

15:03

πŸ”‘ Using Escaping Closures to Manage Asynchronous Tasks

The discussion moves to escaping closures, which are closures that the called function may hold onto beyond the time it returns. Nick demonstrates how to mark a closure as 'escaping' and how this allows for the delayed execution of code. He also addresses the issue of maintaining a strong reference to 'self' and introduces 'weak self' as a solution to prevent potential memory management issues.

20:04

πŸ›  Refactoring Code for Readability and Efficiency

Nick refactors the code to improve readability and efficiency. He creates a 'DownloadResult' struct to encapsulate the data being returned from the asynchronous function, allowing for the potential return of multiple data points in the future. He then demonstrates the use of a type alias, 'DownloadCompletion', to simplify the signature of the completion handler, making the code cleaner and more maintainable.

πŸŽ“ Conclusion and Future Learning

In the final paragraph, Nick concludes the lesson on escaping closures, affirming that viewers are now equipped with the knowledge to use them effectively. He hints at further lessons that will cover downloading data from the internet and integrating it into apps, encouraging viewers to stay tuned for more advanced topics in the Swift programming language.

Mindmap

Keywords

πŸ’‘Swift

Swift is a powerful and intuitive programming language developed by Apple for iOS, macOS, watchOS, and tvOS app development. In the video, it is the primary language discussed, with a focus on its advanced features for asynchronous programming and closures.

πŸ’‘Swift UI

Swift UI is a framework for building user interfaces across all Apple platforms, introduced in the video as the context for the discussion on closures. It is used for creating views and user interfaces in a declarative way, which is central to the examples provided.

πŸ’‘Closures

Closures in Swift are self-contained blocks of functionality that can be passed around and used in your code. They are a key concept in the video, where they are used to handle asynchronous operations, such as downloading data from the internet.

πŸ’‘Escaping Closures

An escaping closure is a closure that is called after the function in which it is defined returns. In the video, escaping closures are explained as a way to handle asynchronous code, allowing the completion of tasks that take time, such as network requests.

πŸ’‘Asynchronous Code

Asynchronous code refers to code that does not proceed in a linear fashion, allowing other operations to occur while waiting for tasks like network responses. The video discusses the use of escaping closures to manage asynchronous operations in Swift.

πŸ’‘ViewModel

A ViewModel is a design pattern used in software development to separate the logic from the UI and to manage data for the view. In the video, an 'escaping view model' is created to handle data operations, illustrating the ViewModel's role in managing asynchronous data.

πŸ’‘Observable Objects

Observable objects in Swift UI are a way to make data reactive, so the UI can update automatically when the data changes. The video mentions conforming to 'observable objects' to enable the view to observe changes in the ViewModel.

πŸ’‘Dispatch Queue

A dispatch queue in Swift is a queue to which tasks are assigned for execution. The video uses 'Dispatch Queue' to simulate asynchronous behavior with a delay, mimicking the delay of network requests.

πŸ’‘Completion Handler

A completion handler is a block of code that is executed after a function completes its execution. In the video, the completion handler is used within escaping closures to handle the result of asynchronous tasks.

πŸ’‘Type Alias

A type alias in Swift provides an alternative name for an existing type. The video demonstrates using a type alias to simplify the syntax of a closure, making the code cleaner and more readable.

πŸ’‘Weak Self

Weak self is a concept used to prevent strong reference cycles or retain cycles in Swift, where an object is kept in memory because it is referenced by another object, which in turn is referenced by the first. The video explains the use of 'weak self' to avoid such issues in asynchronous code.

Highlights

Introduction to the concept of closures and specifically escaping closures in Swift.

Explanation of synchronous code and its limitations when dealing with asynchronous tasks like downloading data from the internet.

The necessity of handling asynchronous code with escaping closures in Swift for tasks that do not return immediately.

Creating a function within a function to manage asynchronous operations, such as data retrieval from a database.

Demonstration of a simple ViewModel setup with an ObservableObject to connect with a SwiftUI view.

Use of an onTap gesture to trigger a function that simulates data download in a synchronous manner.

Transitioning from synchronous to asynchronous code by introducing a delay to simulate database access.

Introduction of the completion handler as a parameter within a function to manage asynchronous results.

Error handling when using non-escaping closures and the need for explicit self usage to maintain class instance during asynchronous tasks.

The use of weak self to prevent strong reference cycles while using asynchronous closures.

Refactoring the code to improve readability and maintainability by using a struct for the returned data.

Utilization of a type alias to simplify the completion handler syntax and improve code efficiency.

Practical demonstration of using escaping closures to update UI elements after asynchronous data retrieval.

Discussion on the commonality of using escaping closures for returning data and returning void in production applications.

Providing alternative approaches to customize closures for different return types and values.

Conclusion summarizing the importance of understanding and using escaping closures in Swift for asynchronous programming.

Transcripts

play00:06

welcome back

play00:07

everyone i'm nick this channel is

play00:09

swiffle thinking where we cover all

play00:11

things

play00:11

swift and swift ui related and in this

play00:14

exciting video we're going to look at

play00:16

closures

play00:16

and even more specific we're going to

play00:18

look at escaping closures

play00:20

now if you've been following my courses

play00:22

so far almost all the functions that

play00:24

we've created either didn't return

play00:26

anything

play00:27

or had a regular return type and that's

play00:29

been working perfectly

play00:31

but in the next couple of videos we're

play00:32

gonna start downloading data from the

play00:34

internet

play00:35

and when we do that we have to use

play00:37

asynchronous code

play00:38

and to explain that really quickly when

play00:41

we have synchronous code

play00:42

it runs from top to bottom immediately

play00:45

and then executes so if we have a

play00:47

regular function

play00:47

we will write the function it will run

play00:49

all those lines in our code and then it

play00:51

will return as soon as it gets to the

play00:52

bottom

play00:53

so those functions basically can return

play00:55

immediately

play00:57

but when we are going to a database to

play00:59

download data from our internet

play01:01

we're going to create functions to go

play01:03

get that data but that data is not going

play01:05

to come back immediately

play01:07

it's going to take a couple seconds to

play01:08

go to the server get that data

play01:11

bring it back to our app so we can't

play01:14

just

play01:14

immediately return out of this function

play01:16

and instead of

play01:17

immediately returning we need to handle

play01:19

this asynchronous code

play01:20

and we do that in swift with escaping

play01:23

closures

play01:23

so basically what we end up doing is

play01:25

creating a function and then within that

play01:27

function

play01:28

we are passing another function as a

play01:31

parameter into the first function and

play01:34

this way we can call that second

play01:36

function

play01:37

when our code comes back from the

play01:38

database and when we want it to actually

play01:40

execute

play01:41

so this is something that sounds

play01:42

confusing and actually could be

play01:44

confusing

play01:44

if you've never dealt with asynchronous

play01:46

code before so i hope this video helps

play01:48

someone out there who is struggling with

play01:50

this

play01:50

because this is used all the time in

play01:53

production applications and something

play01:54

you

play01:55

definitely will need to know all right

play01:57

and that's enough of me talking

play01:58

let's jump into the code and we're going

play02:01

to build our way up to this escape

play02:02

enclosure so you guys can fully

play02:04

understand

play02:05

what's going on all right

play02:08

welcome back everyone we're back in our

play02:10

xcode project with another

play02:12

fun video today let's right click on the

play02:15

navigator create a new file for the code

play02:17

we're going to write

play02:19

and this of course will be a swift ui

play02:21

view and

play02:22

let's call this escaping boot camp

play02:26

go ahead and click create and we're

play02:30

calling it escaping because in this

play02:32

video we're going to cover escaping

play02:33

closures now before we actually get into

play02:37

escaping closures i want to build up to

play02:39

them

play02:39

so you can understand why we are

play02:41

actually using them

play02:42

and then i'll show you how to use them

play02:45

so let's start very simply by creating a

play02:48

view model

play02:48

for our view so we'll say class let's

play02:51

call it

play02:52

escaping view model

play02:55

let's make it conform to observable

play02:58

objects so that we can observe it from

play02:59

our view

play03:00

while we're here let's initialize one in

play03:03

the view

play03:04

we'll use an at state object

play03:07

var let's call it vm for viewmodel and

play03:09

we'll set it equal to an escaping

play03:16

viewmodel

play03:18

all right in this view model we're gonna

play03:19

have a very simple

play03:21

variable we'll do at published var

play03:24

we'll call it text and it'll be of type

play03:26

string and we'll set it equal to

play03:29

uh hello to start very simple

play03:32

on the view we're going to connect this

play03:34

text to the view model text

play03:36

so we'll say vm dot text

play03:40

let's just make it font of large title

play03:43

font weight of

play03:44

semi and maybe a foreground color of

play03:47

blue let's click resume on the canvas to

play03:51

make sure

play03:51

it is all connected we should see our

play03:53

hello text here

play03:56

and in the view model we're going to

play03:57

create a very basic function we're going

play03:59

to say func

play04:00

get data open close parenthesis open the

play04:03

brackets

play04:04

and we will call this get data from the

play04:07

view

play04:07

so when we tap on this text let's add an

play04:10

ontap gesture and we'll call vm.getdata

play04:14

very simple so when we tap it this

play04:17

function

play04:17

will run and this function is actually

play04:19

going to call another function

play04:21

we'll create another func we'll call it

play04:22

download data

play04:25

open close parentheses open the brackets

play04:28

and we're not going to actually download

play04:30

data in this video but we're going to

play04:32

simulate like it does

play04:33

so for right now let's have this

play04:35

download data

play04:36

return a string

play04:40

so this is the regular return type in

play04:42

swift where we can immediately return

play04:45

and it will return us a string so here i

play04:48

will return

play04:48

and let's say new data

play04:53

now from inside get data we can then

play04:55

call

play04:56

download data so we can say let new data

play04:59

equals download data and then we can

play05:02

just set our text

play05:03

equal to the new data we could have done

play05:06

this on one line but i just want to

play05:08

be very explicit on what we're doing

play05:10

here

play05:12

so this should work let's click resume

play05:14

on the canvas

play05:19

click play on the live preview and when

play05:20

we tap on hello

play05:22

it should change to new data this should

play05:24

not be anything new to you guys we're

play05:25

just updating this text variable

play05:28

and when we have these regular return

play05:30

functions here

play05:31

this is something called synchronous

play05:33

code so basically if we had a whole

play05:35

bunch of logic in this

play05:37

function here it would run immediately

play05:40

line by line by line right so this is

play05:43

the regular

play05:44

swift code where we do something line

play05:46

one runs line two line three line four

play05:48

line five

play05:50

and then it will immediately return so

play05:52

basically as soon as we call download

play05:53

data it will immediately

play05:55

return us a string and that's great

play05:58

whenever you can use this you should use

play06:00

this but there are times when this is

play06:02

not going to work

play06:03

so below this function let's create a

play06:05

new func we'll call it download

play06:08

data two open close parenthesis open the

play06:10

brackets

play06:12

let's have this return a string for a

play06:14

second and let's also return

play06:17

new data let's call this download data 2

play06:21

from our actual code in the get data

play06:25

and for this function let's pretend like

play06:28

it's actually going to go to the

play06:29

database

play06:30

so obviously we're not going to do all

play06:32

the code to download from the internet

play06:33

but what we can do is call a dispatch

play06:36

queue

play06:37

dot main dot async after

play06:41

we can do.now and maybe give it plus two

play06:43

seconds

play06:45

and then we can put some code inside so

play06:48

basically this is a

play06:49

adding a delay to our code and the delay

play06:51

is two seconds

play06:52

so after this is called it will wait two

play06:55

seconds and then

play06:56

call the code inside so then i'm going

play06:58

to cut and

play06:59

paste my return new data in here

play07:03

and this is where our problem comes from

play07:06

because

play07:07

when we have these regular returns they

play07:10

want to return

play07:11

immediately this is synchronous code but

play07:14

when we add these delays

play07:15

into our code this is asynchronous this

play07:18

is not happening immediately this is

play07:20

happening

play07:20

at a different point in time so this is

play07:22

happening two seconds in the future

play07:25

and when we actually go to start

play07:26

downloading from the internet

play07:28

we're going to add lines to download

play07:29

from the internet but that result isn't

play07:31

going to come back immediately it's

play07:33

going to take a couple seconds

play07:34

to go to the internet get that data and

play07:36

then come on back

play07:38

so when we start downloading from the

play07:39

internet we're going to run into this

play07:40

problem every time and we can't use

play07:42

these regular

play07:43

returns all right so

play07:46

now let's get into the solution here and

play07:49

i'm going to put the return data back

play07:51

and before we use an escape enclosure

play07:53

we're just going to look at the basics

play07:54

of a closure so

play07:58

basically closure is adding a function

play08:01

as a parameter

play08:02

into your original function

play08:05

so instead of returning this string here

play08:09

i'm going to instead type a parameter

play08:12

called

play08:12

completion handler

play08:17

and this will be of type and we're going

play08:19

to open the parenthesis using underscore

play08:21

let's call this data it will be of type

play08:25

string close the parentheses and then

play08:29

this function will return void

play08:35

all right so i'm going to explain this

play08:36

in a second and then instead of

play08:39

returning because we don't have that

play08:40

regular return at the end of our

play08:42

function here

play08:43

now we have a completion handler which

play08:45

is then a function that we can call

play08:48

by calling completion handler

play08:51

and then passing in our new data here

play08:57

before we move forward i first want to

play08:58

point out that i'm calling this

play08:59

completion handler

play09:01

very common people will just call it a

play09:02

handler or

play09:04

just completion i'm going to use

play09:06

completion handler just to be a little

play09:08

more explicit in this video

play09:11

and we're getting this error message at

play09:13

the top here because

play09:14

when we write our code like this it is

play09:16

creating this new data function with a

play09:18

string so for regular download data it

play09:21

is returning immediately so we can set

play09:23

up

play09:23

this variable called new data but when

play09:27

we have download data too it's not

play09:28

returning anything immediately so

play09:30

because it's not returning anything we

play09:31

can't actually just set up a variable

play09:34

with this result instead

play09:37

we are going to call download data2

play09:41

and then on the completion handler we're

play09:43

going to press enter

play09:46

and this string that we're seeing here

play09:48

is this data

play09:50

string that we put here and obviously

play09:53

the string is going to be this new data

play09:55

so let's call this returned data

play09:59

and then in this completion block here

play10:02

we will set

play10:03

text equal to the returned data

play10:08

all right so if i resume the canvas and

play10:10

press play on the live

play10:11

preview this should work now we can

play10:14

click hello and it still says new data

play10:16

and we're using our download

play10:18

data2 function so basically as soon as

play10:20

we call this completion handler

play10:22

it's going to execute this function

play10:26

and this function is this

play10:29

this block here

play10:33

so before we move forward looking at

play10:36

this this is

play10:36

kind of ugly to see if you've never seen

play10:38

it before but think about this just

play10:40

as a separate function if we were to

play10:43

create a function

play10:44

let's let's do funk do something

play10:48

open close parenthesis open the brackets

play10:51

and this do something let's pretend

play10:53

like it had a parameter called data of

play10:55

type string

play10:58

all right so this is very similar to

play11:00

what we have here data of type string

play11:02

but we have this weird underscore

play11:04

so when we create functions we can

play11:06

actually add external and internal

play11:08

names or labels so right now we just

play11:11

have one label for data

play11:13

so in this code we can do print

play11:16

data okay and if i were to call this

play11:19

from my code i'll do it up here real

play11:21

quick i'll say

play11:22

do something and when we go to call it

play11:24

we see the word

play11:25

data as well but we could add an

play11:28

external name for this data

play11:29

we can say maybe just four data

play11:33

and now when i call this from my code

play11:36

do something externally so outside of

play11:39

the function

play11:41

everywhere else this will save for data

play11:43

and this

play11:44

is often used to make this more readable

play11:46

so we'll do something for

play11:47

data but internally inside this closure

play11:51

we still reference just data we don't

play11:53

use four data

play11:54

inside the closure however when we're

play11:56

creating this completion handler

play11:58

we can actually use these external names

play12:01

here

play12:02

so instead we just use an underscore and

play12:05

then if we call to do something

play12:08

we can see that we have the underscore

play12:10

and data

play12:11

so basically we just can't give it an

play12:12

external name and that's why we have

play12:15

this underscore

play12:16

and then lastly we have this return void

play12:19

and that's what this function is so if

play12:22

this function wanted to

play12:24

return a string we could change this to

play12:28

return string but if this doesn't return

play12:31

anything like it was

play12:33

so right here this is actually going to

play12:36

return a

play12:36

void swift is just generally

play12:40

smart enough to know that this function

play12:43

doesn't return anything so we never

play12:44

really have to write this in our code

play12:46

except for when we're using these

play12:47

completions and now another way to write

play12:50

this

play12:50

return void is also return

play12:53

open close parentheses so void and this

play12:57

open close parenthesis are basically the

play12:59

same thing just saying that this

play13:00

function doesn't return

play13:01

anything so often when people use these

play13:04

completion handlers instead of putting

play13:06

void they will just put open and close

play13:07

parentheses

play13:09

and this is a structure you're going to

play13:10

see a lot as we move forward

play13:13

so i just wanted to introduce you guys

play13:15

to that

play13:16

and now let's take this one step further

play13:19

so i'm going to

play13:20

copy this download data to paste it down

play13:23

here

play13:24

let's make this download data3

play13:28

i'm going to change the title the value

play13:30

i'm going to change the function up here

play13:31

to

play13:32

3 and now we have one more problem

play13:34

because if

play13:35

in here we tried to add our delay as if

play13:38

we were going to the database we had our

play13:40

dispatch queue dot main dot async after

play13:44

we'll do now plus two seconds and then

play13:46

we'll put our completion handler

play13:48

inside so this again is simulating going

play13:51

to the database

play13:54

and when we do this we are actually

play13:56

still going to get an error message

play13:58

that this escape enclosure captures a

play14:00

non-escaping parameter

play14:03

so this now is where our escape

play14:05

enclosure comes in so all we have to do

play14:07

to modify this non-escape enclosure

play14:10

to be escaping is add at scaping

play14:16

and when we add this at escaping it

play14:18

makes our code asynchronous which means

play14:20

it's not going to immediately execute

play14:22

and return

play14:23

and that's why we have this delay here

play14:25

and that's also why we're going to get

play14:26

this error message that the reference to

play14:28

this property text

play14:30

requires explicit use of self so if you

play14:33

remembered a couple videos

play14:35

back i covered weak self and the reason

play14:37

i did that first is because as we start

play14:39

to download from the internet

play14:41

we're going to run into these

play14:42

asynchronous tasks and every time we do

play14:45

that we're going to get this error

play14:46

message so the easiest way

play14:48

to solve this is just just add self dot

play14:51

and this creates a strong reference to

play14:54

this class so what's going to happen

play14:57

here is we're going to call this

play14:58

download data

play15:00

but this closure is not going to

play15:02

immediately execute

play15:03

this closure will execute whenever we

play15:06

call it in our code so this completion

play15:08

handler is going to be called

play15:09

in two seconds and during

play15:12

that time between when we called

play15:14

download data and this closure

play15:17

there's a chance that the user has

play15:18

navigated around the app

play15:20

maybe they did something else and maybe

play15:23

they went to another screen that

play15:24

actually doesn't even

play15:25

need this escaping view model so there's

play15:27

a chance in our app

play15:29

that we would have de-initialized this

play15:31

class

play15:32

when we create this strong reference to

play15:35

the class

play15:36

we're basically telling xcode that we

play15:38

absolutely need this class

play15:40

to be alive when we come back into this

play15:42

closure

play15:43

so because of that we create this strong

play15:45

reference but in that video that i did

play15:48

i think two videos ago i explained why

play15:51

that's not always

play15:52

the best solution because if there are

play15:54

cases when this class should be

play15:56

de-initialized

play15:57

this self might be keeping it alive and

play15:59

that could cause issues in your app and

play16:01

start to slow down your app

play16:03

so the solution here is to make self a

play16:05

weak reference instead of

play16:06

a strong reference and we do that with

play16:08

the square brackets

play16:10

we type weak self and then this self

play16:13

actually becomes optional by doing this

play16:16

we are then telling

play16:17

xcode that it is okay if we want to

play16:19

de-initialize this class

play16:21

we don't absolutely need it to be alive

play16:25

all right so now if i click resume on

play16:27

the canvas we're using an at escape

play16:29

enclosure

play16:31

which we are simulating download from

play16:33

the database it's going to take two

play16:34

seconds and then it's going to return

play16:36

so if i click on hello it should take

play16:38

two seconds

play16:39

and then update and now you guys know

play16:42

how to use the escape enclosure

play16:45

before i wrap up this video i want to

play16:47

show you guys two ways to make this

play16:49

a little bit of code here actually a

play16:51

little more readable and this is

play16:52

something that i've seen a lot in

play16:54

production apps

play16:56

especially larger code bases so let's

play16:59

copy this

play17:00

download data3 let's paste it below

play17:03

let's make this download data4

play17:07

and and as we know the data right now is

play17:10

just of type string

play17:12

so let's create a model for this

play17:15

returned data

play17:16

so outside of the view model i'm in

play17:19

between

play17:20

the view model and the struct here i'm

play17:21

going to create a

play17:24

struct let's call this let's call this

play17:27

download result

play17:31

and we'll open the brackets and this

play17:33

download result is going to be just like

play17:35

all of the models we've been setting up

play17:36

in all of our videos

play17:38

and of course it's only going to have a

play17:40

data of type string so we'll say

play17:42

let data of type string

play17:47

and now that we have this download

play17:49

result type we can actually

play17:51

change out this underscore data

play17:54

type string and just put in a download

play17:56

result

play17:58

and in our completion we we can say let

play18:01

result

play18:03

equals download result

play18:06

we'll put in our data of new data

play18:11

and then our completion handler we will

play18:13

just include

play18:14

the result

play18:18

all right so going up to our download

play18:19

data let's delete what we have

play18:21

let's do download data for

play18:25

and now we can see that it is a type

play18:27

download result and i'll click

play18:28

enter here and i'll put this as returned

play18:31

result let's make it a

play18:35

weak self like we just did this will be

play18:38

self

play18:39

with a question mark dot text and we'll

play18:42

set it equal to

play18:42

the returned result dot data

play18:46

and you can see that this could be more

play18:49

efficient

play18:49

if we had a whole lot of data that we

play18:51

wanted to return because we could add a

play18:53

bunch of variables into this download

play18:55

result

play18:56

and then we could access them through

play18:59

here we could say download result

play19:00

dot and we get all of those data points

play19:03

that we wanted to

play19:04

have that we wanted to be returned

play19:07

so if i click resume on the canvas one

play19:09

more time

play19:12

it says hello i click it i wait two

play19:14

seconds it should still work

play19:16

and one more step further

play19:20

i want to show you guys we're gonna copy

play19:21

this download data for

play19:24

let's do download data five

play19:28

this time i'm going to use a type alias

play19:30

and i cover this in the last video

play19:33

and this is basically we can create a

play19:36

new

play19:36

we can give a name for a type

play19:39

so i'm going to give this a name of

play19:41

download completion

play19:45

and this will be of type

play19:48

i'm going to take this type here so this

play19:50

download result with the open close

play19:52

parenthesis

play19:53

that returns void i'm going to copy that

play19:56

and paste that

play19:57

here so the completion is a download

play20:01

result

play20:02

that returns void and i'm going to take

play20:04

this download completion and

play20:05

instead of all this code we're just

play20:08

going to put

play20:09

download completion

play20:13

so you can see in this download date of

play20:14

5 how we went from

play20:17

this ugliness here which could get very

play20:20

long if you had a whole bunch of

play20:22

if you had a whole bunch of variables

play20:23

that you were returning

play20:25

we made it shorter with the result then

play20:27

we made it even better by just making it

play20:30

a completion and we don't even have this

play20:32

arrow and void so this

play20:35

is very efficient coding let's go back

play20:38

up to

play20:38

our app and where we have download data

play20:41

for

play20:41

the completion block is actually the

play20:43

exact same so i can just change this to

play20:46

five i can click resume on the canvas

play20:52

hello let's click it it'll wait two

play20:54

seconds and then update

play20:57

all right guys now you are experts at

play21:00

using this ad escaping and

play21:02

there are a bunch of other cool things

play21:04

that you can do with ad escaping

play21:06

to make really customized closures for

play21:08

example

play21:09

we only had our closures return void you

play21:12

can actually make them

play21:13

return other values but this scenario

play21:16

here where it is

play21:18

giving us data and returning void is

play21:20

definitely the most common that i've

play21:21

seen

play21:22

and i think this is a pretty solid

play21:25

starting point

play21:26

if you've never used these closures

play21:28

before

play21:31

i'll zoom out here so you can see the

play21:32

code but now that we do know this at

play21:34

escaping

play21:35

we can actually get into downloading

play21:37

this data from our internet finally and

play21:39

putting it into our app

play21:42

alright guys thank you for watching as

play21:44

always i'm nick

play21:45

this is swiffle thinking and i'll see

play21:47

you in the next video

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

5.0 / 5 (0 votes)

Related Tags
SwiftEscaping ClosuresAsynchronous CodeProgramming TutorialXcode ProjectViewModelClosure ParametersData DownloadInternet APIiOS Development