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


当前回答

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

免责声明:

需要注意的是,Data(contentsOf:)方法将在执行代码的同一线程中同步下载url的内容,因此不要在应用程序的主线程中调用此方法。

让相同的代码异步运行,而不阻塞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!)
    }
}

也就是说,在现实生活中的应用程序中,如果您希望获得最佳的用户体验并避免同一映像的多次下载,您可能还希望不仅下载它们,而且缓存它们。已经有相当多的库可以无缝地做到这一点,而且它们都非常易于使用。我个人推荐翠鸟:

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) 

就是这样

其他回答

斯威夫特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)

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中使用此代码

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

您可以使用pod SDWebImage来实现相同的功能。它很容易使用。你可以在SDWebImage这里获得文档

下面是示例代码

self.yourImage.sd_setImage(with: NSURL(string: StrUrl as String ) as URL!, placeholderImage: placeholderImage, options: SDWebImageOptions(rawValue: 0), completed: { (image, error, cacheType, imageURL) in
                if( error != nil)
                {
                    print("Error while displaying image" , (error?.localizedDescription)! as String)
                }
            })

这是从URL加载/下载图像的工作代码。NSCache自动和显示占位符图像下载和加载实际图像(Swift 4 | Swift 5代码)。

func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){
    
    if image != nil && imageView != nil {
        imageView!.image = image!
    }
    
    var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
    let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    urlcatch = documentpath + "/" + "\(urlcatch)"
    
    let image = UIImage(contentsOfFile:urlcatch)
    if image != nil && imageView != nil
    {
        imageView!.image = image!
        compate(image)
        
    }else{
        
        if let url = URL(string: imgUrl){
            
            DispatchQueue.global(qos: .background).async {
                () -> Void in
                let imgdata = NSData(contentsOf: url)
                DispatchQueue.main.async {
                    () -> Void in
                    imgdata?.write(toFile: urlcatch, atomically: true)
                    let image = UIImage(contentsOfFile:urlcatch)
                    compate(image)
                    if image != nil  {
                        if imageView != nil  {
                            imageView!.image = image!
                        }
                    }
                }
            }
        }
    }
}

像这样使用:

// Here imgPicture = your imageView
// UIImage(named: "placeholder") is Display image brfore download and load actual image. 

NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }