我想从我的应用程序中的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一起工作,我该如何解决这个问题。


当前回答

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
}

异步:

创建一个带有完成处理程序的方法,从您的url获取图像数据

func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
    URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}

创建一个方法来下载映像(启动任务)

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")
        // always update the UI from the main thread
        DispatchQueue.main.async() { [weak self] in
            self?.imageView.image = UIImage(data: data)
        }
    }
}

用法:

override func viewDidLoad() {
    super.viewDidLoad()
    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 UIImageView {
    func downloaded(from url: URL, contentMode mode: ContentMode = .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() { [weak self] in
                self?.image = image
            }
        }.resume()
    }
    func downloaded(from link: String, contentMode mode: ContentMode = .scaleAspectFit) { 
        guard let url = URL(string: link) else { return }
        downloaded(from: url, contentMode: mode)
    }
}

用法:

imageView.downloaded(from: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")

其他回答

Swift 3错误处理

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

与扩展

extension UIImageView {

    func setCustomImage(_ imgURLString: String?) {
        guard let imageURLString = imgURLString else {
            self.image = UIImage(named: "default.png")
            return
        }
        DispatchQueue.global().async { [weak self] in
            let data = try? Data(contentsOf: URL(string: imageURLString)!)
            DispatchQueue.main.async {
                self?.image = data != nil ? UIImage(data: data!) : UIImage(named: "default.png")
            }
        }
    }
}

扩展使用

myImageView. setCustomImage("url")

具有缓存支持

let imageCache = NSCache<NSString, UIImage>()

extension UIImageView {

    func loadImageUsingCacheWithURLString(_ 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: \(String(describing: error))")
                    DispatchQueue.main.async { [weak self] in
                        self?.image = placeHolder
                    }
                    return
                }
                DispatchQueue.main.async { [weak self] in
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self?.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }
}

在Swift中使用此代码

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

一种获取图像的方法是安全的,适用于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
    }

The reason this last part is needed if you are using the image in the UI is because network calls take time. If you try to update the UI using the image without calling dispatch_async like above, the computer will look for the image while the image is still being fetched, find that there is no image (yet), and move on as if there was no image found. Putting your code inside of a dispatch_async completion closure says to the computer, "Go, get this image and when you are done, then complete this code." That way, you will have the image when the code is called and things will work well.

你需要做的是:

UIImage(data: data)

在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

class ImageStore: NSObject { 
    static let imageCache = NSCache<NSString, UIImage>()
}

extension UIImageView {
    func url(_ url: String?) {
        DispatchQueue.global().async { [weak self] in
            guard let stringURL = url, let url = URL(string: stringURL) else {
                return
            }
            func setImage(image:UIImage?) {
                DispatchQueue.main.async {
                    self?.image = image
                }
            }
            let urlToString = url.absoluteString as NSString
            if let cachedImage = ImageStore.imageCache.object(forKey: urlToString) {
                setImage(image: cachedImage)
            } else if let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
                DispatchQueue.main.async {
                    ImageStore.imageCache.setObject(image, forKey: urlToString)
                    setImage(image: image)
                }
            }else {
                setImage(image: nil)
            }
        }
    }
}

用法:

let imageView = UIImageView()
imageView.url("image url")