2016-08-23 51 views
0

我是iOS開發新手,所以任何幫助,將不勝感激。如何異步從URL加載文本文件,然後從文本文件中的URL中異步加載圖像? (在迅速)

項目:我正在開發一款適用於iOS的表情符號風格的鍵盤。當鍵盤第一次加載時,它會從互聯網上下載一個帶有圖像URL的.txt文件(這樣我可以通過更新.txt文件來添加/刪除/重新排序圖像)。圖像URL被輸入到一個數組中,然後圖像URL數組被用來填充一個集合視圖。

我寫的代碼有效,但是當我切換到我的鍵盤時,系統會一直等待,直到彈出鍵盤之前一切都已加載(通常爲2-3秒)。 我想讓鍵盤在沒有圖像的情況下立即彈出,然後在圖像可用時加載圖像 - 這樣用戶可以看到鍵盤正常工作。

如何讓鍵盤立即加載,然後下載文本文件,然後下載圖像?我發現了很多有關圖像異步下載的信息,但是我的問題是隨着文本下載的增加而稍微複雜一點,我無法弄清楚。

更多信息:

我使用SDWebImage加載所以他們是很好的緩存和應該異步加載,但我有它的方式結束了鍵盤等待,直到一切都被下載到圖像顯示。

我試着在下面的代碼中包裝下面的「do {} catch {}」部分 - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //do-catch code }) - 當我這樣做時,鍵盤會立即彈出來,而不是加載圖像,它需要8-10秒,它仍然在顯示任何圖像之前等待所有圖像。

以下是我的代碼。我通過刪除正在工作的按鈕和其他代碼簡化了代碼。沒有與此代碼相關聯的兩個文件的.xib:KeyboardView和ImageCollectionViewCell

import UIKit 
import MobileCoreServices 
import SDWebImage 


class ImageCollectionViewCell:UICollectionViewCell { 
    @IBOutlet var imgView:UIImageView! 
} 

class KeyboardViewController: UIInputViewController, UICollectionViewDataSource, UICollectionViewDelegate { 

    @IBOutlet var collectionView: UICollectionView! 

    let blueMojiUrl = NSURL(string: "http://example.com/list/BlueMojiList.txt") 
    var blueMojiArray = NSMutableArray() 

    func isOpenAccessGranted() -> Bool { 
     // Function to test if Open Access is granted 
     return UIPasteboard.generalPasteboard().isKindOfClass(UIPasteboard) 
    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     let nib = UINib(nibName: "KeyboardView", bundle: nil) 
     let objects = nib.instantiateWithOwner(self, options: nil) 
     self.view = objects[0] as! UIView; 

     self.collectionView.registerNib(UINib(nibName: "ImageCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ImageCollectionViewCell") 


     if (isOpenAccessGranted()) == false { 
      // Open Access is NOT granted - display error instructions 

     } else { 
      // Open Access IS granted 

       do { 

       self.blueMojiArray = NSMutableArray(array: try NSString(contentsOfURL: self.blueMojiUrl!, usedEncoding: nil).componentsSeparatedByString("\n")); 

       self.collectionView.reloadData() 

      } catch { 
       // Error connecting to server - display error instructions 
      } 

     } 

    } // End ViewDidLoad 


    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return self.blueMojiArray.count 
    } 


    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 

     let iCell = collectionView.dequeueReusableCellWithReuseIdentifier("ImageCollectionViewCell", forIndexPath: indexPath) as! ImageCollectionViewCell 
     let url = NSURL(string: self.blueMojiArray.objectAtIndex(indexPath.row) as! String) 

     iCell.imgView.sd_setImageWithURL(url, placeholderImage: UIImage(named: "loading")) 

     iCell.layer.cornerRadius = 10.0 

     return iCell 
    } 

} 

UPDATE: 感謝您的答案。我能夠用Alamofire解決我的問題。我將Alamofire吊艙安裝到了我的項目中。我用來解決我的問題的具體代碼:首先,我在上面添加import Alamofire,然後我刪除了禁止{}趕上{}碼以上,並與

Alamofire.request(.GET, blueMojiUrl!) 
       .validate() 
       .responseString { response in 

        switch response.result { 

        case .Success: 
         let contents = try? NSString(contentsOfURL: self.blueMojiUrl!, usedEncoding: nil) 
         self.blueMojiArray = NSMutableArray(array: contents!.componentsSeparatedByString("\n")) 

        self.collectionView.reloadData() 


        case .Failure: 
         // Error connecting to server - display error instructions 
        } 
      } 

現在鍵盤負載瞬間取代了它,其次是圖像在2-3秒內加載。

回答

0

我會做這樣的事情:

cellForItemAtIndexPath調用方法下載圖像與當前單元格完成處理器。在下載完成時,將單元格的圖像設置爲下載的圖像,並調用該單元格的方法reloadItemsAtIndexPaths

示例代碼:

func downloadPlaceholderImage(url: String, completionHandler: (image: UIImage) ->()) { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
     /// download logic 
      completionHandler(image: downloadedImage) 
     })    
    } 
} 

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
    /// 
    downloadPlaceHolderImage("url", completionHandler: { image in 
    cell.image = image 
    self.collectionView.reloadItemsAtIndexPaths([indexPath]) 
    }) 
    /// 
} 
+0

謝謝!在我的情況下,使用reloadItemsAtIndexPaths會導致問題,因爲我有幾個集合,所以它們堆疊在一起:)我能夠使它與Alamofire正常工作,並且用結果更新了我的問題。感謝您的回覆,我感謝您花時間提供幫助。 –