我想从我的应用程序中的URL加载图像,所以我首先尝试了Objective-C和它的工作,但是,与Swift,我有一个编译错误:
'imageWithData'不可用:使用对象构造'UIImage(data:)'
我的函数:
@IBOutlet var imageView : UIImageView
override func viewDidLoad() {
super.viewDidLoad()
var url:NSURL = NSURL.URLWithString("http://myURL/ios8.png")
var data:NSData = NSData.dataWithContentsOfURL(url, options: nil, error: nil)
imageView.image = UIImage.imageWithData(data)// Error here
}
在objective - c中:
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:(@"http://myURL/ios8.png")];
NSData *data = [NSData dataWithContentsOfURL:url];
_imageView.image = [UIImage imageWithData: data];
_labelURL.text = @"http://www.quentinroussat.fr/assets/img/iOS%20icon's%20Style/ios8.png";
}
有人能解释一下为什么imageWithData:不能与Swift一起工作,我该如何解决这个问题。
干净的方式:
extension URL {
var favIcon16: UIImage? { getFav(ofSize: .s) }
var favIcon32: UIImage? { getFav(ofSize: .m) }
var favIcon64: UIImage? { getFav(ofSize: .l) }
var favIcon128: UIImage? { getFav(ofSize: .xl) }
var favIcon256: UIImage? { getFav(ofSize: .xxl) }
var favIcon512: UIImage? { getFav(ofSize: .xxxl) }
private func getFav(ofSize s: FavSize) -> UIImage? {
guard UIApplication.shared.canOpenURL(self),
let favUrl = URL(string: "https://www.google.com/s2/favicons?sz=\(s.rawValue)&domain=\(self.absoluteURL)"),
let data = try? Data(contentsOf: favUrl)
else { return nil }
return UIImage(data: data)
}
private enum FavSize: Int, CaseIterable { case s = 16, m = 32, l = 64, xl = 128, xxl = 256, xxxl = 512 }
}
和用法:
let myUrl = URL(string: "http://facebook.com")
myImgView.image = myUrl.favIcon16
斯威夫特4
这个方法将从一个网站异步下载图像并缓存它:
func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) {
guard let url = URL(string: urlString) else {
return closure(nil)
}
let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
guard error == nil else {
print("error: \(String(describing: error))")
return closure(nil)
}
guard response != nil else {
print("no response")
return closure(nil)
}
guard data != nil else {
print("no data")
return closure(nil)
}
DispatchQueue.main.async {
closure(UIImage(data: data!))
}
}; task.resume()
}
在使用:
getImageFromWeb("http://www.apple.com/euro/ios/ios8/a/generic/images/og.png") { (image) in
if let image = image {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
imageView.image = image
self.view.addSubview(imageView)
} // if you use an Else statement, it will be in background
}
斯威夫特4::
这将在加载图像时显示加载器。
你可以使用NSCache临时存储图像
let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
func loadImageUsingCache(withUrl urlString : String) {
let url = URL(string: urlString)
if url == nil {return}
self.image = nil
// check cached image
if let cachedImage = imageCache.object(forKey: urlString as NSString) {
self.image = cachedImage
return
}
let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView.init(activityIndicatorStyle: .gray)
addSubview(activityIndicator)
activityIndicator.startAnimating()
activityIndicator.center = self.center
// 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
activityIndicator.removeFromSuperview()
}
}
}).resume()
}
}
用法:-
truckImageView.loadImageUsingCache(withUrl: currentTruck.logoString)
我建议使用Kingfisher库来异步下载图像。使用翠鸟最好的部分是,它默认缓存所有下载的图像,图像url作为id。下次当您请求下载具有特定URl的图像时,它将从缓存中加载它。
用法:
newsImage.kf.setImage(with: imageUrl!, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, imageUrl) in
if error == nil{
self.activityIndicator.stopAnimating()
}else if error != nil{
self.activityIndicator.stopAnimating()
}
})
我把这个问题的最佳答案的代码包装成一个单一的,可重用的类扩展UIImageView,所以你可以直接在你的故事板中使用异步加载UIImageViews(或从代码中创建它们)。
这是我的班级:
import Foundation
import UIKit
class UIImageViewAsync :UIImageView
{
override init()
{
super.init(frame: CGRect())
}
override init(frame:CGRect)
{
super.init(frame:frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func getDataFromUrl(url:String, completion: ((data: NSData?) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) { (data, response, error) in
completion(data: NSData(data: data))
}.resume()
}
func downloadImage(url:String){
getDataFromUrl(url) { data in
dispatch_async(dispatch_get_main_queue()) {
self.contentMode = UIViewContentMode.ScaleAspectFill
self.image = UIImage(data: data!)
}
}
}
}
下面是如何使用它:
imageView.downloadImage("http://www.image-server.com/myImage.jpg")