简体   繁体   中英

How does threading (asynchronous queues) work in Swift?

ok I am updating this question but left the old one there. So I have an array that stores the data for different views in a uipageviewcontroller. I need to grab image data in the background. I don't understand how to code this though within an asynchronous task. Heres the code for the task:

let queue = NSOperationQueue()

                queue.addOperationWithBlock() {
                    // do something in the background
                    println("background")
                    self.cards[newIndex].loadImag()
                    var cardimages = self.cards[newIndex].images
                    NSOperationQueue.mainQueue().addOperationWithBlock() {
                        // when done, update your UI and/or model on the main queue
                        println("update ui")
                        self.cards[newIndex].images = cardimages
                    }
                }

this is what the .loadImag() function looks like:

    func loadImag(){
        println("images= \(self.images)")

        if self.

location_id != nil && (self.images == nil) {
        println("before api call loc_id= \(self.location_id)")
    ApiWrapper.getPictures(self.location_id!, completionHandler: self.imagesCallback)
    }
    }
}

and this is self.imagesCallback code:

private func imagesCallback(cardImagesArray: [CardImage]){
    println("images callback id= \(self.location_id)")
    self.images = cardImagesArray
}

problem is I am not sure how to put this code inside of the operation cue since the function must have a callback. How can I get the operation queue working so that it updates the self.card array in the uipageviewcontroller?

OLD QUESTION_________________: So I have this line of code I need to run concurrently in a different thread than the main thread. When I add it to the main queue like so:

var queue = dispatch_get_main_queue()
dispatch_async(queue, {
    self.cards[newIndex].loadImage()
})

doing this it works fine but doesn't seem to run concurrently. When I change the queue to concurrent like this:

dispatch_async(DISPATCH_QUEUE_CONCURRENT, {
    self.cards[newIndex].loadImage()
})

The app crashes saying "EXC_BAD_ACCESS". What am I doing wrong here? Also when I run the self.cards[newIndex].loadImage() function in a different concurrent thread will this update the values in the main thread?

you shouldn't use GCD unless you want to explicitly use functionality which is only available on GCD. For your case it is more beneficial (and cleaner in code) to use NSOperationQueue. NSOperationQueue uses GCD in the background and is more secure (less ways to mess up)

let queue = NSOperationQueue()

queue.addOperationWithBlock() {
    // do something in the background

    NSOperationQueue.mainQueue().addOperationWithBlock() {
        // when done, update your UI and/or model on the main queue
    }
}

You can also read through the Apple Concurrency Programming Guide The guide is using examples with Objective-C but API is basically the same for Swift.

It also might look strange but with the addOperationWithBlock() I used something called "trailing closure" you can read here about it

You need to use dispatch_get_global_queue . Try something like:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {self.cards[newIndex].loadImage()})

dispatch_get_main_queue() , as you were trying, runs on the UI/main thread, which is why you saw the behavior you did.

To answer the second part of your question, If loadImage() is modifying the UI, you don't want to do that from a background thread. It must be done from the main/UI thread. A typical idiom would be, from the main thread do:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {
    <code to load/prepare images>
    dispatch_async(dispatch_get_main_queue(), {
        <code to update UI elements>   
    })
})

Can you paste the whole code so we can see what are you doing? Below is very basic code snippet. This is basically how concurrency works in Swift.

let qos = Int(QOS_CLASS_USER_INITIATED.value)
 dispatch_async(dispatch_get_global_queue(qos, 0), { () -> Void in

// Put your code here to work in the background

 dispatch_async(dispatch_get_main_queue(), { () -> Void in
            // Put your code here when the process is done and hand over to the main thread.
            // Ex. self.cards[newIndex].loadImage()
        })
    })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM