如何从URL异步加载文本文件,然后从文本文件中的URL异步加载图像? (快速地)

时间:2016-08-23 16:51:02

标签: ios swift asynchronous keyboard

我是iOS开发的新手,所以任何帮助都会受到赞赏。

项目:我正在为iOS开发一个Emoji风格的键盘。当键盘首次加载时,它会从Internet下载带有图像URL的.txt文件(这样我只需通过更新.txt文件即可添加/删除/重新排序图像)。将图像URL输入到数组中,然后使用图像URL数组填充集合视图。

我编写的代码有效,但是当我切换到键盘时,系统会等到键盘弹出之前所有内容都加载(通常为2-3秒)。 我想要的是键盘在没有图像的情况下立即弹出,然后在图像可用时加载 - 这样用户就可以看到键盘正常工作。

如何让键盘立即加载,然后下载文本文件,然后下载图像?我找到了很多关于图像异步下载的信息,但我的问题是添加文本下载更加复杂,我无法弄明白。

更多信息:

我正在使用SDWebImage来加载图像,因此它们可以很好地缓存,并且应该异步加载,但是我把它包裹起来的方式是等待所有内容下载到显示器。

我尝试将下面代码中的“do {} catch {}”部分包装在内部 - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { //do-catch code }) - 当我这样做时,键盘会立即弹出,就像我想要的那样,而不是2-3秒加载这些图像需要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
    }

}

更新 谢谢你的回答。我能用Alamofire修复我的问题。我在我的项目中安装了Alamofire pod。我用来修复问题的具体代码:首先我在顶部添加了import Alamofire,然后删除了上面的do {} catch {}代码并将其替换为

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秒内加载图像。

2 个答案:

答案 0 :(得分: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])
   })
  ///  
}

答案 1 :(得分:-1)