What's new in Swift 5.5

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey folks how are you doing uh it is now day two of wwc hopefully you'll hear me nice and clearly and see my screen nice and clearly um today's talk is about uh swift 5.5 and what is new into 5.5 and uh there's a lot newer 5.5 as the answer and obviously concurrency asynchronous functions and many more things kind of steal the limelight they're pretty massive in fact they're absolutely massive uh and and that's fine i would say uh uh this release is easily the biggest since with three i mean so five one was huge right that's uh property rappers and dsls and more and stuff um but this is bigger i mean this is a huge release and honestly you could argue this is the biggest release in swift one it's just huge uh and so uh a lot's changing and that's hard um it's made extra hard because some of the things that are changing in fact quite a few of the things that are changing are really big in their own right and uh and they're complex and there's actually an old joke brilliant old joke uh which is uh someone says themselves i've got a problem i know i'll use regular expressions to solve the problem and now they have two problems and there's a very famous variant of that which is that if you've got a problem and think to yourself i'm going to use concurrency so i can solve this problem in parallel now two u problems have uh of course the answer there is that it's easy to find your code running at different speeds in different times completing at different speeds and times um and it just causes all sorts of complexity um we call these usually race conditions when they are bugs and that's when two pieces of our code are sort of racing to complete the work at the same time and modifying data at the same time and whichever one completes first affects the result of the program and they're particularly fiendish to debug right because you've got to try and you run it and it goes well it works fine now run again now it's broken right again it works but again it's broken depending on how fast it all comes back so um it's complicated and so our brains are struggling a little bit right because our brains kind of don't think in parallel they think very much in one simple straightforward line and uh trying to think about many operations at the same time is challenging and just for fun of course all this happens attached to dub dub dc and so many of apple's apis have been updated either automatically or by hand to take advantage of these things these new features and so you've got lots of change you've got difficult topics you've got api churn at the same time there's lots and lots happening and so uh i want to make it really clear if you're sitting there thinking wow this is really hard to understand honestly i think that's a sign your brain is working correctly because it is hard to understand right and in this stream i want to share with you what i figured out so far but keep in mind this is hard for me too you know i i'm saying this all up front because i want to try and set a tone for this stream i'm not sitting here trying to tell you the uh one true way to use async or weight or use tasks and task groups whatever i want to hear your feedback and hear your discoveries and hear what you think along the way and we'll figure out together that's where we're at it's only tuesday of wbc week right uh and and that's okay we'll figure out together you're in the night you're in chat you can't see it but i'm reading your chat area on my screen down here i'm seeing what you're writing as we go uh what we don't yet know uh is the back deployment story you know we don't know what's going to be right next right now it's only available macares mac os monterey plus ios 15 um to have all these new features and uh ted kramernick on the developer tools swift uh lounge right now like a few minutes ago said they are looking into ways to find some kind of back deployment story without compromising future performance um they don't know either and that's okay they're figuring out too and so um if you want to support before ios 15 you might have some problems we don't know what the answer is just yet and that's fine so c is the answer okay let's kick off with some examples of stuff because so much has changed and if you've read my existing writing i'm sorry you'll find this whole stream very very boring if you haven't this will all be new and exciting to you let's dive in together um the the biggest thing for end users like us the most immediate obvious win i think is going to be async await support and this is kind of a foundational thing from our perspective not so much from the internal swift perspective but from the way we use it async await is really really important and there's a way to structure our code and you'll see this if you've seen it in in c sharp or javascript or other languages that have a single weight already it works very very similarly from our perspective and it has the same positives and the same negatives which is great because if you've used those other languages you've got a head start already and this allows us very easily to run complex asynchronous code as if it were synchronous almost there's a few little uh little tweaks you gotta make here and there you don't get this plague of async everywhere um but it's almost the same which is really nice and it's mostly backed by these two keywords async and await we mark a function as being async this must be run in asynchronous context not you know on the main thread and then we call those using a weight so the function itself is async we call them using a weight and that's how it works and i think the way i've talked about elsewhere is to walk folks through how code looks right now like before a single wait so 5.4 how do we solve these problems how would we say i want to call a function and get a value back at some point in the future without causing my whole ui to freeze up and we do this using traditionally completion handlers which are closures and we might say for example uh that we want to go ahead and fetch some data about the weather somewhere in the world so we'd say funk fetch weather history now this thing is going to do some work it's going to connect the internet and download stuff and pause it and i don't know what's going to do stuff right we don't want to say this is going to download download and return immediately an array of doubles we wouldn't do that because it would cause our whole app to freeze while we were doing that so it's a real mess instead we use completion handlers we would say that fetch weather history accepts one parameter its completion handler and this thing is a closure a function to run at some point in the future if it's immediately pass it on in if it isn't immediately we want to say it's going to be escaping it'll be run at some point after the function ends in this case the function we expect to call will take an array of doubles like that and it will return void so we'll call this thing with a function and that function will accept an array of doubles and return void like that now you'd go ahead and do your complex networking work go ahead and download stuff power stuff whatever you want to do stuff now on the internet could take you know a split second could take minutes we don't know it takes time so you put in here your complex networking code and at some point in the future call the completion handler you would say in our case we'll just cheat we'll do dispatchq dot main dot async that's our complex networking code right there i'll invent some numbers i'll say our results are one through a hundred thousand map underscore in double dot random in minus ten dollar dot thirty so we'll get back an array of a hundred thousand doubles in the range minus 10 to 30. and then we'll call the completion handler with those values that's how it works right now go ahead and asynchronously do some work completion handler with that value to pass it back we might have some more work we might say okay at some point we'll get some values back from our weather history i want to calculate the average temperature for those records an array of double again again with a completion handler this will take some time to happen here don't block the main thread do it somewhere else so it's say this is going to be another escaping closure sorry completion escaping close like that escaping except a single double the average temperature and again returns void inside there we're going to go ahead and again do our work later on i'll push us to a background thread for example we might say our total value is going to be all our records reduce zero plus so add up all the doubles in our array to make one total double then get average will be oh my dogs have arrived sorry total divided by the double of records.count so that's now the mean average of our records array and then call a completion handler with that average so we've got two functions now both taking a completion handler and finally we've fetched it we've got the average stuff behind here will now upload the average to our server we'll say something like uh funk upload come up then say hello to the people watching here you go oops that's for later perhaps there you go i would say no to you would i no okay only one dog i have two dogs promised two dogs two straws two kids anyway uh upload our server so we'll say upload that result double again with a completion at escaping takes a string one of the server return returns void like that we'll have more complex networking code here right uh in our case we'll just do some a little cheat we'll do dispatch queue uh dot global dot async completion okay like that where's the other dog gone only one dog anyway so we've got at these three functions fetch some data from the internet in our case just generate hundred thousand random values get the average of those temperatures take some time so again it's done by completion handler and then upload the results to a server and return back what the server replied with in our case it'll always be okay now how would we call that how do we actually run that functionality here it would look like this would say first i want to fetch the weather history and when that returns give me the records coming in in my completion handler closure then calculate the average temperature temperature for those records again another closure coming in with our average and inside there we'll do upload that result with the response coming in and then finally we can say print server applied response like that so that's roughly how it looks we have our code using the old school uh completion handler approach it's been standard in swift 5.4 and earlier hopefully you can see the problems with this kind of code right it's pretty messy it is entirely possible for these functions here to forget to call the completion handler i might have had an if checking here somewhere and only had the completion called in one of those two places so it's called here but not there in which case the whole thing kind of fall flat it's also possible to call it twice maybe i've had completion here and completion there you know classics of go-to fail error from the letter cell days right having things called twice by accident cause massive problems this kind of syntax ad escaping array of double returns void this can be quite hard on your eyes to read there's lots and lots of stuff going on it's not pleasant to read and it's actually quite a bit of a you know for complex functions like that it's pretty intense in fact i'd say and then particularly when we call this stuff down at the bottom uh we have fetch weather history then calculator temperature does it do it um you can see we have this whole pyramid going on do a indent do b indent do c uh each one handling a completion handler inside the first thing again and again and again so there's lots of work happening here but also think about how would handle errors you had two treats that's enough for you you don't need more than two treats go on let's get out sorry they're obviously never fed here's the last one i'll throw it that way okay look here go let's get out right we've got a minute to talk uh gert asks why are these in underscore to help my eyes read big numbers i'm not simple anyway um that's how it looks how do you handle errors well we might say actually our completion closure might take uh a result of double but also some kind of network error or similar there then handle that in the completion closure down there it's more complex it gets more and more difficult as we handle it and it's problematic we've got to have all sorts of custom code to handle errors and indents and messy and escapings everywhere it's complex and this is where async await comes in they can do so much better because we can ditch the completion closes entirely and instead return values directly as if it were a synchronous function so i might say that fetch weather history i'll just delete this whole completion closure part here and say this thing is now an asynchronous function and directly returns an array of double like that and then inside the function i'll ditch the call to dispatch q main async and just call our code directly let us do that that's our entire function now ah here's the other dog you've had no treats yet come on you've had like three treats now come on that's about you're tubby hair off enough sorry um that becomes our new function send the value back directly no more fussing around doing asynchronous here there and ever it's already asynchronous just go ahead and carry on being asynchronous now when it comes to our average temperature again we want to keep this thing coming in here's the values of to work with i'll get rid of the completion closure that goes away and again say this is an asynchronous function and returns a single double the average temperature you want to work with i'll then get rid of the asynchronous work it's already asynchronous now let's do directly return average like a regular synchronous function would do these look like synchronous functions obviously the async what keywords there otherwise they look like synchronous functions and upload down here it's exactly the same thing again get rid of the completion closure here make it have a string going back and then just send back in our case it is just okay like that okay so we've removed stacks of syntax stacks of complexity just from our function definitions which is amazing but at the core site it's even better because we can now start to make this whole thing look nicer we could say if i have a funk process weather uh function here that is async i now go ahead and call those functions one by one in a straight line i'll just do let records equals await fetch weather history then let average equals await calculate average temperature for records and then let response equals await upload upload that result average and finally print server replied response like that that's how it looks in an async world i'm missing async here good spot thank you very much khan there we go anvitor thanks for the chat books you can't see it but the chat window right here hidden on my screen i'm sort of reading from carefully when i can um and that's how it looks so all the completion closures all the indenting is gone instead we have straight line code we call it because literally a nice beautiful straight line apart from the await calls that are in there it looks just like synchronous code it looks and works just like it's absolutely brilliant in terms of understanding and what we're seeing here is when we're seeing look dog you've had multiple treats you've got to go away now wait wait wait wait wait wait wait wait wait wait oh wait wait wait you get fed you really do what we're seeing here we're telling swift hey this bit of work this might take some time it might take some time it might return immediate in which case it won't take any time it'd be like a regular synchronous function call but it might take some time and so swift has the option to suspend our work to suspend the function and say okay i'll use the thread you on to some other work instead for a while i'm sorry my dogs are extremely love-hungry today apparently um no more treats um it can it can say okay um i'll just pause here for a while spend the thread do some other more interesting work in the meantime that's more important right now and then come back to you later on and it'll happen here and then here and here they're all suspension points i can see any point of these things yes go ahead and do some other work uh stacy it's not actually laid out for me to see if my clock is 20 past two my brain is currently on pacific time which i find much much easier to handle wdc with so these are these are maybe suspension points uh when work might stop temporarily and come back later on we don't know but in this case uh it's just beautiful clear simplified code now there are a handful of rules around doing this stuff you'll see i've marked process weather as being itself an async function because if i remove that i've now got a synchronous function and this synchronous function is trying to call asynchronous functions and you can see it's very unhappy it does not like that one at all uh synchronous functions cannot just call asynchronous functions it wouldn't make sense you know they don't understand how to suspend their work how to yield their thread back up to the system to do something else with asynchronous functions do they've got a slightly more expensive uh way of calling themselves to handle this ability to suspend themselves however when it is async it can now call other async functions just fine async can call async an async function can also call synchronous functions just fine the fact that you're in asynchronous context doesn't really matter you can call synchronous functions as much as you want to because broadly you're still in that asynchronous context and helpfully this is very very clever from the swift team they've got some very good uh handling of functions with the same or similar signatures and so if you have a library right now which does a particular way of working and they want to support an async version of the same function they could have the same function name in there marked async so the function has the same signature almost except one sync and one's async and swift will automatically choose the async one if you're calling from an async context otherwise it'll call the synchronous one from asynchronous context which is brilliant because you'll see other languages and frameworks have async literally in their function names to distinguish from synchronous versions of the same function and swift doesn't have that which is really really nice so that's a great job there from the team which is great um now what i found is that uh async await the way it works is so similar and it fits really well alongside do try and catch i mean it's so similar in the way it works like you can say try some throwing things some throwing things some throwing thing in one line of code and that one try handles it the same is true for a weight i can actually have try and await or throws an async in the same code handle it all together and resolve those behaviors as you need whenever you need which is really really nice um there is one catch um which you need to be aware of and it'll it'll blindside you at first but when you're used to it it's fine um the order of these keywords is reversed which is cool um and i want to demo this with some more code of course because it's obviously a code driven event let's say uh let's give her this code here question fuzzy herbivore how do you start the async context that's a good question uh and i there are two ways of doing it one is if you're using the new at main uh attribute you could say something like you know hello.swift here if you had uh at maine struck my main thing uh with static funk main async that already works so you can go ahead and call async functions there and it'll be run uh expect declaration is there anyway um you you can call async functions there just fine that works brilliantly um and it'll just boots up that when your app launches out of the box which is cool i believe there is work of foot but i bet it's not in beta 1 to allow async function calls directly at the top level so in theory if it's in here beta 1 i don't think it is in theory uh if i had again main.swift in theory that would work no so i believe uh in future betas that might work we're gonna see um yeah but but later on i'll walk you through examples of this with actual uh ios 15 code using this directly inside say swift ui because that already has support for this built in because like i said api is changing swift's changing all at once is just brilliant another example let's do another example throwing stuff so if we had an example down here of some kind of error loading users uh i'll do error here and then you've asked for too many invited count and dated too long too much information going on if you want us to have a way to fetch some number of users i'll do funk fetch users count int async throws returns string so you can see here this thing obviously this thing is an asynchronous function uh into theory i've just collapsed it by accident there we go it's an asynchronous function and it will potentially throw errors now remember both these things mean maybe it doesn't actually mean it has to throw errors doesn't mean it's actually going to suspend the function just means that it can can do these things uh inside here we're going to say if they've asked for more than three we don't have that many users what is through throw user error dot invalid count and then if we're still here we're going to send back as many users as we can so we will watch check says use async to run the context no please don't um don't um i'll explain more on that later on i this is really fluid stuff folks it's changing very very quickly and um yeah please don't but i'll show you why not uh where's safari here's safari you can go on me this is the swift um source code repo on github if you dig into standard library and then look at the public stuff here and then concurrency you'll find there's a whole section of source compatibility shims to help people bridge their code from old code and new code and you'll find in here func async is here and it's already deprecated so things are extremely fluid right now and that async function is used in various wdc videos and it seems to be replaced by the new task initializer i'll show you later on that might still change you know they've got a really good open flexible approach with these things because so much is changing that they really really do want community feedback and so uh you know get onto the forums you'll see ben cohen's post a thing there saying what's your feedback on this concurrency stuff let us know how you're finding it and they want to hear your feedback so you know get in touch and get involved anyway um work yes here we are again so if you've got more than three requested users just say about so we can't handle it sorry if we're still here we'll send back an array and i'll pass back we have uh anthony we have uh caramel and we have tan and i'll just use uh prefix up to the prefix up to count so that's what one will get like anthony get back to the anthony caramo and then add to grammar tan if you have three that's our simple fetch user's method but it can throw errors that's the main thing and then we'll have another one we'll do funk save those users a string array again it's gonna be async and again it's gonna throw a return of string i'll do let's save users equals users dot joined separator comma and if that is too long save users dot count over 32 will throw another error use error but they are too long else you know actual saving code here and return saved saved users okay so two very very simple functions to get some data and write it out somehow but they're both marked async and throws they are asynchronous functions they must be called from an asynchronous context and they might throw errors uh neither of these things by the way are doing any asynchronous work right async means you know they they have the potential to uh suspend in this case they are not um when it comes to calling these things so this is where it gets problematic uh chris what does prefix do it returns the first n number of items so if we do prefix one return anthony prefix two anthony caramel and so forth anyway uh down here we're going to say there's a funk called update users which is async inside there's our do block and we'll get our users by saying try await fetch users count some number i'll do three and let result equals try a wait uh save those users and then print the result everything goes wrong will catch and print out oops so this is what i'm saying about the order being reversed it will real curveball at first but it makes sense eventually we have at the function definition level the function's type is async throws it is asynchronous it might throw errors but when we call it it's try a wait it's the other way around attempt to call this thing and then wait for it to complete now this went through extensive reviews you might imagine on the evolution system and i think it's fair to say they're right that trial weight does read off the tongue more easily then awake try which is great but more importantly i think it reflects what's actually happening here we are waiting for some work to complete a weight fetching this thing and if it does complete with an error then throw it i suppose the other way around so that's the basis of async await and you're going to find it all over the place in ios 15. we've adapted it in lots of places for example a url session if you had some function down here let's say we had a funk fetch data here you might say i want to use url session i want to try and you know uh read some value out uh contest again air reviews a wait try it used to be a warning but i'm not sure what happens in beta one picture one it is still a warning yeah saying don't do that so yeah try away don't get it wrong around and actu and that's actually it was an explicit choice from the developers you know let's make this enforced let's not allow either way around because they could have let it go either way it doesn't really matter then but i think having a simple strict way of thinking actually removes problems anyway url session and many other types inside the system foundation and beyond have been updated support async await for example you can now say uh let url equals some kind of url i'll do uh https card slash apple.com that and then i'll do data underscore is try await url session dot data or share sorry got data from that url and that's it there they'll go off and fetch the data as it needs to be afterwards an async context by accident there we go um and attempt to handle that you know fetch it sorry for the server go ahead and fetch all apple.com download it somehow into this data and then parse it save it whatever you want to handle along the way uh let's just put an escalation mark in there for now boom so you can see it's that easy now to do these kinds of things you can just say go ahead and fetch stuff and figure out you know there's no more it was data response error is there an error is there a data it's very very confusing and messy it's all gone away and uh yesterday i walked through an example of this inside swift ui uh carl what does it mean when i say in context so you've got to imagine your codes could either be running currently on the main thread where all your ui work happens it's a very privileged position they're running with and it's it's you know that is a synchronous contact everything runs sequentially one after the other right in async context we have the possibility of running in parallel doesn't mean it is running in parallel the the different things um but it means it has a possibility of running a parallel and so we want to keep that separate from our main piece of work you know this is these bits here might be able to run in parallel these bits here definitely are sequential and so it's an async context and in the synchronous context i want to walk you through an example of this using um the uh refreshable i told this yesterday i'll do it again now because it's so awesome and this is in swift ui for ios 15 you can now ask system to have pull to refresh functionality inside your uis and uh it's so very very nice to do because it's built using async await and so um if we had our simple ui here i've got you know text hello world whatever i had a navigation view here and then a list inside this with one two a hundred row in and then text row row uh pavel and error mac os oh yes you're probably right pavel you're probably exactly right um i was using the new url session code in mac os 11. not mac i was 12. i don't risk monterey i'm sure it's brilliant but you know i'm i'm doing streaming i don't want to start catching fire even what it is right now anyway there's a swift ui list of stuff and uh in theory i can press play and see it previewed on the right hand side here uh xcode has been causing some comedy audio problems for me recently uh and hopefully that's not going to come back i know it's better why not blame them too much but we'll see imminently whether i have any comedy audio problems or not why it's busy preparing the iphone simulator for previews i need one of those fancy pants m1 m2 whatever is imac pro um but i haven't got one of those yet i've got my old intel i9 i think it is so uh sadly i have to wait for my mac to catch up with my brain come on mac you can do it show me a preview please all right while it's thinking about its crimes i'm gonna just carry on and say that oh there we go thanks for that yes threatening you launched straight away um we can see a bunch of rows there which is fine exactly how you expect to be um i might want to say this thing has paul to refresh and you do that by attaching a refreshable modifier to your view hierarchy somewhere and then do some work uh yes great i said it is the popping noise when the symbol is running it's spread now to xcode which is uh which is great oh brilliant question from marco pont hi mark i hope you're doing well hope the kids are good um is there a reason why async is afterwards as opposed to preceding the funk keyword this is a brilliant question because it tells you a lot about how the way swift works internally because functions are types in swift they're a typo by themselves and there's a function has a type what is the type of the function what uh values does it accept what does it return are both parts of that function uh signature um not part of the type are things like i believe how visible it is is it private or public for example that's not part of type but is it throwing or not is part of the type and async is also part of the function's type it is an asynchronous function and so having at the end as part of the function type itself makes more sense than stashing it somewhere else because it is literally part of the function itself as opposed to a modifier for the function it's part of the function it describes it and so you have a a parameter that expects to be given an async function you mark that right there as part of the closure you'd have something like you know open close async throws void or something like that right in your uh uh parameter type anyway sorry massive tangent um in here refreshable once you have a fresh blend here you can say something like you know print uh do your refresh work here boom and that's all it takes that's what it takes to get uh pull to refresh working inside swift ui you now just drag down from the top and it will call this function immediately and refresh the ui if you if you scan into what refresh was actually doing if you look at the definition inside uh swift ui i'll drink some coffee while it's thinking in slow motion boom so you can see this thing here expects to be given again right there baked into the function's type expected to given an asynchronous closure it can run and it'll go ahead and run this thing for us which is amazing because what happens here is it will as you pull down it'll reveal a bit of the indicator i'll press command r let's see if it's going to break my audio or not if the audio breaks i apologize you'll you'll have to wait and if it all goes wrong we'll do it again tomorrow because i can't i'm not responsible for xcode audio breaking i'm afraid so we'll see how we get on um while it's loading in slow motion um it's a standard pull to refresh indicator you sort of pull down it's obviously a bit the clock appear pull further more clock appears pull all the way it starts spinning on the screen it'll then call the refreshable closure this function here print do your refresh work here and it will wait for that to finish and as soon as it finishes it will then go back and hide the little clock refreshing indicator so it it knows how to wait for the work to complete which is so important and it's expressed just beautifully here with a very small amount of work here is my simulator and i if you now hear crackling sound the microphone i'm sorry it's nothing to do with me i'm doing my best here folks uh justin asks what about scrollview does refreshable work there too you know honestly it ought to but it does not right now um and so i that's a bug or it's a feature and it will never work or it's not until ios 16 but right now it only seems to work with lists i would say by the way it's quite clever feature um refreshable um you know the fact that it just works out of the box is it finished no it's just sorry mac it's so very slow the fact that works out the box is brilliant because we know we're in an async context we can go ahead and start calling a weight await await await inside here to do more complex work oh here we go so i can pull down here and if i pull get a bit of the clock face and i release boom do your refresh work here appears but only when i fully pull the thing all the way down like that so that's a simple way of doing it obviously in a real example you want actual work happening here this is where you can use the new url session async await values too uh and i gave a complex example yesterday i'll do it again here because it's helpful to see it really happening in real life i say there's a struct called news item which is decodable news item the code was going to load from json and also identifiable so let me show inside a swifty white loop i'll do let id int to satisfy identifiable uh a title string come on hudson you can type properly title string and a strap string and i content view i'll say by default there is one news item private var news equals an array of news item and i'm going to use uh id 0 title want the latest news latest even news strap pull to refresh like that so by default you see one item in there and inside our 50y view we're honest looping over one to 100 we can now say actually i want to have a list of all my news items with each item coming in and for each item i'll have a v stack alignment being leading and first i'll have the items title in a nice headline font then item strap line item come on you can do it i term strap my mac is really not doing well for speed right now foreground color secondary there we go like that so go ahead and show our items in a v stack inside the list of stuff now inside our refreshable we want to do some actual work now do some real async await work we're already in async contact which means we can call a weight functionality here i could say do start a throwing block of code and then make a url in our case the euro is going to be the string of http dub dot hacking with swift.com samples newsone.json that ought to be if i have made some comedy typos an actual url pointing at some json i can now fetch it i can say let data underscore the underscore here is the url the http response i don't care about it here i just want the data so i'll do uh try await urlsession.shared again using the data from option that url so go and fetch it download it put in the data for us to work with i can now decode it i can say news equals adjacent decoder dot decode an array of news item dot self from that data and now all i do is catch any errors down here so i'll say if anything goes wrong in uh the decoding get some nonsense for example uh or we can't get the internet whatever news will be an empty array and i've made an error here it's saying well yep try that's important we try and theory that should compile and run let's find out press command r to launch that code on matt you can do it so one of those news pulled refresh i'll just pull down and release and boing in it comes so it's it's done all the work of fetching it and playing it back and decoding it on the screen immediately with hardly any code all asynchronously i i haven't had to worry about dispatch queue main async whatever nonsense the old url session apis you know not needed anymore this is a much nicer way of thinking which i said we're working much less code for a start it's a big improvement so that's how we have uh async await in you know simple example code you can see the basis of how it works and improvements you get but also how you use it inside real applications now with uh ios 15's improved apis which is great now you might think this is the death knell for the result type which is introduced in swift five so you can say result success array of news items or result failure some kind of error happened here and that's partly true mostly true maybe i'd even say um certainly they knew at the time the benefits of result would decrease when async await hit the language they knew it'd be less important because you know there are things to worry about right but it's still useful result is still useful because it's still the best way to store the actual resulting value of some functionality stash away in the result pass around elsewhere evaluate that in a few minutes or later on whenever you want to at some point which you still can't do this kind of a single weight stuff results much much better at that storing the actual finished result of value and just passing around now uh as you've seen in our code uh i was always wrapping things in uh async functions like this so async function course async function async functional other xing functions so forth goodnight fuzzy herbivore um and that's how it works quite frankly you know async functions called other async functions that's how they work um and in a pure swift approach you might wonder well how the heck do i start doing an async function how do i start from synchronous calling asynchronous um i gave you an example here because swift ui is doing it for us with refreshable but in your own code there's a whole other batch of ways of doing that and it's part of a separate evolution proposal structured concurrency uh oh someone's hit a dislike i'm i'm trying my best folks sorry for doing these free live streams i am doing my best um uh so you might think there's no way of doing uh launching your first async function but there is this particular proposal and we'll get up that shortly and the other thing i think about is and this is very important no part of our code over here our basic example code is designed to run in parallel right this is all asynchronous but not parallel it's concurrent and and and they're different things and the way to think about it is like a single core cpu like you know intel core solo remember those from like the original imacs or intel um and they had a single core right but they could still run mac os 10 and play music and surf the web and even though they had a single core now at any given time it wasn't doing two things at once it wasn't running the network and safari and whatever whatever you know not spotify but it was at the time napster i remember a long time ago it wasn't doing those simultaneously it wasn't running them in parallel but it was able to handle concurrency they're able to pause this thing and do some other work for a while then pause that thing and do some other work for a while so we're distinguishing between being able to run things together and actually running them together they're different things anyway that is our first proposal kind of flown through really really fast next up i want to talk to you about uh another important change is effectful read-only properties and this is a much more advanced way of handling properties now because properties if they're just computed reading properties can be throwing and asynchronous now you can be you know get throws async all in one big mix of functionality which allows for a lot more power and you'll see this comes back later on in our in some of our code now as an example i'll go back to our simple example function over here again let's delete some of this code we could say i want to have a way to load bundle data so i've got my app bundle here and there are files inside there i want to just link it out and use it and we might say first up well there's an enum for all the possible file errors we can have which in our case there'll be two of them um the file isn't there it's just flat out missing or it's unreadable like it's there but it's you know locked or corrupted or no permissions or or who knows what right so it isn't there or is there but we somehow can't read it and now inside of a new struct called bundle file after you make this thing by saying what's the name of the file you want to read so file name is string and then we can read the contents of that file as a property now this thing isn't going to be writable you can't write back to your app bundle it's read only it's fixed in time you only have changes you download updates from the app store sam i am reading the chat hello sam you can't see it there's a chat window on my screen over the xcode thing it's my software is very clever kind of hides it from you um i am seeing it uh yes hello sam anyway we want to read our file but it can't be written to and so it's going to be a read only property it's got a getter inside there to compute the value as we go but this thing might take time it could be a huge file so it takes time to figure out and load it in yada yada so i'll say not only is it read only thing it's also asynchronously read-only plus again the file might not be there the file might be unreadable so it's not only getter and asynchronous it's also throwing it's a get async throws property and now inside here we can say things like get me the url by using bundle.main.url for resource our filename extension nil if that fails we'll do throw file error dot missing heidi you don't need a sneaky way to get a shout out hi heidi get a url if it fails through a missing problem and then do a do block attempt to return uh the string version of that file if that fails i'll throw file error dot unreadable we literally can't read the file if not exists so now we have this struct with a property content which is async and throws at the same time and because it's async and throws we want to use try and await to read that value coming out again so i'll say down here is a new function called print high scores which is async and throws i'll do let file equals a bundle file using the file name of high scores and try await print file dot contents so attempt to read the files contents print out the result and then also uh wait for the finish it could be asynchronous happening at the same time now cunningly just like with try by itself you can shuffle these around if you want you could say print try weight file contents if you prefer to um it doesn't really matter what i would say is that i said earlier repeat it here perhaps um these things stack up beautifully and so you know if you had try some throwing thing dot some throwing thing dot some throwing thing whatever which you can do right now you'd have one try the same is true of a weight one or weight will wait for many many uh things here uh cooper that's not really fair to say uh chris is a wonderfully nice man he wouldn't do that he's a good friend so now we have these uh complicated throwing properties which is great and they're used elsewhere as you're going to see shortly because this is sort of another one of those foundational blocks that swift builds upon to do more advanced things it cause them effectively we know properties and they're very very powerful indeed so let's go on to sort of the main event or one of the main events as it were the next level up how we actually handle concurrency how do we uh execute tasks together cancel tasks monitor tasks and so forth how do we handle this and this builds upon async or weight it builds upon uh these effective uh throwing properties and similar but we don't own any problems sorry it's kind of building up a hierarchy of information here so from simpler to more complex which is great now this is part of a proposal called structured concurrency it's actually technically still in review i asked literally like an hour ago is it been approved yet the answer was no it's still being revised and improved and refined um even though it was finished a little while ago which is great because it means you still have time to go and weigh in and see what you think and you have seen this demoed at wbc videos weirdly with the old syntax rather new syntax um which isn't ideal because it's evolving quickly but that's fine that's why it's part of the fun right um and so uh i'll try and walk you through is the current correct syntax for these things but it may any point just go away and be replaced now uh this is going to require some more functions to work with like fetching whether data and calculating averages and so forth so i'll give some examples up to work with first we'll say that uh we have a way to fetch some weather readings so i'll say there's an enum called location error which is an error and this thing has one value which is unknown i don't know what the weather readings are for that location because i don't know location actually is and i say funk uh get weather readings for location string async throws returns an array of double inside here i'll do switch on the location if we've been asked for london's weather we'll return lots of value so a hundred values a hundred even map and approximately in normal temperatures uh it's going to be double dot random in six through twenty six like that then i'll uh copy and paste a few times and we have case roam again 100 values the values here are going to be between 10 and 32 and then we'll have also san francisco here it's like 12 to 20 so you know quite nice basically and default all other values i will throw location error dot unknown so no idea what it is just bail out and throw an error that's our first function we're working with a second one is a simple synchronous way of getting the nth number in the fibonacci sequence so i'll say funk fibonacci of number int turns in it have our first is zero if our second is one for underscore in zero oops two number let previous equals first first equals second second equals previous plus first and then finally return first that's the fibonacci sequence and a few lines of code right that's it right there now the simplest async approach used by structure concurrency i showed it briefly earlier this is where you use the at main attribute to launch some code asynchronously this does not work in a main.swift file that auto-generates the main uh for you you go across something else like my app.swift for example and now you can say uh main struct main static funk main async throws and this will automatically be run when your program starts up in an async context you can go ahead and and call stuff from here so i might say my readings is try a weight get weather readings for london and then print readings are readings like that that works great today right now you can do that now with at main at the simplest way to be working along with your program obviously it doesn't cover many cases unless you're making many um command line apps but in in theory that's the the easy way of doing it like i said i believe it's also impossible in the future to remove this and have top level code being asynchronous and it'll basically wrap it in a task automatically it doesn't actually work yet but i presume it's coming uh i think i last saw john mccall talking about that on the forums um so we'll see is the answer anyway that's simplest way but realistic you want to use one of the new structure concurrency types which are task and task group for handling things to run concurrent operations individually or in some kind of coordinated way uh shadow facts can you have xcode 12 5 and x go 13 at the same time yes you can you can on i have it right now let's go 125 and x code 13 at the same time um i haven't got monterrey i only have um uh big sir sorry mine went for a moment there oh it's michael mayer i missed you michael sorry that's come along michael he's a good pal um anyway so that's a simple way of doing it but realistically you want to have task or task group like this and um this is where we saw async being used at wdc and right now at least that has been deprecated and that itself was replacing another deprecated function called spawn it's been through quite a lot of discussion which is great by the way it's lovely seeing the backwards and forth discussion improvement refinement today right now it's done using tasks the same thing so when you saw something like uh uh async blah at dub dub um the current approach right now is to do tasks instead and so let's have a go at doing that everything i'm doing in that now so i'm going to say uh that uh inside here we want to go ahead and make some tasks so i'll say uh get rid of this this gap up here and call this thing main.swift again uh i'll say the function called oops print fibonacci sequence which is async and uh this thing is going to use what was async previously is now task we would say let task 1 be a new task and this task will take no parameters and return an array of integers inside there our numbers will be an empty inter array we'll count from 0 up to 50. then for each of these things we'll call fibonacci of that number and do numbers dot append result and finally return the numbers so this whole task here has an empty array of numbers counts from 0 to 50 gets fibonacci of that number adds the array and then oops in in there and added the array and sends the array back now it's complaining because it needs monterey i believe yes it wants to monitor at this point uh which isn't ideal but that's the correct syntax i'll probably fuss it with um one of the tool chains let's try this one if it's fragile more modern it might still complain that i'm not a monterey but you know it's all right anyway he'll have a little think about that in the meantime that's how we get value back and what happened is task one will now my mac is now beach balled i've dared a switch for different different swift version before i get a beach ball uh uh on beach ball there we go um i've now made the task it's gonna go off and do its work to calculate all these results for us in one go and when it finishes down here after the task is done i can say try and get that value coming back now this is where those effectful read only properties become really really useful because we can say let result ah xcode is completely beach balling now cool it's thinking at result there we go at one equals a weight task one dot value wait for that effectful read-only property to come back and that's where it's marked as async so it'll take some time to come back and when it's done this line will finish its result will be in result one for us to use in this case an array of integers so i might say something like uh print the first 50 numbers are whatever and then the result one like that so we've got lots and lots of function calls being put inside this task running it'll go away and just do it right now i've had to be explicit here and say this task takes no values coming in our returns and arrangements just coming out again um if you have very simple tasks that isn't needed because you can just ditch it entirely and just do the work directly without having to say exactly what it is um in this case you can probably see at a glance um we're basically going from zero to fifty calling fibonacci on each one and so all this code can come out and really you can just write 0 to 50 dot map fibonacci like that to get the same result and that way i haven't got to say the exact functions type for the task because it knows it can read it from here now it's it's whinging because uh it's it doesn't like the the the version trust me that is the current correct syntax for making these tasks that's how it works i might commercial official tool chain perhaps i'm expecting beta2 or maybe beta3 you'll get this version of the code or let's get a snapshot from the site anyway so that's what we're looking at give me this task go ahead and do the work and give me the value back using these effectful read-only values here wait for it to finish and then put it into there now what will happen here is behind the scenes this task is going to start running straight away like you know here the task is gone it's all off busy doing its work right and our code carries on running wherever it was whatever it was and as a result it's gonna over here do its work do its work and eventually the weight will go ah it's ready and read the value out for us which is fantastic now what is happening internally to task is we're passing it some work to do as a function or in this case a closure of work to do and the task starts running that work immediately it doesn't hang around it goes right go let's do a task let's get to it right as a result this is an is a non-escaping closure it's run immediately which means if you had one of these things inside a class you don't have to say self dot foo self dot bar self dot baz because no chance of capturing happening here it's run immediately and discarded so there's no requirement to have you know weak self or similar now when it comes to reading the value back out again that's where await task1.value kicks in this will make sure all those calls are fibonacci finish fully the whole task finishes fully and only when the output is ready does it go into the result to read it back out and this is really powerful you know you haven't got to worry about you know watching it or marching yourself it'll just take care of itself for you you just say a weight and wait for it to finish fully if you don't care what the task returns you just want a fire and forget function to run do a stinging and skedaddle um you haven't even gonna store a task anywhere just use task by itself and it will run off and do the work for you and it'll make sure it finishes before exits because that's what it's trying to do here now if there are errors being thrown you can handle that as well why do i look younger ask colin all the coffee i have no idea coffee ages you surely anyway if you have multiple things here and maybe some are throwing or errors happening or whatever you've got to handle appropriately this thing will gain extra powers right now it is an async property but it can also be an async throwing property as well so we might say i want to run multiple calculations here uh i'll do async throws again we'll have our first task i'll just copy and paste the first task let's do this whole thing here um you go into here like that and the second task is going to be another task with try await get where the readings for run throws there we go so we've got two tasks happening now one of which is throwing and we can now say let result two equals try a wait task 2 dot value wait for it to come back like that but make sure we try any errors here and handle appropriately now this whole thing is marked as throwing so it'll just bubble upwards at this point the next level which is fine you can then at this point know that both values are back the first numbers are this and print roam where the readings are result 2 like that so we've now got two pieces of work happening uh in in parallel i'm gonna just launch task to start running wait for them both to finish and then print out their values now i i would expect that i haven't tried it but i expect if i had this whole thing here in my swift ui project let's paste it into here maybe i have to steal those methods as well where are they uh this one and i think all these functions here perhaps you can all command you can all come in there we go uh this will be no enum shouldn't be in there no it's fine this will be slightly closer there's a few complaints now because i'm using the io15 sdk if i switch across to the new tool chain well that with iodine sdk let's just find out i don't know where to find that isn't it i pressed build my mac if my mac beach balls again you'll just have to wait uh someone asked about dogs the dogs that lord moojos about dogs i think it was um lord mooch i'm sorry the dogs have been and gone already they've had their fill of treats they might if i might make the treats sound they might uh dogs no it's it's i don't know what time is anyone in the uk what time is it 10 past 11 in the uk so they're probably downstairs asleep somewhere um so they are clearly not interested in treats i'm afraid so lord mooch you have to miss out on dogs today by the looks of it uh it's building this in slow motion it's probably not terribly happy that i have the ios 15 uh sdk backed up by some random swift uh main snapshot i'll let think about it for a while anyway so we've now got individual tasks being created just randomly unstructured go ahead and do a task please go ahead and do a task and then wait for it later on when we're ready to wait for it it's a nice way to handle work being executed in concurrent ways when you have to customize somewhat there are lots of options you can add into this you could say for example i want to have different priorities i want to have a high priority task when you make it that's available right there in the task initializer or about 3 45 am respect lewis no it's not an m1 it's an interline nine it's like a year old 18 year old 18 months a year old i've lost track time's a blur 18 months old at this point uh and it's uh aging slowly that's for sure um anyway um what are you saying ah priorities yes you can make the tasks with parameters you could say i want to have this with various priorities and you could say high default low or background and these more or less match up with the traditional sort of uh darwin style ones we're used to uh usually initiated as high uh utility is low and then uh well you don't get user interactive that's been blocked away um that's not for us to use anymore that's you know main thread only but you can use either one you can use a sort of traditional one or use the modern names you prefer uh this is not even building with the custom uh tool chain so let's not do that it's a bad idea um you have to stick with my uh wonky build on my other screen instead anyway um just survive with these warnings they're perfectly fine they are correct it's just xcode being useless um right can i maybe activate the main one last try let's try that one it's thinking it's your last try it's go for i switch back just carry on cody and talking which might be best uh what do you got m1 i think they're brilliant i'd love to get one i'd love to have an m1 imac right now and i don't i'm annoyed anyway um so we have tasks we have task priorities which is cool you have various extra functionality you could say uh sleepless tasks for a while it's currently measured in nanoseconds which is basically extraordinarily hard to read because one billion nanoseconds is one second so you've got a one zero zero zero zero zero zero zero i've got mac os versions now um oh there's a there's a hack you can put in place a build setting which i don't know if i cut off my head you can force it that off with a bill testing to say don't warn me about mac os 999 um let me try and find it real fast in safari if i can just grab it oh come on out of the screen i run the screen rats oh anyway i don't know you can google it but if you sign up with the option to disable uh version availability let me know and i'll enable it so get rid of the warnings and errors anyway you can sleep your task for x number of nanoseconds you could say have it been cancelled or not using task.checkout cancellation and if you have been cancelled or throw a cancellation error if it hasn't your code carries on so you can avoid doing unnecessary work you can call task.yield to say go ahead and do some work uh elsewhere in the system for a while if you want to have a really tight loop for example and you don't want to chew through too much cpu time yield some time elsewhere anyway um cancellation matters you know being able to say my work isn't important anymore or uh that task isn't needed anymore whatever just bailout and you can do that using cancellation so we might say for example um i have uh these warnings have really annoying me you can absolutely do it as a way to do it um uh i don't recall what it is i'm afraid so if i had like uh swift disable availability checking um blah blah blah blah blah blah go away none of those not that it's a build setting it's a front end built i think i'm sure it is none of these no no no no nine nine nine nine sorry folks ah this sounds good concurrency api not available there we go that's the one there i thought where is it x front end horror show that's a one look at that boom so don't warn me that i'm not on monterey so i was saying yes i know i'm not monterrey please just do it anyway uh build settings and other swift flags i think others were flags maybe other compiler flags let's just search for swift in here shall we swift blah blah blah blah blah oh there's a flag let's put this one here let's add that into here and see if that makes it significantly happier stop screaming at me is what i'm trying to say it's going to sit and think it's the same thing for a good old while hopefully that will get rid of the major errors in my code because it goes correct it's just it's convinced it's not correct so i'm not a monterrey yeah so bill's fine now there you go okay so you can now see it's working correctly which is great anyway uh next up we have a cancellation of stuff let's say we want to have a task you can cancel i might say uh funk cancel sleeping uh task is async if paul can google it live stream all my securities go away i google all the time folks often google my own stuff i can't enroll in my head front end swift flags do not stay in my head i'm afraid uh yeah anyway um we're gonna make a task we'll say my task is a new task that takes no params and returns a string and i'll print out the word starting and then we'll say await task dot sleep and i want to sleep for one second like i said this thing is measured in nanoseconds and so i'm gonna say one zero two zero zero zero zero zero zero to mean one second after the one second i will do try task dot check cancellation like that attempt see if we've been cancelled or not and then return done that's our task and it'll start running immediately it'll start go it's already happening but we're going to cancel it while it's sleeping so i'll say task dot cancel bailout immediately and now we'll say do let result do sorry let result equals try a weight task of value and then print come on result was result and then we'll do catch print task was cancelled so what's gonna happen here is when we call task dot cancellation yes it is static it's all static these these methods um we say check cancellation have i been cancelled or not and in this case it will realize ah i have been cancelled it will immediately throw a special cancellation error yes don't do any more work so it won't return done it'll bail out saying i was cancelled but we don't know that because that whole throwing thing is wrapped up inside the task it only actually throws the error down here where we try and read the value back out from the task that is the one that's throwing that's the one we're going to mark with try and it's super smart here understands we've got to mark with a try it knows this thing is going to throw errors because we have this try line in here it's going to throw errors right and so we know where to handle appropriately and put the right thing in here and so this will print out all being well uh task was cancelled again not running monterrey i'm very much not running monterrey um but let's find out who's gonna run anyway because you never know a bit of fun a bit of a on screen on stage crashy like fun times let's find out waiting to attach in slow motion normally this max fairly fast obviously xcode plus simulator plus live streaming not so much but that's all right i'll get me an m1 m2 mac pro one of these days no imac pro i can't afford mac pros imac pro can afford maybe from lucky it's just thinking it's not getting anywhere i'm afraid but that's that's how it should work that's the point of this thing okay yeah didn't get anywhere yeah nothing i haven't called a function that's why i'm called count sleeping task let's put in here uh my main and then down here let's call the damn thing uh at main strike main static funk main async and then we will call cancel sleeping task i'll work much better always call your functions folks otherwise it won't do anything an important life lesson right there let's try again this time calling the actual function we're supposed to have in the first place bang yes now it's not happy he hasn't got libswift concurrency i think there are hacks again for that you can put in place um to try and get the thing working now uh where was that sort of forum thing blah blah blah blah blah none of these probably no probably not that one no no no there'll be a there'll be a way of saying don't load the libraries um which is really you don't want to do that um in production code um but for just noodling around that's fine right don't run the code unless you're running monterrey it's going to explode in your face anyway so we can use try weight task.vi to read the resulting value of the task or handle the error at that point and if you don't want to handle it just yet you can instead say let result is task dot result and this thing will uh give us the result form of the task and now there's no errors to handle we haven't got to have do and catch in here because the error still hasn't been looked at it's still sitting in there it's like schrodinger's error is there a result value success or is there a failure error in there somewhere we don't know at this point but we get to evaluate that later on so swift's result type is still really really useful you'll see it right here this thing uh is useless not helpful at all this thing will be a result uh string error like that that's what it'll be if uh co-completion worked in in this hacky version i'm running here um that's what they'll be as you can pass it around from function to function of function how much you want to until you're ready to evaluate it at which point find you can look at it and use it so the tasks create one they start running immediately wait for them to finish and then respond however you want to for more advanced work that's where you start creating task groups these are collections of tasks that work together to produce a single finished value of some sort now there are lots of careful rules around using task groups and i think swift enforces them all for you like it stops you screwing things up it's really really good at avoiding problems which is fantastic because any kind of numpty mistakes i would make someone numpty it kind of spots and says no you can't do that no you shouldn't do that no smack don't do that whatever it it does help you out a great deal so let's zap some code from here stacks of boring stuff um we'll make a a task group we'll say i want to print a message print a message this is going to be async and this thing is going to attempt to make a string one string by calling await now what we're going to call is a function called with task group and this thing creates a task group of as many tasks we want and it will work together to finish them up and send back a single value in our case a single string and one of the many protections swift puts in place for you is you get access to the task group inside this function it passes you the new task group so we'll say await with task group and this thing is going to build a string at this job it'll give me this the group coming in my new task group now return a string and now you can go ahead and give it all the work you want to do you can say i want to get string from the local file system get a string from the server get a string from my pal down the road whatever you want to you can return strings however you want to each particular task inside the group fetch the string wherever where you want to in our case we'll just do group.async and do hello directly in there so there's no fancy code to turn hello straight away and the reason we're doing this is because if i say group to asynch hello then group the async from and then i'll copy paste a few times like this a task group like that so i've got five uh tasks i have my group each one give me a different string coming back i could then say i want to collect those into a single value so i'll say our array is called collected i have a string array i'll then await every value coming back from that using for a weight value in group collected got come on append that value and we'll end up with the string array of hello from a task group i can now uh return collected dot uh joined separator space so i get back hello from a task group and after task group finishes i'll have a real string i can do print my string so real simple five individual tasks part of one task group they all start running straight away they all start doing their work hello from a task group we then piece them together to a single array and join it with spaces that looks great it looks simple but in practice when you run that you have the problem i mentioned earlier now you have two problems you might get hello from a task group you might get from a task group hello or group task from a hello or who knows what because they're all running at the same time they're all running asynchronously and so they're complete in their own order we don't know all they're gonna run in that's where you're in race condition territory the chance of getting hello from a task group are pretty darn slim and so uh chances are you don't want to do that that's a complex way of thinking for your brain try and order things and then get it exactly right it's just not gonna work it's just not gonna work and there's actually a better way of doing this i'll show you later on um using async let bindings instead but the point is that the all these tasks in the group their goal will get to his here's one value here's another value another value as a group you then resolve all the values into a single value and send it back somehow now if inside your task group you are running throwing functions then you don't say with task group instead you say with throwing task group and now you've got to use try a weight do stuff uh you know we can't just do a weight anymore it's for try awake is it might be handled somewhere inside here right and for example we might say so again you know try wait here i want to get an array of lots of values from all my weather reports so i might say for example down here let's get rid of this line here let's say funk print all weather readings is async and then do i'll do uh print calculating average weather let result equals trial weight now with throwing slow so slow task group of array of double dot self so each one of the tasks in my group will return an array of doubles my group comes in i'll pass a string back and inside here i say add asynchronously try a wait uh get where the come on laptop you can do it readings for london that returns the array of doubles for the weather readings for london so that task will get back in the red devils i'll then say group async the same thing for rome and then group async the same thing for san francisco francisco like that so we now have an array of doubles from london an array of doubles for rome array of doubles for san francisco and what we can now say is i want to put those into an array of arrays and so we've got realistic the array of arrays right now we want to try and get these things into a single array of doubles so i'll say let all values equals try await our group dot reduce so i'm going to get out of our group which is an array of array of doubles so remember london's weather readings are rare doubles roam rare doubles have just got red doubles together it's an array of array of doubles we can reduce that down to a regular array so now all values will contain all numbers in one flat array eliot getting a headache hey i said the beginning if you hear the beginning this is hard stuff it's hard stuff there's no way around it it's hard stuff that's good headache sure it's working sort of anyway i can now get the average worldwide temperature by saying uh all values reduce zero plus divided by uh the double form of all values.count and finally return uh overall come on you average temperature is average like that so let's break it down step by step this thing is going to create a throwing task group a task group that is going to throw errors inside it somehow each one of the tasks inside there will return an array of doubles inside there what do you want to do with this well rome ray of doubles london red devils francisco a rare doubles and so forth the whole group therefore will be not double but an array of array of double like that we then collapse it down to a single array of all values in one single dimensional array and then that should be a dot here sorry then sum up all those values get the mean average and send it back as a string that's where we are now so now we have inside result this will be our string saying overall our temperature is some number and as mark's asking what if these things throw well i haven't made my throwing task group handle those errors i haven't asked to handle them i want to handle that somewhere else you could handle internally if you want to it's down to you you'll just cancel the other tasks and similar in our case though i want to handle that outside the task group like this i could now say no matter what goes wrong here catch it all in one place i'll just do print error calculating data like that so i've caught the errors from the whole thing in one place externally so we've got each of these calls to async inside the group again and again and again happening here if the group succeeds this will all run return back the string put it into result and we can now print it out we could say print done with result but if it throws an error reading the values out any point of things throw an error we don't want to handle that we bubble it up to outside the task group to handle it there instead it's a great way to do lots of complex work and wait for it all to finish fully before combining them somehow now if you want to you can say to your task group actually just bailout just just give up you can just say cancel all at any point or you can say when i'm adding work don't just add the work add the work add the work only add the work async unless cancelled so don't add the work if i am cancelled so you've got a lot of fine grain control over your code sam asks when would you use this like if you had lots of work to do fetch some data pack some other data fetch third data you know load an image decode it add this lots of complex pieces of work but they've all got to be joined together somehow then you'd want to do this kind of work for example three different pieces of network data three different images being loaded or rendered three different whatever is you're working with happening but wait for them all to finish then combine them and use them somehow it's extremely common actually in applications however there is an easier way to do this this is the the really careful structured approach it's a beautiful way to get exact control over your functionality there is an easier way and i'm going to delete all this cocos tons of code already sorry i type a lot let's go ahead and just zap all this code now there you go all goes away i'm going to say i want to have multiple pieces of data for my user i'm going to say that there's some user data has a username string and has some friends a string array and a high scores table for the game they're playing which is integrate like this and now my code i'm going to write three separate functions that will load those pieces of data the username might come from the keychain the friends might come from a net request the high scores might come for another request or from persistent storage or who knows where they're loaded somehow i don't really care how so i'll say funk get user is async returns a string what's going to return it will just turn taylor swift for now okay but obviously in a real thing fetch from the internet the code from jason i don't want to do some complex work here to load user later somehow graphql call there you go cool kids then we'll say funk get high scores again async returns it into ray again you do some complex work here to get values i'll send the value back immediately the answer is i'll do 42 23 16 15 8 and 4. like that our third function func get friends is async returns an array of strings and i'm going to send back uh hardcore string of eric maeve and then otis that again it async do whatever you want await some url session call download decode whatever you want to it's your code here do complex work i've hard coded three values here now if we want to make an instance of our user data we need to have the username and the friends and the high scores in order to work correctly and they all come from three different places personal storage keychain internet i don't care where all different places we want to stitch them together somehow into a single user and we can do that by saying funk print user details async then async let user name equals get user and async let scores equals get high scores high scores then async let friends equals get friends like that so go ahead and start waiting for these things to happen do this work now now it's whinging at me because i haven't enabled experimental time that was an option there wasn't it maybe turn on the forums perhaps one of the flags you can switch on enable that's the one enable experimental concurrency love it let's do that actually experimental sounds great uh build settings and swift flags to be enabled i think swift there we go let's just poke it on in there so it doesn't warm me too much boom is it x front end it is sorry sorry the x110 that as well x front end that as well otherwise it'd be very unhappy there we go okay in theory that'll be happier so saying async let get user async let's get high score didn't escape friends three times here and this only works if you are already in an async context so you can only do this if you are currently doing async work here and now you can go ahead and start using them you can say i want to read them back in do some work whatever you want to and pull them together however you need to i might say let my combined user be await user data come on you can do it use the data code completion not happening cool um name oh there you are it's happening now for items let's load of the game xcode use data come on come on no there we go okay username friends is friends friends is friends and high scores is high scores and then i do print hello my name is user.name and i have uh user.friends.count friends boom so all three of these functions will be running fetching the data from wherever you want to around the world device are nowhere around the world and we stitch them all together sorry scores here not high scores we stitch them all together with a single await call await all three of those things to finish and return a value and what i call it user dot username sorry stitch them all together into a single user data just by saying await and it will do the rest of the work for us it's really really powerful stuff even better if these things happen to be throwing then you have to say uh try only when you start using it you say async let do the work and then push back the try handling until you try and actually read the value back out again so you can handle the errors later on when you actually need the value out if you want to so for example again uh lots of examples here love example code if we had uh add a don't do this if we had an asynchronous fibonacci uh number sequence generator um i mean i i made it clear don't do this it's a bad idea um and you'll see why a second um it is hopelessly naive um we might say enum number error returns an error uh case out of range i don't support too many here otherwise mackle really really hard freeze up um we'll say in here i want to do uh fibonacci again baba nachi of number int async throws and this is going to call itself recursively using a async or weight async let every single time and it is not efficient at all but you get the idea if number is less than zero or number is greater than 22 so no you can't go negative obviously it doesn't work i go too big of my mac will freeze up i'll do throw number error dot out of range uh if we're still here i'll say if number is less than two brilliant return number because zero and one have to be zero and one otherwise we'll use async let to call fibonacci of our number -2 and then acing let second equals fibonacci a fibonacci of our number -1 and return try a wait first plus second like that um so we're calling ourselves recursively without memoization using async this is going to be deeply inefficient right you really don't want to do this um so yeah please don't um but the point is that we can handle calling asynchronous throwing functions here very very easily if you want to and then just handle that in one place both of these two things can throw we only have to handle a throwing in one place you don't say async let try let's try again and again and again you gotta push it back to where it's actually needed which is really really nice um so at this point i've been talking now for quite a long time an hour and 40 minutes right and we're only about believe it or not about halfway through the changes in swift55 i mean it is just vast so many changes in one language update and they're complex like i said they're complicated changes do you have the power for more if you do i'll i will happily plow on in with even more swift five five because there's so much more to come including things like actors and cg float double bridging and more in the meantime i've got my uh caffeine free diet coke other colas are available i'm gonna pour a glass of that for myself so you can hear me belching comically down the microphone sorry i didn't a drink i'm talking quite a long time it's getting quite dry well you're still here you are clearly a glutton for punishment you had your chance to run away yeah elliot you think you're fried you try teaching them the thing is tomorrow i want to do things in the new in ui kit because there's stacks and stacks of things changing ui kit as well so yeah i mean i can just keep on talking anyway the point is you know only a fraction the way through and there's still much more to come because swift five five is really changing a huge amount all right mostly folks saying yes carry on so i'll just blindly continue and hope for the best okay let's go ahead and clean up some codes getting really messy now there we go much better okay um swiff5 has a lovely way to adapt all style completion handler code to new style async await star code now for objective c all of ui kit all of spritekit all of you name it kit behind the scenes it will automatically do some really cool bridging it'll take completion handler objective c code and bridge across two async swift functions and that's clever but what's like wow is it'll do the reverse as well and so if you write an async swift function it'll bridge it into objective c completion handler code automatically is just amazing but there are many times when you have completion handler code you want to leave alone like it's not yours it's someone else's code or it's complicated code that's used in lots of places you know i touch it right now i've got other problems to think think about and in this case you can do a little bit of bridging using continuations so for example if i had a function called fetch latest news which is completion handler escaping takes an array of strings and then returns void this will doesn't work go to the internet download some stuff yada yada yada yada send back the values i'll just do uh dispatchq dot main dot async and call the completion handler with uh swift 5.5 released and apple acquires apollo for reddit that is not the uh graphql company um not true by the way sorry christian um that's a fairly traditional sort of completion handler thing i expect to be given an array of strings at some point and return nothing at all to send back that value let's assume that is your function right and that's either you use a lot of places you don't want to touch right now or it's someone else's function you can't change very easily but you want to use a new fancy pads a single weight in swift 5.5 you don't have completion handlers anymore you want async to wait and so swift gives us the idea of continuations the ability to make a little bridge to adapt an old api to a new api from completion handlers to asynchronous functions and we can do that by saying i'm going to make a little wrapper called helpfully funk fetch legends news this takes no parameters now because it's going to be asynchronous which means it will return its array of strings directly no more call in the completion handler to send it back directly it's an asynchronous function but we want this thing to call fetch latest news with a completion handler and that's where this continuation has come in we can say await with a checked continuation continuation this thing i want to pass this thing in some code to run and it'll give me a continuation which we're going to call when we're ready inside there we'll call our old api we'll say i want to call fetch latest news with some items coming in and inside that continuation dot resume returning those items like that so we're telling it yes take our exact same api we used before fetch latest news with a completion handler closure at the end but wrap around it this continuation so we can end up with a truly async function in swift 5.5 asynchronous world and we now get all the new async await behavior without having to change our original function we'll put a little wrapper a little shim to temporarily bridge us over to where we want to be so we can now have something like funk uh print the news is async and then do lead items equals await fetch latest news and then for item before item in items print item like that and it'll do all for us so we've bridged uh my print news parents here we've bridged the old api style to an async await star instead without having to rewrite our code it's really really nice there is one thing that i messed up i wanted to show you which is really cool um it's in xcode 13. if you say for i term boom it creates a singular version for you all right so i just typed literally for it it does the rest it says oh items is plural singular is item you want for item items and i did it's brilliant great great xcode feature really nice xcode improvement so these are continuations bridges between the old world and the new world they're really really nice but it's called a checked continuation because swift's gonna check things on our behalf at time it'll make sure we aren't getting things wrong because you've got to do something with the continuation you've got to say hey here's my finished value i'm done carry on working here's my value like i'm doing in line 19 right here if you forget that you've got a leak you've got this thing staying alive somewhere without returning you've wasted the data your code's not working the way you expect it and so you do that swift can say hey no there's an error here or a warning this is a bad idea make sure you always use your continuation similarly if i had some logic logic here and then call resume again it's a serious problem i'm trying to send values back twice isn't allowed and so swift with a checked continuation will actually have an error it'll go bang don't do that stupid idea you know it's a illegal operation okay the dogs have now arrived lord mooch took you a while hey dogs took you what half an hour is it beauty sleep time perhaps come on yeah comedy comic relief break come on push up we'll go one where's luna gone luna where's the other dog well that's just come on good job come on up good dog yeah all right so swift going to check these things for you i use them correctly i call them exactly only once ever not twice not nonce no never right and so it'll check them for you now there is a cost to doing that it's doing some extra work for us behind the scenes and as a result if you're super sure your code is correct and you want to avoid that runtime cost you can say not check continuation but unsafe continuation and this will no longer do those runtime checks on your behalf you can call it twice you can forget to call it and good luck i mean it's your own fault quite frankly the the nice thing is they're both called in exactly the same way the code with unsafe or with checked the same way return the value same parameters going and so forth and you can switch across from one to other very very easily and so i expect most of us will use checked most of the time a handful of folks will go check check check check checked ready for release now unsafe because they want the extra little performance boost just to make absolutely sure um so that is continuations a lovely feature to bridge the old world of completion handlers and the new asynchronous world next up this is where things get interesting swift five five introduces the concept of actors which is used in a handful of other languages and i've used none of them i've used none of the other languages akka and similar none of them and uh helpfully the swift team appear to have hired from akka say hey do i come over here have another go at doing our stuff and as a result there's been some wonderful work towards actors and the implementation is really really nice what they are sorry my dog's got hiccups now oh eat your treats slower next time actors are effectively classes right we can create them as classes but they are designed baked in fundamentally to be safe to use in concurrent environments so you cannot make a wide variety of common mistakes with them and even though swift five five introduces a range of gigantic features it's not swift six it's swift five five i don't know why i expect it's why because it's a non-source breaking change it's ben sherman hi ben how's it going in a screencast go check him out next screencast.com um swift six i believe is more likely to introduce source breaking changes because of the way they handle this isolation of data five five does not and that's why i think it's called five five rather six but they're really important yes there we go uh uh conrad uh kotos i think he called himself uh on on twitter uh who did come from akka and he's it wasn't it i have so many talks here to shame us hoping to see him a talk i think he's based in japan which is probably why i didn't see any talks anyway um actors they're like simplified classes that are safe for concurrent uses and it's really really powerful here because swift at the compiler level will make sure you don't share mutable state in your actors automatically and it helps eliminate a wide variety of bugs literally at compile time it's absolutely beautiful as an example let's think of a simple class example there's someone who likes collecting cards here like this a collector of cards and they've got a deck of cards here which is a set of string all right that's the cards they're collecting right now and there's an initializer with deck set string and i'll just do self.deck equals deck and what this person is going to want to do is have a transfer method to receive a card coming in and a send method to send a card to somebody else they're collecting card they've got a trading card meet another collector send from a to b and so forth so i'll say we've got a transfer method which takes a card string and as dec dot insert that card we're also going to have a send method to send a card to another collector so i'll say funk send a card which card is selected to a person another risky collector and returns bull now if our deck contains a deck contains that selected card brilliant if it doesn't though send back false straight away we can't do the trade we haven't got the card you asked for if we're here we have got the card we can do something with it we will first remove that card from our set we'll then call person dot transfer card send that card to the other collector and send back true and this is how we could have a simple card collector i've called it risky because it is risky there are all sorts of problems with this now in a simple single threaded environment this code's basically safe we check do we own the card yes we do remove the card transfer to the collector say it all worked brilliant but in a multi-threaded environment there's multiple things running in parallel right now maybe multiple trades happening right now we have a race condition happening right here or potential race condition at least and that's again where two parts of the code will be trying to compete to see which one completes fastest and it means several parts of our code will affect the actual results we get think about it we call send to a person twice on two different threads with the same data the first thread reverse you right first thread yeah first fret left and right the first thread here goes do i have a card yeah got the card brilliant it goes to this line of code here it then the the second thread goes do i have the card yeah i got the card brilliant it goes to here so they're both on line 24. first thread removes the card oops transfers the card the other other player the second thread attempts to remove the card can't because it isn't there anymore but so silently fails and transfers it anyway to the other person so we've got a race condition happening here they can both try and compete to see which one wins and they both have the possibility of getting different answers depending on the speed they run if you know contains runs at the same time one might fail or might succeed they both might succeed who knows what it's a complete mess in in the situation what'll happen is we'll transfer the card twice we'll actually create a new card right we've removed it once transferred it twice from our data and if this is a particularly valuable card i believe black lotus magic the gathering for example is a very very valuable card they've got a major problem and of course anything you know the classic example is bank accounts um same thing that you don't have money being invented it's a bad idea actors solve this problem by introducing the idea of actor isolation all the stored properties and all the methods on an actor cannot be read from outside the actor unless they are performed asynchronously and the properties can't be written to at all just don't do it right and the asynchronicity the async behavior isn't there performance that's not its goal the point is how it handles it swift will pass the request please transfer stuff whatever it is please send a card it'll pass that into a little queue like a message and say you know go ahead and do this when you're ready and the actor will ensure that only one piece of information is being processed at any given time only one thread is using its later any given time automatically we haven't got to worry about it at all it's really really nice and so we can say this is no longer a class it is an actor i'll call this thing a safe collector this is much much safer you can't go wrong anymore right uh so we have uh download no it wouldn't crash you can remove this thing from set and it wouldn't do anything at so no it wouldn't crash so we now have this thing and it's telling us straight away wait a minute you're trying to transfer this on an actor isolated method you can't do that you cannot do that unless you uh are calling on yourself an actor can do it likes to itself but to do on another actor we've got to make this whole thing asynchronous we cannot do it synchronously anymore so our first thing here is an async function and we're going to await transferring the card to the other safe collector like that so we've made a handful of tiny tiny changes here we've got this new key word here actor this is what in fantasy pants compiler land is called a concrete nominal type we have structs we have enums we have classes we now have actors they're a top level type like that when we want to work with data from an actor we have to be in async context so our send method has to be marked async plus the transfer method must be marked with a weight we have to call the weight this won't run immediately necessarily it might be immediate but it might also take some time because some other threads doing some work in the other actor right now so an actor can use his own data as much as it wants to it can read my value deck remove here that contains here this is all fine that's my deck this is all good but when i want to talk to a different actor that's when it goes asynchronous and without those simple changes swift will ensure that all actor isolated state will never be read concurrently every read from like three things happen at the same time oops let's just ban house of pain because they're clearly a chump anyway um anything like that remotely has to be done asynchronously that's how it works right it's another person's data we can't just read it directly and it's done at compile time it wouldn't let me call that directly it knew this is a bad idea you've got to use a weight here automatically so the compiler is checking it all for us just fantastic now like i said they're basically simplified classes sam i don't wanna use instagram for pictures of code no i'm on twitter okay use twitter man um they are both reference types are intentional they're designed to be shared in your program to be to be you know shared state that's the point of these things but the safe shared state unlike classes with the unsafe shared state but they can have methods and properties initialized subjects and more they have all the same regular swifty functionality that classes might have except they cannot be subclassed can't have inheritance class actors down the line at least not yet they can if you want to conform to protocols they can be generic plus if you have methods that are static or properties that are static they have no idea of self therefore there's no isolation they're just pure functions as far as i'm concerned why isn't transfer method marked as async it it's automatically going to be async that's the point of the actors um uh who was it eternum but it's a the point of the action is using any of these things remotely makes them async it just seems rather um annoying to having to put async everywhere because remember the actor can call its own functions synchronously that's fine we don't await those only other things has to be called uh with a weight i would say i did see some discussion that maybe they're thinking about possibly adding actor inheritance the future um it's like it's not in there now but they're not trying to like ban it right um so there's no need for final there's no convenience required initializers and nonsense overriding that's all gone away right the much simpler beast at this point and helpfully also all actors conform to a new protocol called actor which is good because you can actually use that to restrict parts of your code you can say actually this function here takes some kind of actor which is cool uh the the best way i've heard to explain how actors differ from classes is this actors pass messages not memory so uh they they say hey please do this please as opposed to sort of poking around and properties and strings integers and so forth and so rather than sort of nudging around and changing things or calling their functions directly they say please give me your value please call this method whatever and the swift runtime handles it all for us uh pavelpower asks are they reference types yes they are that's the point they're designed to be shared as a point of actors okay so that's actors in a in a nutshell but it goes further than that because swift 5.5 introduces the idea of global actors actors that are available uh anywhere you need them using special marker now in theory you can make your own global actor if you want to um in practice honestly i think organ is the one built-in shared uh example which is at main actor this thing here is absolutely brilliant you can mark properties methods or whole types with at main actor and swift will make sure for us out of the box whenever you call that method for example or anyone that type it'll run on the main thread it's really really nice for example we might have said uh there is a sort of classic example of something you want in the main thread if i had an old data controller class i want to save stuff here we don't want to have multiple saves overlapping at the same time it's a bad idea so we want to make sure we're on the main thread when we call this function we would say guard thread dot is main thread else return false so refuse to even work unless we're on the main thread right now and then we'll do print saving data and then return true so you've saved data to disk basically the kind of thing you again you don't want to have being called several times at the same time because it's a disaster from corruption everywhere right make sure on the main thread and then write it out that works but with this new main actor we can actually make that whole code much much simpler we can say instead there is a new class new data controller and this thing is going to be at main actor funk safe i'll do print saving data and that's it it's it will make sure when you call save from anywhere in your program it will always happen on the main thread no more work required if you want to say actually this whole class is going to be a main actor class great everything inside there will now always be called in the main thread it's automatic now obviously again this is an actor behind the scenes doing some work for us what's going to be required is when you want to call save on your instance you've got to use a weight you know push this message into the message box please save on the main actor it'll do its work on the main thread eventually and say yes i'm done but you've got to wait for it to come back automatically uh and that this actually this main actor i'm not sure we'll see it perhaps if it's going to work no um the main actor is actually a struct the main actor struct it uses a global actor keyword to make it an attribute sorry to make it into a uh one of these main actors things but it's a struck underneath hood um as help because if you want to you can actually call mainactor.run so if you had some work here you might say main actor slow motion dot run some code and that code will be run on the main actor on the main thread right uh sorry you gotta await that obviously uh yeah so it will have to emit a whole thing you see how it spread so easily can't you the point is that um you can go ahead and call that on the main actor and it will do automatically if you want to and it's it's more or less dispatch q.main.async right it's the same thing as well i can tell i see no difference there quite frankly at all um do this work on the main thread somehow just in a more convenient way okay let's think now so we've covered actors and they're not complicated but to see how they pan out in actual practice and use um there's a bunch of improvements for swift ui which is really really nice to see because it makes you while that much nicer um jack chavat asks is there any advantage to having a class in an actor while making an actor in the first place i don't think so i mean i'm still noodling around trying things out i think it'll take a little while for us to figure out uh you know what the uh costs of these things are but no i would make it directly um actors seem brilliant quite frankly seem very very nice as a way to share data safely which is cool anyway so if you want improvements um ah so do our example over here let's just clear this code a little bit yeah give it all this junk you can all go away here go away go away nice simple code again and then boom uh text hello world and which compiler will be in we're in the wrong one so switch down again okay so they've made some improvements 50y in sorry into swift in 5.5 that benefits swift ui and one of the most important one i think to cleaning up your code is a hash if for post fix member expressions eterna main actor is an actor not a class and actors do not support inheritance at this time and may never will we'll find out anyway what this means is you can now use hash if do a check and modify your code with postfix member expressions for example if i had text hello world in font large title that might look really good on mac os for example but look too big on ios i can instead say after text hash if os mac os do large title else let's use dot font dot headline end if like that and that's now perfectly legal that was not possible foreign 5.4 if you want to these can do wildly different things you could say i want a large title there but here i want you know foreground color uh red honestly it can do whatever you want to do it's all perfectly fine um and if you want you can even nest them you could say i want to have uh if it's a mac os use large title else uh if i am in debug mode then that uh else l something else let's do uh foreground color secondary from secondary there we go so you can nest them i wouldn't recommend it but you could do um that's cool if you really wanted to uh annoy your teammates slash have maximum job security um use whatever the heck you want honestly you can do whatever you want you could say um like in here steal this safe function here you could have said um uh let result equals an array of one two three uh if os oh hashif sorry hash if os is ios then i want to read dot count else i want to use reduce zero plus endif and they do completely things you know what what different things you whatever you get from printing results will either be three the number of items in the array in ios but on all of the platforms let's add them together to make six so don't do that you you can do it doesn't mean you should do it um so please don't do that unless you really really hate your teammates um you could even if you wanted to make them completely different types and actually that's what we're doing over here inside swift ui it's all some view ultimately i've got a font thing here or a foreground color here you might have had you know a background uh dot ultra thin material or something like that all sorts of customizations they all resolve into some view uh with some complex type behind it of course so you can do if you want to um please don't what can i say please don't do that bad idea but there are more improvements to ui because one of the things that has plagued my brain since day one has now kind of been retroactively being removed which is cool swifty y has all sorts of ways to manipulate your views if i look in here in my text for example i can say um my text has uh opacity of some number opacity of you know 1 or 0.9 whatever right and if i had a scale i could say i'm going to have a scale effect of something else and this will also be 0.9 for example so it's slightly transparent slightly scaled down right if i sit up here let my value be 0.9 and try to put that into here and here what i have silently done is actually mixed two different values if you look carefully scale effect expect to be given a cg float and opacity expects to be given now thank you very much for using completion opacity especially given a double double and cg float are completely different types in swift in order to see it it was a type def but in swiftly different types and so you had to have my value was explicitly a cg float here or you'd constantly do typecast to say okay this one is a double but this one here that's a cg float it was very very painful and i mean ideally they wouldn't have shipped cg float at all in 50 why it'd be just double everywhere that didn't happen presumably for performance reasons um and they've done away with it you can now mix and match the two now what is not happening here is they have not gone back and retroactively added double overloads to everything there's no scale effect it takes double it's still a cg float behind the scenes what's happened is swift recognizes these two things are basically the same right they are interchangeable with fractional differences but basically the same thing and it will silently add that for us cgfloat myvalue it'll create the initializer for us with our double enter cg float and also vice versa so we'll go double ct floats usually double happily it'll prefer double at every possible cost it can but it can go either way which is really really nice doing all that work for us and this means you can actually just treat the two as being interchangeable you could now say something like let first is a cg float equal to 42 let second be a double equal to 19 let result equals first plus second and then print result and that's absolutely fine because it will automatically bridge the two by having an implicit initializer um to make this cg float here into a double i'm just doing behind the scenes basically doing that which is cool that'll really help with swift ui particularly there's more there's still more honestly it's a packed packed packed release they've added support at last for codables uh to our enums to be codable if they have associated values which is really really cool because before they had to be raw representable handle it that way it wasn't very pleasant and now they've made much much more flexibility and power enables us basically free we could say there's an enum called weather which is codable it might be sunny it might be windy with a speed of int it might be rainy with a mountain and a chance int and we've now got a simple case uh a more complex case with one value attached and even more complex case with two values attached it handles them all it'll handle any kind of you want to you now say you know i want to have like a forecast be an array of weather and i'll just pass in all of let's do it'll be sunny then windy with speed 10 then sunny again then it's gonna rain for a while uh so amount five chance 50 like that a whole array of weather here i can then put that straight into jason and bring it back from jason into enum values i could say do uh let result equals try json encoder dot encode that forecast that's now as data i can then get up into a string to prove it all works we'll do let json string equal string decoding that result as utf 8 dot self and then print json string if it goes wrong we'll just do print encoding error and do error dot localized description boom and that'll do the whole work for us let's find out if i press build and run i can get rid of most of this junk in fact not using anything work anymore are we nope let's write it back see how it looks it's planning how to build my 34 lines of swift code come on you can run it i've got faith in you wilfred looks forward to apple open sourcing swifty why at some point i wouldn't get your hopes up i wouldn't do it if i were them uh i still have the concurrency noodling enabled i'd like to take that out again let's just delete all these values here maybe so i can get my thing being happy again come on have another go build in my code please be nice play nicely run again ah there we go so that's the string it outputs as json so you can see uh that sun has no values wind has to be 10 sun has our values rain amount it's all there we can read it back in and make enough stuff for us here uh and it's actually behind the scenes doing all sorts of work for us making multiple coding key enums to handle nesting structure for us it's doing a lot of work uh in hardly any code it's really really nice and and honestly folks there's still more there's still more you can now use uh lazy in local contexts you could say you know i want to have uh lazy var greeting equals you know i know print greeting to paul and it'll call a function print greeting to uh string come on string print in print greeting and then return hello to i've made it lazy so it won't actually call the print greeting until it's required you can go ahead and do you know uh print i'm before lazy print i'm after lazy and then print greeting at that point and i'll only call the lazy function at that point so it should print before lazy after lazy and then in print greeting in theory and then uh our hello message let's find out i'll press command r to build and run exciting there we go so it it pushes the work back until it's needed and you might think well why is that needed it's one of those things that you can basically just set up the work here make this thing at the beginning but don't do the actual work go ahead and do some complex logic oh it's really needed now print the greeting out at which point it'll call print greeting and do the work behind the scenes but maybe you never have to do that work and save it entirely which is really really nice and there's more it's even more it's just packed with information here we can now use um property wrappers inside function closure parameters you can now say uh this parameter function has a property wrapper attached to automatically do some extra work uh which is really cool for example i could say i want to have a function called set score one two score int i'll do print uh setting score two score and we can now go ahead and call that however we want to let's do set score one two fifty let's get score one two minus 50. let's go one two five hundred whatever you want to now we said actually our score needs to be in the range of zero through 100 nothing else makes sense these two values here are bad we don't want those to be used anymore we want to clamp them in the range 0 to 100 and that's where property wrappers come in we can make a really simple property wrapper let's say uh actually here's fine at property rapper here oops like that one struck here i call it clamped to some kind of comparable data our wrapped value is that comparable data that t t even there's initializer with the wrapped value of type t and a range to work with so the range 0 to 100 for example uh close range sorry closed there you go inside here i'll say our wrapped value is and we want to make sure we clamp it between inside that range don't go below the minimum don't go above the maximum that's done by saying min and max the wrap value so range dot lower bound comma range dot upper bound so clamp it in that range correctly and that is now a fully working property wrapper we can have a new function down here called setscore2 again using twoscoreint again doing print settings score to that score but now we want to apply our clamped property wrapper to that particular value coming in so we can say set score 2 at clamped range zero to a hundred to score like that do not let our value go outside that range and now we call sketch score one we'll call two two and two and press command r it should make sure our values stay fifty zero a hundred boom exactly right so we're forcing our values into the right format here without having to write any extra code inside our function it's really really nice way of thinking and reusing functionality write it once and i forget about it now this wrapper clamp is obviously simple because it's immutable we don't want to handle updates and so forth it's being used only for uh parameters coming in but you can make your wrappers as complex as you want to and it'll carry on working it's really really good uh paul any change on decoding unknown future types uh kelvin not i know of sorry okay there's still more changes folks but they get increasingly obscure that is the main set and that's been two and a half hours two and a half hours of me talking to myself with my dogs eating treats i knew very kindly sitting through it we've covered stacks and stacks of new swift 5.5 features i hope you're keen to start using them i know it's a lot i said at the beginning it is a lot there's lots and lots to get into your head concurrency task groups tasks priorities actors and more it is hard so if you're sitting here thinking wow my brain hurts okay it's okay it takes time to squeeze these things into your brain and maybe just practice try them out yourself see what you think see how person do your code i think tomorrow i sort of talk about from ben cohen saying he's going to be upgrading an existing app to use these concurrency features you'll see it in practice there old and new for a whole wdc talk there um so there's it is hard don't be too you know hard on yourself if you find it hard because it is difficult to understand so give it time anyway if you enjoyed the video i make lots more videos like this one teaching folks swift swift ui and more completely free so please subscribe to the channel leave a like leave a nice comment below and share the video with your friends it means a lot to me it really encourages me it makes me want to make more videos like this one first you can do is hit like and subscribe right that's not too hard to do it's free do that if you have any questions you can grab me on twitter i'm there as two straws two straws and the bottom left corner of your screen you should see hacking with swift.com slash offers that's there for a reason because right now i've got a half price sale on all my books and bundles so you want to go and learn swift efficiently and now for less go ahead check out that url and you'll save big money anyway there's still three more days of dub dub dc21 to go i hope you enjoy it make the most of it go to the labs go to the lounges ask questions get involved check out wwc.comunity there's lots of great things happening i hope you enjoy the rest of the event take care folks
Info
Channel: Paul Hudson
Views: 24,851
Rating: 4.9580555 out of 5
Keywords:
Id: 6C0SFPEy_0Y
Channel Id: undefined
Length: 146min 47sec (8807 seconds)
Published: Tue Jun 08 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.