我是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秒内加载图像。
答案 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)
在iOS 8之后使用NSURLSession.dataTaskWithURL
执行此操作的推荐方法请参阅: sendAsynchronousRequest was deprecated in iOS 9, How to alter code to fix