"We all love Paul Hegarty." Stanford IOS8 public class personal note multithreading multithreading

Source: Internet
Author: User


There are many queues in iOS, just like the queues in our data structures, where the queue concept is first-in-one. Each method (including closures) is organized in these different queues, and each queue has its own thread to run these queues, which creates a multithreaded environment.

One of the most important queues is called the Home column, which is a serial queue, so the host column executes only one function in the main queue. All of the UI activity has to happen in the main queue, so when you want a function or a closure, you execute some code, it does anything about the UI, you have to put it in the main queue, it's a good way to protect the UI, and the home row doesn't want to do anything that might be blocked. For example, to read a nsdata that contains a URL, the demo in the previous session will be stuck when we click the button to get a larger image, so we'll take it out of the main queue.

Usually you use the things in MVC in the main queue, such as Viewdidload, viewwillappear in the page life cycle, and we don't need to be careful.

iOS will create additional queues for you when you need them.

So how do you execute functions or closures in other queues?


First initialize a queue, then call the function Dispatch_async, there are two parameters, the first is the queue, the second is a closure, which is written in the form of a trailing closure. So how do you get the home row in the first sentence? Using the function Dispatch_get_main_queue (), you can return to the home row. There is also an object-oriented approach that can be done: Nsoperationqueue.mainqueue (). Here's an example of doing something in another queue that might block the UI, and then opening the home column to do what needs to be presented to the UI.

Here are some other queues outside the home column that are typically represented by different processing levels, which also represent different processing speeds for the queue.


To create a non-home column, first to create a service level, the method of creating the level is a little strange, using an int constructor, which constructs the Value property of the selection level, is caused by historical reasons. After creating a good level, use the Dispatch_get_global_queue function, pass in the level and a 0, and this 0 will be used later. With the new queue, you can use the DISPATCH_ASNYC function and execute the code in the non-primary queue.

If there are multicore processors, the queues can actually run in parallel, but in most cases they are ticks. You can create your own serial queue and use Dispatch_queue_create to build a serial queue.

Some APIs are multithreaded in iOS, such as the following example:


For example, the nsurlsession in the example above, note the yellow font part, it lets you download a file from a URL, and is asynchronous to do. Add a closure after the method, the function of this closure is when you download the file you need to open in the UI, the closure for you to specify a local URL, an HTTP response to an error message, using this information you will do some update the UI things. So does that make sense? The answer is "NO".

Because the downloaded file is not in the main queue, the workaround is to open the home column in the closure:


Now to do the actual combat session, back to our previous demo, open the picture will always cause blocking, this is not good, try to use multi-threaded knowledge to solve the problem.

What we need to do is to put the link that gets the picture into other threads, the method Fetchimage is modified as follows:

Func fetchimage () {        if let url = imageURL {let        QoS = Int (qos_class_user_initiated.value)//Specify the service "may take time, but the user needs to get, Complete as soon as possible "        Dispatch_async (Dispatch_get_global_queue (QoS, 0)) {()->void in//put the code to be executed in the closure let        imageData = NSData (Contentsofurl:url)        If imageData! = nil{        self.image = UIImage (data:imagedata!)        } else {        self.image = nil        }            }        }
   }
Note that now is not enough, the action of setting image will modify the UI, so this action should be in the main queue, we put the action of setting image into the main queue:

Func fetchimage () {        if let url = imageURL {let        QoS = Int (qos_class_user_initiated.value)//Specify the service "may take time, but the user needs to get, Complete as soon as possible "        Dispatch_async (Dispatch_get_global_queue (QoS, 0)) {()->void in//put the code to be executed in the closure let        imageData = NSData (contentsofurl:url)//load the picture should be placed in other threads            Dispatch_async (Dispatch_get_main_queue ()) {///To use the main        thread when displaying the loaded picture in the page If imageData! = nil{        self.image = UIImage (data:imagedata!)        } else {        self.image = nil        }            }            }< c12/>}    }
Now the system does not stutter when loading the picture, you will jump to the next page and wait in the current page to see the loaded Picture:

Now the problem is that every click of a button will generate a new MVC, then how to avoid repeated loading, we need to determine the click button when the URL is the current page slice URL, the method is modified as follows:

  Func fetchimage () {        if let url = imageURL {let        QoS = Int (qos_class_user_initiated.value)//Specify the service "may take time, but the user needs to get, Complete as soon as possible "        Dispatch_async (Dispatch_get_global_queue (QoS, 0)) {()->void in//put the code to be executed in the closure let        imageData = NSData (contentsofurl:url)//load the picture should be placed in other threads            Dispatch_async (Dispatch_get_main_queue ()) {///To use the main                thread when displaying the loaded picture in the page If url = = self.imageurl{//new Judgment statement        if imageData! = nil{        self.image = UIImage (data:imagedata!)        } else {        SE Lf.image = Nil}}}}}    

The last thing to do is to run a cog on the main page to represent the loading process when the other queue loads the picture.

Now go to the object library and drag a gear control into the scene, open the document outline you will find that this new gear control has been added to the ScrollView because we used this scrollview to almost fill our view:

The advantages of the document outline here are that you can drag controls in the document outline to combine their order, and the following are the correct order:

In addition, you can add constraints in the document outline, as in IB, Control-drag, we have the gear control centered


Then set the properties of the gear control and tick the option to disappear when it stops:


To establish a connection with the controller:

@IBOutlet weak var spinner:uiactivityindicatorview!
When I set up an HTTP request to make the gear turn, when I end the request, let the gear stop turning.

So obviously we need to increase the rotation of the gears in the following position:

Func fetchimage () {        if let url = ImageURL {            spinner?. Startanimating ()//new Gear rotation let        QoS = Int (qos_class_user_initiated.value)//Specify the service "may take time, but users need to get it done as soon as possible"        Dispatch_async (Dispatch_get_global_queue (QoS, 0)) {()->void in//put the code to be executed in the closure let        imageData = NSData ( Contentsofurl:url)//load the picture should be placed in another thread            Dispatch_async (Dispatch_get_main_queue ()) {////To use the main thread if the loaded picture is displayed on the page                url = = self.imageurl{//new Judgment statement        if imageData! = nil{        self.image = UIImage (data:imagedata!)        } else {        self . Image = Nil}}}}}    

Note that when calling spinner it is optional, because the page may be generated before the spinner control, which is a common approach when invoking the control. However, this method is loaded with different processing situations, in common with the image, so we choose to stop the gears in the set method that calculates the attribute image:

Private var image:uiimage? {        get {return imageview.image}        set {        imageview.image = newvalue        imageview.sizetofit ()        ScrollView?. Contentsize = ImageView.frame.size        spinner?. Stopanimating ()//load completed stop gear        }    }

Now it's time to run, when the picture is not loaded, we see a white page, and now the gears in the middle of the page are turning:


Gear disappears after loading:



"We all love Paul Hegarty." Stanford IOS8 public class personal note multithreading multithreading

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.