1 00:00:00,540 --> 00:00:02,450 Students are always trying to modify the blog 2 00:00:02,450 --> 00:00:05,520 reader app, to repurpose it, which is great. 3 00:00:05,520 --> 00:00:09,860 But working with real world data, you either have too much data or you're trying 4 00:00:09,860 --> 00:00:11,550 to download images while on the same 5 00:00:11,550 --> 00:00:14,370 time you're like scrolling the table view controller. 6 00:00:14,370 --> 00:00:17,820 So that, you know, gives you a very choppy experience. 7 00:00:17,820 --> 00:00:22,120 The code that we wrote in the blog reader project is synchronous code. 8 00:00:22,120 --> 00:00:26,250 So let's try to understand what it's asynchronous versus synchronous. 9 00:00:26,250 --> 00:00:28,470 And how we can write asynchronous code, 10 00:00:28,470 --> 00:00:31,609 which is real world code, using NSURLSession. 11 00:00:32,880 --> 00:00:36,180 So I've the Blog Reader course in front of me. 12 00:00:36,180 --> 00:00:41,748 I'm going to scroll right down to the last stage which is Viewing a Web 13 00:00:41,748 --> 00:00:47,412 Page and click on the last video which is Implementing a UIWebView'. 14 00:00:49,880 --> 00:00:54,822 And let's go ahead and download these project files if you want to follow along. 15 00:00:54,822 --> 00:00:58,870 All right so I've opened up the Blog Reader project and if you followed 16 00:00:58,870 --> 00:01:03,960 along with the course, then you understand what's going on with the code over here. 17 00:01:03,960 --> 00:01:07,491 Let me set a break point on line 45. 18 00:01:09,230 --> 00:01:14,850 And let's run the application. So of course, 19 00:01:14,850 --> 00:01:19,780 it halts at that line where the break point was placed and if 20 00:01:19,780 --> 00:01:24,900 I, go back to the simulator as you can see the simulator is black. 21 00:01:24,900 --> 00:01:29,215 That's because it's waiting for the information to be processed. 22 00:01:29,215 --> 00:01:33,030 It's waiting for you to build that dictionary from the data 23 00:01:33,030 --> 00:01:37,250 that has been downloaded so that it can finish drawing the view. 24 00:01:37,250 --> 00:01:40,020 You can see the TableView, you can't 25 00:01:40,020 --> 00:01:44,800 see the TableView. And over here you can see that it says 26 00:01:44,800 --> 00:01:50,840 Thread 1, which is the main thread. It says apple, com.apple.main_thread. 27 00:01:50,840 --> 00:01:55,090 So that's the main thread where all the UI Drawing happens. 28 00:01:55,090 --> 00:01:59,990 You know, your, your UI views are loaded, you know, the sub-views are loaded. 29 00:01:59,990 --> 00:02:03,020 All the drawing is happening on the main thread. 30 00:02:04,040 --> 00:02:05,060 Which is a 31 00:02:05,060 --> 00:02:08,000 simplest, I mean if you want to understand threading, it's 32 00:02:08,000 --> 00:02:11,790 kind of like documenting multi-processes running at the same time. 33 00:02:11,790 --> 00:02:16,270 It's a bit more complicated than that but think of it as a 34 00:02:16,270 --> 00:02:21,270 cue, you know, you're cuing up tasks to happen and you have multiple threads. 35 00:02:21,270 --> 00:02:24,860 And the main thread, most of the cuing happens when you're 36 00:02:24,860 --> 00:02:30,140 like creating the window, you're creating the views, you're loading the views, 37 00:02:30,140 --> 00:02:32,030 all of that is happening there. 38 00:02:32,030 --> 00:02:36,060 So, when you're downloading data, you primarily don't want to 39 00:02:36,060 --> 00:02:39,120 do it on the main thread or the main queue. 40 00:02:39,120 --> 00:02:44,430 You want to do it on a separate thread, so that your view can still load and 41 00:02:44,430 --> 00:02:48,080 the user can still interact with your application, while 42 00:02:48,080 --> 00:02:51,450 the data is being downloaded on a separate queue. 43 00:02:51,450 --> 00:02:55,812 So, lets, lets go, I'll go ahead and stop this. 44 00:02:55,812 --> 00:03:02,439 Let me remove this breakpoint and I'll put a breakpoint 45 00:03:02,439 --> 00:03:09,351 right here in the cellForRowAtIndexAtPath on line 83. 46 00:03:09,351 --> 00:03:14,060 Right now, lets run this task or let's run this application. 47 00:03:14,060 --> 00:03:17,780 So now, as you can see, once again, our our 48 00:03:17,780 --> 00:03:21,020 app has halted on the main queue, you know, and there's 49 00:03:21,020 --> 00:03:22,330 the main queue. 50 00:03:22,330 --> 00:03:27,190 And the task is, or the method is self erode index path. 51 00:03:27,190 --> 00:03:29,370 So if I go back to the simulator. 52 00:03:29,370 --> 00:03:33,530 You can see that our simulator is black, you know, it hasn't drawn 53 00:03:33,530 --> 00:03:39,210 the view completely because we you know, we don't have anything to show yet. 54 00:03:39,210 --> 00:03:42,980 So, cuz we're waiting for us to download that image, so that 55 00:03:42,980 --> 00:03:46,100 we can add that image to the cell, which can then be 56 00:03:46,100 --> 00:03:49,520 drawn on the main screen. 57 00:03:49,520 --> 00:03:52,340 So there's a lot of overhead going on over here. 58 00:03:52,340 --> 00:03:57,470 You are simultaneously downloading data and trying to display that on the screen. 59 00:03:59,190 --> 00:04:03,640 So, let's figure out how we can refactor this code. 60 00:04:03,640 --> 00:04:06,910 So we can have a lot of asynchronous 61 00:04:06,910 --> 00:04:11,670 data downloading happening while the view is being drawn 62 00:04:11,670 --> 00:04:12,940 on the main thread. 63 00:04:14,190 --> 00:04:17,180 So right now the, the code that we have is synchronous. 64 00:04:17,180 --> 00:04:23,765 It happens synchronously where one task is being queued be behind the other task. 65 00:04:23,765 --> 00:04:29,380 Asynchronous is when one tasks happens, while there is another task happening 66 00:04:29,380 --> 00:04:32,960 in the background and then it comes back and joins the main queue. 67 00:04:32,960 --> 00:04:37,130 Think of this as you know, lanes on 68 00:04:37,130 --> 00:04:38,200 a highway. 69 00:04:38,200 --> 00:04:42,080 If you had only one lane, then the traffic would go really slow. 70 00:04:42,080 --> 00:04:44,880 But if you want the traffic to move faster, then you 71 00:04:44,880 --> 00:04:48,470 can open up multiple lane son the highway, and that way 72 00:04:48,470 --> 00:04:51,610 you can, you know, have more, you know, several cars driving 73 00:04:51,610 --> 00:04:56,040 on the same side or, you know, in the same direction. 74 00:04:56,040 --> 00:04:59,310 And you can have the traffic moving faster and faster. 75 00:05:01,310 --> 00:05:02,160 Let's go back to our 76 00:05:02,160 --> 00:05:07,100 viewDidLoad method. And let's, let's keep some of 77 00:05:07,100 --> 00:05:12,220 this code. So we'll keep the blogURL because we 78 00:05:12,220 --> 00:05:17,680 need that. We don't need this jsonData, we don't need 79 00:05:17,680 --> 00:05:22,360 this, actually, let's keep a lot of this code and 80 00:05:24,450 --> 00:05:25,830 I'm going to go down here. 81 00:05:26,860 --> 00:05:31,080 And the class that we're going to use is NSURLSession. 82 00:05:31,080 --> 00:05:34,214 Now this is a new class that came about in iOS 7. 83 00:05:35,410 --> 00:05:39,440 This is called NSURLSession. So, 84 00:05:39,440 --> 00:05:42,970 let's look at the documentation for NSURLSession. 85 00:05:42,970 --> 00:05:50,980 I'll option click and look at the class reference and there's our NSURLSession. 86 00:05:50,980 --> 00:05:55,500 As you can see it says, the class and related classes provide an API for 87 00:05:55,500 --> 00:06:04,030 downloading content via HTTP. And it's a very rich API, it can do a lot. 88 00:06:04,030 --> 00:06:09,342 And here, if I scroll down you'll see that the URL Session Class Hierarchy. 89 00:06:09,342 --> 00:06:13,800 So NSURLSession is made up of several different classes. 90 00:06:13,800 --> 00:06:15,990 It's not just one class. 91 00:06:15,990 --> 00:06:21,910 So you have a URL Session. You have URL session configuration. 92 00:06:21,910 --> 00:06:23,130 You have the task. 93 00:06:23,130 --> 00:06:25,020 So there are several different types of task. 94 00:06:25,020 --> 00:06:27,700 You have a data task. You have an upload task. 95 00:06:27,700 --> 00:06:29,320 You have a download task. 96 00:06:29,320 --> 00:06:32,220 The one we're gonna use is the, the 97 00:06:32,220 --> 00:06:35,240 download task, cuz we want to download data 98 00:06:37,340 --> 00:06:38,940 And then of course, it has delegate. 99 00:06:38,940 --> 00:06:40,750 So if you want to overwrite some of the 100 00:06:40,750 --> 00:06:44,650 methods, like while it's downloading or if it's redirecting. 101 00:06:44,650 --> 00:06:48,490 Or you know, while the process is happening and if you want to hook 102 00:06:48,490 --> 00:06:53,460 into any of those events, you can do that using some of the delegates. 103 00:06:53,460 --> 00:06:57,420 So in order for us to use NSURLSession, we need a 104 00:06:57,420 --> 00:07:02,271 URL object, which we have already, we have the blog URL, 105 00:07:02,271 --> 00:07:06,033 we need a NSURL request, which we don't have 106 00:07:06,033 --> 00:07:09,528 right now, but we'll see how to do that. 107 00:07:09,528 --> 00:07:11,868 And we don't need any of these, I mean 108 00:07:11,868 --> 00:07:14,468 we will get back a response cuz, we're going to 109 00:07:14,468 --> 00:07:16,678 make the request so we get back a response 110 00:07:16,678 --> 00:07:20,120 from the server so we'll See how that looks like. 111 00:07:20,120 --> 00:07:25,100 And then there's a cached url response, we're not gonna look at that right now. 112 00:07:25,100 --> 00:07:27,510 So let's go back here and 113 00:07:27,510 --> 00:07:29,040 create a session first. 114 00:07:29,040 --> 00:07:36,420 So we'll say session and in this URL session you can do shared session. 115 00:07:36,420 --> 00:07:41,090 Which is a shared singleton object for the, for your app. 116 00:07:41,090 --> 00:07:47,340 So you can create custom configuration sessions if you look at the documentation 117 00:07:47,340 --> 00:07:52,920 for NSURLSession. Let me go back here, going back to 118 00:07:52,920 --> 00:07:57,970 our documentation. So, Creating a Session. 119 00:07:57,970 --> 00:08:02,010 So if I click on the left under Tasks here 120 00:08:02,010 --> 00:08:05,360 and say Creating a Session, you have several different options. 121 00:08:05,360 --> 00:08:09,220 You have sessionWithConfiguration, sessionWithConfiguration and 122 00:08:09,220 --> 00:08:10,150 then, you know, you can 123 00:08:10,150 --> 00:08:14,670 implement delegates or simply you can use a shared session. 124 00:08:14,670 --> 00:08:19,530 And, and you can see here it says shared singleton session object. 125 00:08:19,530 --> 00:08:24,390 So this gives you back some boilerplate session code 126 00:08:24,390 --> 00:08:29,480 and you know, and that's usually good enough for you to use in most instances. 127 00:08:30,740 --> 00:08:35,830 So, now that we have our session, we're going to 128 00:08:35,830 --> 00:08:40,940 create our NSURLRequest, 129 00:08:40,940 --> 00:08:45,240 okay? And the request basically 130 00:08:45,240 --> 00:08:50,929 is NSURLRequest alloc init 131 00:08:50,929 --> 00:08:56,180 and we'll say, initWithURL. Now, we already have a URL so, I am gonna 132 00:08:56,180 --> 00:09:03,920 use that which is blogURL. Next I am going to create 133 00:09:03,920 --> 00:09:09,877 an NSURLSessionDownloadTask. 134 00:09:09,877 --> 00:09:16,290 [NOISE] So we create a task using the session 135 00:09:16,290 --> 00:09:23,590 and we will use one of these methods here, so we use DownloadtaskwithURL. 136 00:09:23,590 --> 00:09:26,690 Actually we don't even need to create the, the request. 137 00:09:26,690 --> 00:09:29,180 The request can be automatically created for us, 138 00:09:29,180 --> 00:09:31,090 all we need to do is provide a URL. 139 00:09:31,090 --> 00:09:34,475 So let's use this one, this method here that says, 140 00:09:34,475 --> 00:09:36,800 downloadTaskWithURL. 141 00:09:36,800 --> 00:09:42,380 All right, so we'll provide this with the blogURL, now delete this NSURLRequest. 142 00:09:44,890 --> 00:09:49,290 And then coming to the completion handler, all you have to do 143 00:09:49,290 --> 00:09:53,880 is press Enter and then it'll fill the block out for you. 144 00:09:53,880 --> 00:10:01,082 Now, before I go ahead and do anything with this block, let's put a semicolon 145 00:10:01,082 --> 00:10:07,810 here and let's do NSLog and we will print out the, the response. 146 00:10:10,620 --> 00:10:15,030 So as you can see we get three parameters to our block. 147 00:10:15,030 --> 00:10:16,830 The first one is the location. 148 00:10:16,830 --> 00:10:21,800 So this is the location of the data that has been downloaded for us. 149 00:10:21,800 --> 00:10:27,500 And this is an NSURL so the data has been downloaded on the disk of 150 00:10:27,500 --> 00:10:32,960 the device and it's giving the location, so this is not just like a web URL. 151 00:10:32,960 --> 00:10:36,110 NSURL can also be a location 152 00:10:36,110 --> 00:10:41,320 that's local on the file system. And then you have the response 153 00:10:41,320 --> 00:10:46,290 and finally you have the error. So there's our response. 154 00:10:48,460 --> 00:10:53,220 I'm gonna put a breakpoint here so you can see what, what happens. 155 00:10:53,220 --> 00:10:55,130 We're still not deleting any of this code up 156 00:10:55,130 --> 00:10:58,980 here so our, our app should work as normal. 157 00:10:58,980 --> 00:11:04,580 And, as you can see, we get a warning and the warning says unused task variable. 158 00:11:04,580 --> 00:11:08,750 That's because we have to do task resume. Whoops. 159 00:11:11,330 --> 00:11:15,230 And what task resume is basically doing is it's just starting the task. 160 00:11:16,330 --> 00:11:18,950 I know, it's called resume and not start, for some reason. 161 00:11:18,950 --> 00:11:19,920 Who knows? 162 00:11:19,920 --> 00:11:23,230 So, let's do command R to run our application. 163 00:11:24,690 --> 00:11:34,120 And if I go back here, it, it halts the completion of our tasks but as you can see 164 00:11:36,580 --> 00:11:39,610 here, it's, it's on a separate thread. 165 00:11:39,610 --> 00:11:42,620 It's not holding up the main thread anymore. 166 00:11:42,620 --> 00:11:47,600 So, it can draw whatever it needs to draw in the UI. 167 00:11:47,600 --> 00:11:48,960 And there is our UI. 168 00:11:48,960 --> 00:11:55,460 So that, that's what happens here, it's that the task is being 169 00:11:55,460 --> 00:12:01,670 executed and the completion handler is being called later on, so that 170 00:12:01,670 --> 00:12:04,680 it does not hold up the drawing of our UI. 171 00:12:08,120 --> 00:12:08,850 Okay. 172 00:12:08,850 --> 00:12:12,150 So, oh, by the way, I, I didn't show you the, the response. 173 00:12:12,150 --> 00:12:18,510 So let's run this app again and here you have the, the response. 174 00:12:18,510 --> 00:12:23,400 So basically it's just showing you you know, general information 175 00:12:23,400 --> 00:12:27,370 of what the response was and how it was processed. 176 00:12:27,370 --> 00:12:31,250 And HTTP status code 200 means that the response was successful. 177 00:12:33,960 --> 00:12:37,630 Okay, so, what do we want here? Well, we can basically 178 00:12:37,630 --> 00:12:41,280 take most of this code that we have 179 00:12:41,280 --> 00:12:46,000 here and we can put it in our completion handler. 180 00:12:46,000 --> 00:12:55,050 So let's copy all these code from line 38, where were parsing 181 00:12:55,050 --> 00:12:59,605 the JSON and we will paste it here. So the 182 00:12:59,605 --> 00:13:06,760 JSON basically needs, as you can see, it needs JSON data. 183 00:13:06,760 --> 00:13:11,793 Now, previously, we were getting the JSON data just by calling NSData and 184 00:13:11,793 --> 00:13:16,940 dataWithContentsOfURL, which is a synchronous way of getting the data. 185 00:13:16,940 --> 00:13:18,620 It's not asynchronous. 186 00:13:18,620 --> 00:13:22,450 So we'll, we'll delete all, these two lines because we don't need it. 187 00:13:22,450 --> 00:13:24,860 So what, how do we get the JSON data? 188 00:13:24,860 --> 00:13:31,200 Well, we need NSData, json data. So remember 189 00:13:31,200 --> 00:13:37,090 I said we have our location, which is the location of where their data is stored. 190 00:13:37,090 --> 00:13:40,630 Well, now instead of downloading it from the web, 191 00:13:40,630 --> 00:13:42,970 we can just pick up the data from the disk. 192 00:13:42,970 --> 00:13:44,600 You know, which, which does not take a 193 00:13:44,600 --> 00:13:47,470 lot of time, It's, it's right there, it's local. 194 00:13:47,470 --> 00:13:57,470 So we can say NSData alloc initWithContentsOfURL and 195 00:13:58,830 --> 00:14:02,590 we can give it a location. And that's it. 196 00:14:02,590 --> 00:14:08,450 Basically there's our there's our you know, there, there's our data. 197 00:14:08,450 --> 00:14:11,370 And then the rest of the code remains exactly the 198 00:14:11,370 --> 00:14:14,290 same, you know that, that part doesn't change at all. 199 00:14:15,600 --> 00:14:18,460 So now if I run our app, you will 200 00:14:18,460 --> 00:14:22,700 notice that the table view is blank, nothing is happening. 201 00:14:24,070 --> 00:14:29,850 So let me, let me put a breakpoint here on line 51 and run the app. 202 00:14:29,850 --> 00:14:37,590 So, as you can see, our UI has been drawn and we earn a separate thread. 203 00:14:37,590 --> 00:14:41,310 So this operation is happening on a separate thread. 204 00:14:41,310 --> 00:14:44,710 Our main thread is not being held up and then we 205 00:14:44,710 --> 00:14:49,950 are like, parsing the data and massaging it and putting it in 206 00:14:49,950 --> 00:14:54,975 whatever format we need to put it. Now why is our view not being drawn? 207 00:14:54,975 --> 00:14:59,100 So, remember I said this is a separate queue and 208 00:14:59,100 --> 00:15:03,520 the, all, all the UI drawing happens on the main queue. 209 00:15:03,520 --> 00:15:06,290 So this is the only part that's a bit tricky, 210 00:15:06,290 --> 00:15:10,120 we need to send a request to reload the TableView. 211 00:15:10,120 --> 00:15:14,360 So, I could just do this here, let me scroll this up. 212 00:15:14,360 --> 00:15:14,980 If I 213 00:15:14,980 --> 00:15:19,932 could say, oops, self.tableView 214 00:15:19,932 --> 00:15:25,050 reloadData. I could do that but 215 00:15:25,050 --> 00:15:30,415 nothing will happen. Our table views will still be blank, so, 216 00:15:30,415 --> 00:15:35,612 instead what we have to do is call dispatch async. 217 00:15:35,612 --> 00:15:37,499 [BLANK_AUDIO] 218 00:15:37,499 --> 00:15:39,982 And what is that? Well let me. 219 00:15:39,982 --> 00:15:43,215 [BLANK_AUDIO] 220 00:15:43,215 --> 00:15:47,889 dispatch_async, and [NOISE] basically 221 00:15:47,889 --> 00:15:52,563 this is a way to send a request to the main queue 222 00:15:52,563 --> 00:15:58,480 that you want to do something on the main queue. 223 00:15:58,480 --> 00:16:02,775 So how do you access the main queue? Well, you have to call 224 00:16:02,775 --> 00:16:08,420 dispatch_get_main_queue. 225 00:16:08,420 --> 00:16:12,970 As you can see, these are C functions and you get back a block. 226 00:16:12,970 --> 00:16:19,280 And so, basically, you're saying, make a call dispatch a 227 00:16:19,280 --> 00:16:25,240 request to the main queue and execute this piece of code, whatever that code may be. 228 00:16:25,240 --> 00:16:31,080 So, in our case, that code is basically reload data. 229 00:16:33,830 --> 00:16:37,480 So, any of view drawing or updating that you need to do. 230 00:16:37,480 --> 00:16:39,710 You need to do it on the main queue and then 231 00:16:39,710 --> 00:16:44,500 you call table view reload data and there is our data. 232 00:16:45,790 --> 00:16:47,010 So there you have it, we just 233 00:16:47,010 --> 00:16:50,810 converted our Blog Reader project to be asynchronous. 234 00:16:50,810 --> 00:16:54,980 And this is of immense value and you should probably do this going forward 235 00:16:54,980 --> 00:16:59,790 for most of your projects, where you want to download data and process it. 236 00:16:59,790 --> 00:17:05,140 Very seldom that you should use synchronous way of downloading data. 237 00:17:05,140 --> 00:17:10,080 So the next thing we wanna do is improve our image downloading. 238 00:17:10,080 --> 00:17:15,910 So in our cellForRowAtIndexPath, where we download the image and display it. 239 00:17:15,910 --> 00:17:19,890 Here once again, this is a synchronous way of downloading data. 240 00:17:19,890 --> 00:17:24,310 We should change that to an asynchronous way of downloading data. 241 00:17:24,310 --> 00:17:24,860 So let's see how we 242 00:17:24,860 --> 00:17:29,010 can facilitate that. All right, so, let's go ahead and remove 243 00:17:29,010 --> 00:17:36,348 these two lines of code. Actually, we just need to remove 244 00:17:36,348 --> 00:17:42,672 this one line of code and, we'll go 245 00:17:42,672 --> 00:17:49,713 ahead and do a NSURLSession. And then NSURL, 246 00:17:49,713 --> 00:17:55,290 NSURLSession sharedSessio, and then 247 00:17:55,290 --> 00:18:00,698 we need to NSURLSessionDownloadTask 248 00:18:00,698 --> 00:18:05,599 and once again, we use our session 249 00:18:05,599 --> 00:18:09,576 object. And we'll say 250 00:18:09,576 --> 00:18:14,905 downloadTaskWithURL, and where do we get the URL? 251 00:18:14,905 --> 00:18:21,975 Well, remember in our blog post model, we created a method called thumbnailURL, 252 00:18:21,975 --> 00:18:27,089 so that's where we get our URL. And once again press Tab and 253 00:18:27,089 --> 00:18:32,790 Enter, so you can have your completion handler block. 254 00:18:32,790 --> 00:18:36,230 So for our code, once again, we'll get our data. 255 00:18:36,230 --> 00:18:39,970 We'll say data equals and 256 00:18:39,970 --> 00:18:46,600 NSData alloc initWithContentsOfURL which is 257 00:18:46,600 --> 00:18:53,710 location. And now, we can take this line 258 00:18:53,710 --> 00:18:58,850 of code, actually both these lines of code and copy them in our completion handler. 259 00:19:00,150 --> 00:19:02,725 So, we can change this basically instead of 260 00:19:02,725 --> 00:19:05,070 imageData or we can change the name of our 261 00:19:05,070 --> 00:19:05,740 variable here. 262 00:19:05,740 --> 00:19:10,490 We can call it imageData so its kind of clear what data is coming to us. 263 00:19:11,600 --> 00:19:17,320 And then, for us to store the imageView 264 00:19:17,320 --> 00:19:19,860 or store the image in the imageView, once again, 265 00:19:19,860 --> 00:19:23,040 we'll have to call dispatch_async, because that's view 266 00:19:23,040 --> 00:19:26,280 operation that should be occurring on the main block. 267 00:19:26,280 --> 00:19:30,270 So let's go up here and copy this line where 268 00:19:30,270 --> 00:19:35,200 we do the dispatch_async. 269 00:19:35,200 --> 00:19:40,670 We'll copy that and instead of calling tableView reload we'll simply 270 00:19:40,670 --> 00:19:45,890 copy our cell.imageView.image. 271 00:19:45,890 --> 00:19:50,858 Now, do not forget to you know, call task resume, so we're gonna do 272 00:19:50,858 --> 00:19:56,950 task, resume here. 273 00:19:56,950 --> 00:19:59,920 All right, and let's run our app. 274 00:20:01,990 --> 00:20:06,780 And our thumbnails don't show up. So there, there is one thing to 275 00:20:06,780 --> 00:20:12,130 consider here, the property imageView is, as 276 00:20:12,130 --> 00:20:17,530 you can see it says, read only. This is a lazy loading way 277 00:20:17,530 --> 00:20:22,230 of defining your views. And what do we mean by lazy 278 00:20:22,230 --> 00:20:27,270 loading? Well, it's not created until it's needed. 279 00:20:29,020 --> 00:20:35,230 So, it's created over here because you're setting an image. 280 00:20:35,230 --> 00:20:39,830 But in our case we are not, when we're returning this 281 00:20:39,830 --> 00:20:41,750 cell, so when you're creating 282 00:20:41,750 --> 00:20:45,620 this cellForRowAtIndexPath you're returning your cell. 283 00:20:45,620 --> 00:20:49,360 So, when you're creating and returning the cell, you're saying 284 00:20:49,360 --> 00:20:52,240 like well, I need an imagery and I'm setting it here. 285 00:20:52,240 --> 00:20:54,220 But in our case, the imagery 286 00:20:54,220 --> 00:21:00,630 is not being created until the completion handler block is called, until much later. 287 00:21:00,630 --> 00:21:05,870 So, we are returning the cell, but we are not setting an imagery whatsoever. 288 00:21:05,870 --> 00:21:09,610 So instead of setting an L statement, we're going 289 00:21:09,610 --> 00:21:14,040 to delete or we're going to cut this cell.imageView. 290 00:21:14,040 --> 00:21:18,760 We're not going to have an L statement. And right here, 291 00:21:18,760 --> 00:21:25,180 before our if statement, we'll always set the treehouse.png as a default image. 292 00:21:25,180 --> 00:21:29,890 So we'll create an imageView and return to cell and then we 293 00:21:29,890 --> 00:21:34,720 can override the, the image property of our imageView. 294 00:21:34,720 --> 00:21:37,640 So let me run the application so you can see. 295 00:21:37,640 --> 00:21:38,790 So now it all works. 296 00:21:38,790 --> 00:21:44,030 You know, now you can see images in all of the rows. 297 00:21:44,030 --> 00:21:47,760 So, basically we're instructing that, hey, we 298 00:21:47,760 --> 00:21:50,100 need an imageView when we're building this 299 00:21:50,100 --> 00:21:54,920 cell and then we'll tail, change the image out latter when we download the image. 300 00:21:54,920 --> 00:21:58,020 And if doesn't download a new image, then, by default, it 301 00:21:58,020 --> 00:22:02,190 will always show the, the Treehouse logo which is what we want. 302 00:22:03,490 --> 00:22:06,080 So, it works, it works out perfectly for us. 303 00:22:06,080 --> 00:22:09,170 So there you have it. We've changed our, 304 00:22:09,170 --> 00:22:14,750 blog reader, project to download data in asynchronously. 305 00:22:14,750 --> 00:22:19,030 We've changed our cells to download images asynchronously. 306 00:22:19,030 --> 00:22:22,290 And the benefit of doing this is two fold. 307 00:22:22,290 --> 00:22:27,440 One is you don't block the UI, so that the user can still interact with the UI. 308 00:22:27,440 --> 00:22:29,920 And secondly by downloading your images 309 00:22:29,920 --> 00:22:34,140 asynchronously, you don't get choppy scrolling. 310 00:22:34,140 --> 00:22:38,790 You know, so you're not downloading images while the user is scrolling. 311 00:22:38,790 --> 00:22:42,970 The downloading of the images happens in the background so the user 312 00:22:42,970 --> 00:22:47,780 has full access and can interact with the UI, as they normally would. 313 00:22:49,090 --> 00:22:50,960 >> Hope you now have a better understanding 314 00:22:50,960 --> 00:22:55,560 of how to download data asynchronously using NSURLSession. 315 00:22:55,560 --> 00:22:57,100 I would definitely make this the default 316 00:22:57,100 --> 00:22:59,450 way of downloading data in future projects.