线程(异步队列)如何在Swift中工作?

时间:2015-04-23 18:12:56

标签: ios multithreading swift

好的我正在更新这个问题,但在那里留下旧问题。 所以我有一个数组,用于在uipageviewcontroller中存储不同视图的数据。我需要在后台抓取图像数据。我不了解如何在异步任务中编写代码。 下面是该任务的代码:

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
                    }
                }

这就是.loadImag()函数的样子:

    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)
    }
    }
}

这是self.imagesCallback代码:

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

问题是我不知道如何将此代码放在操作提示中,因为该函数必须有回调。如何让操作队列工作以便更新uipageviewcontroller中的self.card数组?

旧问题_________________: 所以我需要这行代码,我需要在与主线程不同的线程中并发运行。当我将它添加到主队列时,如下所示:

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

这样做效果很好,但似乎并不是同时运行。当我像这样将队列更改为并发时:

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

该应用程序崩溃说" EXC_BAD_ACCESS"。我在这做错了什么?另外当我在另一个并发线程中运行self.cards [newIndex] .loadImage()函数时,这会更新主线程中的值吗?

3 个答案:

答案 0 :(得分:3)

除非您想明确使用仅在GCD上可用的功能,否则不应使用GCD。对于您的情况,使用NSOperationQueue更有益(并且代码更清晰)。 NSOperationQueue在后台使用GCD并且更安全(更少的方法搞乱)

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
    }
}

您还可以阅读Apple Concurrency Programming Guide 该指南使用了Objective-C的示例,但是Swift的API基本相同。

它也可能看起来很奇怪但是addOperationWithBlock()我使用了一种叫做“尾随闭包”的东西,你可以阅读here关于它的内容

答案 1 :(得分:0)

您需要使用dispatch_get_global_queue。尝试类似:

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, {self.cards[newIndex].loadImage()})
正如您所尝试的那样,

dispatch_get_main_queue()在UI /主线程上运行,这就是您看到所做行为的原因。

要回答问题的第二部分,如果loadImage()正在修改用户界面,则您不希望从后台线程执行此操作。 必须从主/ UI线程完成。一个典型的习语是,从主线程做:

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>   
    })
})

答案 2 :(得分:0)

您可以粘贴整个代码,以便我们可以看到您在做什么吗? 下面是非常基本的代码片段。这基本上是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()
        })
    })