即使使用dispatch_get_main_queue()

时间:2017-03-25 09:27:21

标签: ios swift alamofire dispatch-async

我知道UI的所有更新都需要在主线程上进行。我有一个代码,它发出Alamofire请求,并通过解析JSON响应中的每个项目所取得的进展来更新用户。我已将dispatch_async(dispatch_get_main_queue()){}放在设置UILabel文本的行周围,但标签未更新。我的for循环打印到日志“我们在项目0上”,“我们在项目1上”等等,并且我的标签文本从未出现过。如果我在getPhotoCollection()函数结束后更新标签,标签文本会按预期显示 - 所以我的UILabel本身没有任何问题。

我发现无数Stack Overflow帖子说如果你想从不在主线程上的代码更新UI,只需将其包装在dispatch_async(dispatch_get_main_queue()){}中。那为什么不起作用?

这是我的代码。我已经留下了一些不相关的部分,以防它们成为这个问题发生的部分原因。

func getPhotoCollection(urlString: String, finished: (success: Bool, numResults: Int) -> Void) {
    Alamofire.request(.GET, urlString, parameters: nil, encoding: .JSON)
        .validate()
        .responseJSON { (response) -> Void in
            guard response.result.isSuccess else {
                finished(success: false, numResults: 0)
                return
             }  
            let json = response.result.value!
            if let items = json["items"] as? NSArray {
                 let numResults = items.count
                 if numResults > 0 {    
                     self.photoArray.removeAll()
                     var itemNum = 0
                     for item in items {
                         var photo: UIImage!                        
                         let jsonItem = JSON(item)
                         let photoURLString = jsonItem["url"].stringValue
                         let url = NSURL(string: photoURLString)
                         print("We're on item \(itemNum)")
                         if let imageData = NSData(contentsOfURL: url!) {
                             dispatch_async(dispatch_get_main_queue()) {
                                 self.progressLabel.text = String(itemNum + 1) + " photos found"
                             }
                             photo = UIImage(data: data)
                             self.photoArray.append(photo)
                             itemNum++
                            }
                        }
                    }
                    finished(success: true, numResults: numResults)
                    return
                }
            }       
        }
    }

3 个答案:

答案 0 :(得分:0)

我发布的答案不是因为我自己想出了这个想法,而是因为我想为读者提供解决问题的实际代码。

根据上述建议,我现在在后台线程上转换NSData,并在该块中更新主线程上的UILabel。这是代码,从for循环开始:

    var itemNum = 1                     
    let qualityOfServiceClass = QOS_CLASS_BACKGROUND
    let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
    for item in items {
        let jsonItem = JSON(item)
        let photoURLString = jsonItem["postingImageUrl"].stringValue
        let url = NSURL(string: photoURLString)
            dispatch_async(backgroundQueue, {

                if let imageData = NSData(contentsOfURL: url!) {
                    let photo = UIImage(data: imageData)
                    self.photosBeingDisplayed.append(photo!)                                
                    dispatch_async(dispatch_get_main_queue(), { () -> Void in
                        self.progressLabel.text = String(itemNum) + " photos found"
                        itemNum++ // We increment itemNum here rather than in the main code of the for loop because these photos are getting processed on the background thread and we are not guaranteed they will finish in order.
                        })
                    }
              })
        }

答案 1 :(得分:0)

这给我带来了很多问题。我希望这对未来的读者有用。当没有任何事情没有时,以下对我有用:

self.label.text = ....
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];

答案 2 :(得分:-1)

尝试使用label方法更新main thread上的performSelectorOnMainThread