私はURL非同期からの画像表示に取り組んでいます。ダウンロードイメージ用の新しいスレッドを作成し、main thread
で更新しようとしました。
func asyncLoadImg(product:Product,imageView:UIImageView){
let downloadQueue = dispatch_queue_create("com.myApp.processdownload", nil)
dispatch_async(downloadQueue){
let data = NSData(contentsOfURL: NSURL(string: product.productImage)!)
var image:UIImage?
if data != nil{
image = UIImage(data: data!)
}
dispatch_async(dispatch_get_main_queue()){
imageView.image = image
}
}
}
私がそれをデバッグしようとしたとき、dispatch_async(downloadQueue)に関しては、funcを飛び出しました。なにか提案を?どうも
Swift 3.0+更新コード:(jamesrochabrunリンクから助けを借りました https://github.com/jamesrochabrun/JSONTutorialFinal =)
let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
func imageFromServerURL(_ URLString: String, placeHolder: UIImage?) {
self.image = nil
if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
self.image = cachedImage
return
}
if let url = URL(string: URLString) {
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
//print("RESPONSE FROM API: \(response)")
if error != nil {
print("ERROR LOADING IMAGES FROM URL: \(error)")
DispatchQueue.main.async {
self.image = placeHolder
}
return
}
DispatchQueue.main.async {
if let data = data {
if let downloadedImage = UIImage(data: data) {
imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
self.image = downloadedImage
}
}
}
}).resume()
}
}
}
Swift 3更新コード:
extension UIImageView {
public func imageFromServerURL(urlString: String) {
self.image = nil
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
})
}).resume()
}}
Swift 2.2コード:
extension UIImageView {
public func imageFromServerURL(urlString: String) {
self.image = nil
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error)
return
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let image = UIImage(data: data!)
self.image = image
})
}).resume()
}}
サーバーurlから画像を読み込むためにこれを行う必要があるところはどこでも:
Swift 3.0を使用+プレースホルダーイメージを使用して更新されたコード:UIImageView.imageFromServerURL(URLString: "here server url"、placeHolder:uiimage形式のプレースホルダーイメージ)
Swfit 3以下:UIImageView.imageFromServerURL( "here server url")
シンプル!
Swift3
でextension
を使用します。 ネットワークの問題を解決するには、NSCache
を使用することをお勧めします。
import UIKit
let imageCache = NSCache<NSString, AnyObject>()
extension UIImageView {
func loadImageUsingCache(withUrl urlString : String) {
let url = URL(string: urlString)
self.image = nil
// check cached image
if let cachedImage = imageCache.object(forKey: urlString as NSString) as? UIImage {
self.image = cachedImage
return
}
// if not, download image from url
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
if let image = UIImage(data: data!) {
imageCache.setObject(image, forKey: urlString as NSString)
self.image = image
}
}
}).resume()
}
}
それが役立つことを願っています!
Shobhakar Tiwariの答えを引き継いで、これらのケースでエラーの場合にデフォルトのイメージを持っていると、ロードの目的で役立つことが多いと思うので、オプションのデフォルトのイメージを含めるように更新しました。
スイフト3
extension UIImageView {
public func imageFromServerURL(urlString: String, defaultImage : String?) {
if let di = defaultImage {
self.image = UIImage(named: di)
}
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error ?? "error")
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
})
}).resume()
}
}
このソリューションは、不必要な画像更新なしでスクロールを非常に高速にします。セルクラスにurlプロパティを追加する必要があります。
class OfferItemCell: UITableViewCell {
@IBOutlet weak var itemImageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
var imageUrl: String?
}
そして拡張子を追加します:
import Foundation
import UIKit
let imageCache = NSCache<AnyObject, AnyObject>()
let imageDownloadUtil: ImageDownloadUtil = ImageDownloadUtil()
extension OfferItemCell {
func loadImageUsingCacheWithUrl(urlString: String ) {
self.itemImageView.image = nil
if let cachedImage = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.itemImageView.image = cachedImage
return
}
DispatchQueue.global(qos: .background).async {
imageDownloadUtil.getImage(url: urlString, completion: {
image in
DispatchQueue.main.async {
if self.imageUrl == urlString{
imageCache.setObject(image, forKey: urlString as AnyObject)
self.itemImageView.image = image
}
}
})
}
}
}
また、それを改善し、より一般的なセルクラス(CustomCellWithImageなど)にコードを抽出して再利用可能にすることもできます。
blink
またはin Swift 4
効果なしで非同期画像を読み込む最も一般的なchanging images
の方法は、次のようなカスタムUIImageView
クラスに使用します。
//MARK: - 'asyncImagesCashArray' is a global varible cashed UIImage
var asyncImagesCashArray = NSCache<NSString, UIImage>()
class AyncImageView: UIImageView {
//MARK: - Variables
private var currentURL: NSString?
//MARK: - Public Methods
func loadAsyncFrom(url: String, placeholder: UIImage?) {
let imageURL = url as NSString
if let cashedImage = asyncImagesCashArray.object(forKey: imageURL) {
image = cashedImage
return
}
image = placeholder
currentURL = imageURL
guard let requestURL = URL(string: url) else { image = placeholder; return }
URLSession.shared.dataTask(with: requestURL) { (data, response, error) in
DispatchQueue.main.async { [weak self] in
if error == nil {
if let imageData = data {
if self?.currentURL == imageURL {
if let imageToPresent = UIImage(data: imageData) {
asyncImagesCashArray.setObject(imageToPresent, forKey: imageURL)
self?.image = imageToPresent
} else {
self?.image = placeholder
}
}
} else {
self?.image = placeholder
}
} else {
self?.image = placeholder
}
}
}.resume()
}
}
UITableViewCell
以下でこのクラスを使用する例:
class CatCell: UITableViewCell {
//MARK: - Outlets
@IBOutlet weak var catImageView: AyncImageView!
//MARK: - Variables
var urlString: String? {
didSet {
if let url = urlString {
catImageView.loadAsyncFrom(url: url, placeholder: nil)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
最良の方法の1つは、 SDWebImage を使用することです。
迅速な例:
import SDWebImage
imageView.sd_setImage(with: URL(string: "ImageUrl"), placeholderImage: UIImage(named: "placeholder.png"))
目標Cの例:
#import <SDWebImage/UIImageView+WebCache.h>
[imageView sd_setImageWithURL:[NSURL URLWithString:@"ImageUrl"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
ここで、このコードが役に立つかもしれません。
let cacheKey = indexPath.row
if(self.imageCache?.objectForKey(cacheKey) != nil){
cell.img.image = self.imageCache?.objectForKey(cacheKey) as? UIImage
}else{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
if let url = NSURL(string: imgUrl) {
if let data = NSData(contentsOfURL: url) {
let image: UIImage = UIImage(data: data)!
self.imageCache?.setObject(image, forKey: cacheKey)
dispatch_async(dispatch_get_main_queue(), {
cell.img.image = image
})
}
}
})
}
この画像では、テーブルビューのスクロールを遅らせることなくダウンロードしてキャッシュします