本文翻译自:Loading/Downloading image from URL on Swift
I'd like to load an image from a URL in my application, so I first tried with Objective-C and it worked, however, with Swift, I've a compilation error: 我想从我的应用程序中的URL加载图像,因此我首先尝试使用Objective-C,但是它可以正常工作,但是对于Swift,我遇到了编译错误:
'imageWithData' is unavailable: use object construction 'UIImage(data:)' 'imageWithData'不可用:使用对象构造'UIImage(data :)'
My function: 我的功能:
@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
}
In Objective-C: 在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";
}
Can someone please explain me why the imageWithData:
doesn't work with Swift, and how can I solve the problem. 有人可以解释一下为什么imageWithData:
不能与Swift一起工作,以及如何解决该问题。
#1楼
参考:https://stackoom.com/question/1dflY/在Swift上从URL加载-下载图像
#2楼
You'll want to do: 您需要执行以下操作:
UIImage(data: data)
In Swift, they've replaced most Objective C factory methods with regular constructors. 在Swift中,他们已将大多数Objective C工厂方法替换为常规构造函数。
See: 看到:
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26 https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26
#3楼
let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
var err: NSError?
var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
var bgImage = UIImage(data:imageData)
#4楼
The only things there is missing is a ! 唯一缺少的是!
let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
var err: NSError?
var imageData :NSData = NSData.dataWithContentsOfURL(url!,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
var bgImage = UIImage(data:imageData!)
#5楼
(Swift 4 update) To answer the original question directly, here's the swift equivalent of the posted Objective-C snippet. (快速更新4)要直接回答原始问题,以下是发布的Objective-C代码片段的快速等效内容。
let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)
DISCLAIMER: 免责声明:
It's important to note that the Data(contentsOf:)
method will download the contents of the url synchronously in the same thread the code is being executed, so do not invoke this in the main thread of your application. 重要的是要注意, Data(contentsOf:)
方法将在正在执行代码的同一线程中同步下载url的内容,因此请不要在应用程序的主线程中调用它。
An easy way to make the same code run asynchronously, not blocking the UI, is by using GCD: 使同一代码异步运行而不阻塞UI的一种简单方法是使用GCD:
let url = URL(string: image.url)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
DispatchQueue.main.async {
imageView.image = UIImage(data: data!)
}
}
That said, in real life applications, if you want to have the best User Experience and avoid multiple downloads of the same image, you may want to also have them not only downloaded, but cached. 就是说,在现实生活中的应用程序中,如果要获得最佳的用户体验并避免多次下载同一图像,则可能不仅要下载它们,还要对其进行缓存。 There's already quite a few libraries that does that very seamless and they are all really easy to use. 已经有很多库可以做到非常无缝,它们都非常易于使用。 I personally recommend Kingfisher : 我个人推荐翠鸟 :
import Kingfisher
let url = URL(string: "url_of_your_image")
// this downloads the image asynchronously if it's not cached yet
imageView.kf.setImage(with: url)
And that's it 就是这样
#6楼
Xcode 8 or later • Swift 3 or later Xcode 8或更高版本•Swift 3或更高版本
Synchronously: 同步:
if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) {
imageView.contentMode = .scaleAspectFit
imageView.image = image
}
Asynchronously: 异步地:
Create a method with a completion handler to get the image data from your url 创建带有完成处理程序的方法以从您的网址获取图像数据
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
Create a method to download the image (start the task) 创建下载图像的方法(启动任务)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
DispatchQueue.main.async() {
self.imageView.image = UIImage(data: data)
}
}
}
Usage: 用法:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("Begin of code")
let url = URL(string: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")!
downloadImage(from: url)
print("End of code. The image will continue downloading in the background and it will be loaded when it ends.")
}
Extension : 扩展名 :
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) { // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
Usage: 用法:
imageView.downloaded(from: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")