异步图像下载功能Swift - 一些图像不返回

时间:2015-02-22 18:42:50

标签: swift

由于某种原因,此函数返回大多数有效图像,但对于某些函数,它只返回任何内容。它显示正在交换的数据,但图像没有正确返回。有人可以帮助我改进这个功能一些如何解决这个问题。

    func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in
        var data: NSData? = self.cache.objectForKey(urlString) as? NSData

        if let goodData = data {
            let image = UIImage(data: goodData)
            dispatch_async(dispatch_get_main_queue(), {() in
                completionHandler(image: image, url: urlString)
            })
            return
        }

        var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
            if (error != nil) {
                println(error)
                completionHandler(image: nil, url: urlString)
                return
            }

            if data != nil {
                println(data)
                let image = UIImage(data: data)
                self.cache.setObject(data, forKey: urlString)
                dispatch_async(dispatch_get_main_queue(), {() in
                    completionHandler(image: image, url: urlString)
                })
                return
            }

        })
        downloadTask.resume()
    })
}

这是我正在使用的全班,它也有作者学分。

//
//  ImageLoader.swift
//  extension
//
//  Created by Nate Lyman on 7/5/14.
//  Copyright (c) 2014 NateLyman.com. All rights reserved.
//
import UIKit
import Foundation


class ImageLoader {

    var cache = NSCache()

    class var sharedLoader : ImageLoader {
        struct Static {
            static let instance : ImageLoader = ImageLoader()
        }
        return Static.instance
    }

    func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in
            var data: NSData? = self.cache.objectForKey(urlString) as? NSData

            if let goodData = data {
                let image = UIImage(data: goodData)
                dispatch_async(dispatch_get_main_queue(), {() in
                    completionHandler(image: image, url: urlString)
                })
                return
            }

            var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
                if (error != nil) {
                    println(error)
                    completionHandler(image: nil, url: urlString)
                    return
                }

                if data != nil {
                    println(data)
                    let image = UIImage(data: data)
                    self.cache.setObject(data, forKey: urlString)
                    dispatch_async(dispatch_get_main_queue(), {() in
                        completionHandler(image: image, url: urlString)
                    })
                    return
                }

            })
            downloadTask.resume()
        })
    }
}

3 个答案:

答案 0 :(得分:2)

您在不同主题中使用self.cachedispatch_async vs dataTaskWithURL

不要重新发明轮子,使用经过良好测试的库来进行此类事情

  

https://github.com/Alamofire/Alamofire

下载图像并将其存储在缓存中令人惊讶的不是iOS上的简单编程任务。

此外,您可以使用同一作者的Objective-C库

  

https://github.com/AFNetworking/AFNetworking

UIImageView可以直接在UI控件中下载图像(并将它们存储在系统和内存缓存中)。

答案 1 :(得分:1)

为什么要努力工作。有很多方法可以用更少的代码来做同样的事情。

func downloadImage(url: NSURL, handler: ((image: UIImage, error: NSError!) -> Void)) {
        var imageRequest: NSURLRequest = NSURLRequest(URL: url)
        NSURLConnection.sendAsynchronousRequest(imageRequest,
            queue: NSOperationQueue.mainQueue(),
            completionHandler:{response, data, error in
                handler(image: UIImage(data: data)!, error: error)
        })
    }

答案 2 :(得分:0)

我同意其他人的看法,您应该考虑使用SDWebImageAFNetworking等完善的框架。

如果要解决此问题,则应改进错误日志记录。我还建议检查HTTP状态代码:

func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) {
    if let data = self.cache.objectForKey(urlString) as? NSData {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
            let image = UIImage(data: data)
            dispatch_async(dispatch_get_main_queue()) {
                completionHandler(image: image, url: urlString)
            }
        }
        return
    }

    let downloadTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!) { data, response, error in

        // report basic networking errors

        if data == nil {
            println("\(urlString) error \(error)")
            dispatch_async(dispatch_get_main_queue()) {
                completionHandler(image: nil, url: urlString)
            }
            return
        }

        // report HTTP errors

        if let httpResponse = response as? NSHTTPURLResponse {
            let statusCode = httpResponse.statusCode
            if statusCode != 200 {
                println("\(urlString): statusCode = \(statusCode)")
                dispatch_async(dispatch_get_main_queue()) {
                    completionHandler(image: nil, url: urlString)
                }
                return
            }
        }

        // no HTTP error, let's try to get image

        if let image = UIImage(data: data) {
            self.cache.setObject(data, forKey: urlString)
            dispatch_async(dispatch_get_main_queue()) {
                completionHandler(image: image, url: urlString)
            }
        } else {
            println("\(urlString) found in cache, but not valid image")  // should never get here
            dispatch_async(dispatch_get_main_queue()) {
                completionHandler(image: nil, url: urlString)
            }
        }
    }

    downloadTask.resume()
}