在Swift上从URL加载/下载图像

我想从我的应用程序中的URL加载图像,所以我第一次尝试与Objective-C和它的工作,但是,与Swift,我有一个编译错误:

'imageWithData'不可用:使用对象构造'UIImage(data :)'

我的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 } 

在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,我该如何解决这个问题。

Xcode 8•Swift 3

同步:

 if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) { imageView.contentMode = .scaleAspectFit imageView.image = image } 

asynchronous:

使用完成处理程序创build一个方法来从您的url获取图像数据

 func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) { URLSession.shared.dataTask(with: url) { data, response, error in completion(data, response, error) }.resume() } 

创build一个下载图像的方法(启动任务)

 func downloadImage(url: URL) { print("Download Started") getDataFromUrl(url: 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) } } } 

用法:

 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. print("Begin of code") if let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generichttp://img.dovov.comog.png") { imageView.contentMode = .scaleAspectFit downloadImage(url: url) } print("End of code. The image will continue downloading in the background and it will be loaded when it ends.") } 

扩展

  extension UIImageView { func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) { 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 downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) { guard let url = URL(string: link) else { return } downloadedFrom(url: url, contentMode: mode) } } 

用法:

 imageView.downloadedFrom(link: "http://www.apple.com/euro/ios/ios8/a/generichttp://img.dovov.comog.png") 

(Swift 3更新) Swift自第一个答案以来有所改变。 最简单的方法是:

 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!) 

编辑

如果要使代码运行asynchronous,可以使用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!) } } 

如果你只是想加载图像(asynchronous!) – 只需添加这个小的扩展到你的swift代码:

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = NSURL(string: urlString) { let request = NSURLRequest(URL: url) NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in if let imageData = data as NSData? { self.image = UIImage(data: imageData) } } } } } 

并以这种方式使用它:

 myImageView.imageFromUrl("123.png") 

Swift 2.2 || Xcode 7.3

我有惊人的结果 ! 与AlamofireImage Swift

它提供了多个function,如:

  • asynchronous下载
  • 自动清除图像caching,如果内存警告发生的应用程序
  • 图片urlcaching
  • 图像caching
  • 避免重复下载

并非常容易为您的应用程序实现

Step.1安装pod


Alamofire 3.3.x

荚'阿拉莫菲尔'

AlamofireImage 2.4.x

荚'AlamofireImage'

Step.2导入和使用

 import Alamofire import AlamofireImage let downloadURL = NSURL(string: "http://cdn.sstatic.net/Sites/stackoverflow/company/Img/photos/big/6.jpg?v=f4b7c5fee820")! imageView.af_setImageWithURL(downloadURL) 

而已!! 它会照顾一切


非常感谢Alamofire家伙 ,让iDevelopers的生活变得简单;)

Xcode 8Swift 3

狮子座达布斯的答案真棒! 我只是想提供一个全function的function解决scheme:

 let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generichttp://img.dovov.comog.png") let task = URLSession.shared.dataTask(with: url!) { data, response, error in guard let data = data, error == nil else { return } DispatchQueue.main.sync() { self.imageView.image = UIImage(data: data) } } task.resume() 

我将问题的最佳答案的代码包装成一个扩展UIImageView的单个可重用类,以便您可以直接在故事板中使用asynchronous加载UIImageView(或从代码创build它们)。

这是我的class级:

 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") 

仅供参考:对于swift-2.0 Xcode7.0 beta2

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = NSURL(string: urlString) { let request = NSURLRequest(URL: url) NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in self.image = UIImage(data: data!) } } } } 
 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) 

你会想要做的:

 UIImage(data: data) 

在Swift中,他们用常规的构造函数replace了大多数Objective C工厂方法。

看到:

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26

Swift 2error handling和自定义请求头

只需将扩展名添加到UIImageView:

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = NSURL(string: urlString) { let request = NSMutableURLRequest(URL: url) request.setValue("<YOUR_HEADER_VALUE>", forHTTPHeaderField: "<YOUR_HEADER_KEY>") NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in guard let data = data where error == nil else{ NSLog("Image download error: \(error)") return } if let httpResponse = response as? NSHTTPURLResponse{ if httpResponse.statusCode > 400 { let errorMsg = NSString(data: data, encoding: NSUTF8StringEncoding) NSLog("Image download error, statusCode: \(httpResponse.statusCode), error: \(errorMsg!)") return } } dispatch_async(dispatch_get_main_queue(), { NSLog("Image download success") self.image = UIImage(data: data) }) }.resume() } } } 

然后,使用新的imageFromUrl(urlString: String)来下载图像

用法:

 imageView.imageFromUrl("https://i.imgur.com/ONaprQV.png") 

Swift 2.0:

1)

 if let url = NSURL(string: "http://etc...") { if let data = NSData(contentsOfURL: url) { imageURL.image = UIImage(data: data) } } 

要么

 imageURL.image = NSURL(string: "http:// image name...") .flatMap { NSData(contentsOfURL: $0) } .flatMap { UIImage(data: $0) } 

2)将此方法添加到VC或扩展。

 func load_image(urlString:String) { let imgURL: NSURL = NSURL(string: urlString)! let request: NSURLRequest = NSURLRequest(URL: imgURL) NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in if error == nil { self.image_element.image = UIImage(data: data) } } } 

用法:

 self.load_image(" url strig here") 

Swift 3

这种方法将asynchronous下载一个网站的图像,并caching:

  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/generichttp://img.dovov.comog.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 } 

一种获取安全的图像的方法,适用于Swift 2.0和X-Code 7.1:

 static func imageForImageURLString(imageURLString: String, completion: (image: UIImage?, success: Bool) -> Void) { guard let url = NSURL(string: imageURLString), let data = NSData(contentsOfURL: url), let image = UIImage(data: data) else { completion(image: nil, success: false); return } completion(image: image, success: true) } 

然后你会这样调用这个方法:

 imageForImageURLString(imageString) { (image, success) -> Void in if success { guard let image = image else { return } // Error handling here // You now have the image. } else { // Error handling here. } } 

如果你正在用图像更新视图,你必须在“if success {”之后使用这个:

  dispatch_async(dispatch_get_main_queue()) { () -> Void in guard let image = image else { return } // Error handling here // You now have the image. Use the image to update the view or anything UI related here // Reload the view, so the image appears } 

如果您在UI中使用图像,则需要使用最后一部分的原因是因为networking呼叫需要时间。 如果您尝试使用图像更新UI而不调用像上面那样的dispatch_async,则计算机将在图像仍在提取时查找图像,发现没有图像(尚未),然后继续前进,好像没有图像find。 把你的代码放入一个dispatch_async完成闭包里,对计算机说:“去,得到这个图像,当你完成了,然后完成这个代码。” 这样,当代码被调用时,你将拥有图像,而且事情会很好。

如果你正在寻找一个非常简单的实现。 (这在Swift 2中为我工作)

  let imageURL = NSURL(string: "1591/26078338233_d1466b7da2_m.jpg") let imagedData = NSData(contentsOfURL: imageURL!)! imageView?.image = UIImage(data: imagedData) 

我在一个只有一个图像的自定义单元格的tableview实现

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ let cell = tableView.dequeueReusableCellWithIdentifier("theCell", forIndexPath: indexPath) as! customTableViewCell let imageURL = NSURL(string: "1591/26078338233_d1466b7da2_m.jpg") let imagedData = NSData(contentsOfURL: imageURL!)! cell.imageView?.image = UIImage(data: imagedData) return cell } 

迅速3与error handling

 let url = URL(string: arr[indexPath.row] as! String) if url != nil { 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 { if data != nil { cell.imgView.image = UIImage(data:data!) }else{ cell.imgView.image = UIImage(named: "default.png") } } } } 

唯一缺less的就是一个!

 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!) 

在Swift中使用这个代码

 imageView.image=UIImage(data: NSData(contentsOfURL: NSURL(string: "http://myURL/ios8.png")!)! 

Swift 2.x答案将图像下载到文件(而不是Leo Dabus的答案,它将图像存储在内存中)。 根据Leo Dabus的回答和Rob的回答从NSURLSession的DownloadTaskWithRequest获取来自完成处理程序的数据 :

  // Set download vars let downloadURL = NSURL() // URL to download from let localFilename = "foobar.png" // Filename for storing locally // Create download request let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in guard location != nil && error == nil else { print("Error downloading message: \(error)") return } // If here, no errors so save message to permanent location let fileManager = NSFileManager.defaultManager() do { let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false) let fileURL = documents.URLByAppendingPathComponent(localFilename) try fileManager.moveItemAtURL(location!, toURL: fileURL) self.doFileDownloaded(fileURL, localFilename: localFilename) print("Downloaded message @ \(localFilename)") } catch { print("Error downloading message: \(error)") } } // Start download print("Starting download @ \(downloadURL)") task.resume() // Helper function called after file successfully downloaded private func doFileDownloaded(fileURL: NSURL, localFilename: String) { // Do stuff with downloaded image } 

对于Swift-3及以上版本:

 extension UIImageView { public func imageFromUrl(urlString: String) { if let url = URL(string: urlString) { let request = URLRequest(url: url) NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: .main, completionHandler: { (response, data, error) in if let imageData = data as NSData? { self.image = UIImage(data: imageData as Data) } }) } } }