簡體   English   中英

UI即使使用dispatch_get_main_queue()也不會更新

[英]UI not updating even with dispatch_get_main_queue()

我知道對UI的所有更新都需要在主線程上進行。 我有發出Alamofire請求的代碼,並在解析JSON響應中的每個項目時向用戶更新進度。 我在設置UILabel文本的行周圍放置了dispatch_async(dispatch_get_main_queue()){} ,但標簽未更新。 我的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
                }
            }       
        }
    }

我發布答案不是因為我自己想到了這個主意,而是因為我想向讀者提供解決問題的實際代碼。

基於上述建議,我現在在后台線程上轉換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.
                        })
                    }
              })
        }

這給我帶來了很多問題。 我希望這對將來的讀者有用。 以下是對我有用的方法:

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

嘗試使用performSelectorOnMainThread方法更新main thread上的label

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM