ios - 如何从我通过 API 调用获得的 url 加载图像

标签 ios swift uiimageview uicollectionview ios9

我想使用 UICollectionView 来显示图像,我通过 api 调用获取图像。

问题:所以我通过 api 调用获取图像路径,那么如何将它显示到 UICollectionView??

这是我的代码::

  func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let dic = imagearray .objectAtIndex(indexPath.row) as! NSDictionary
    let cell :imagecell = collectionView.dequeueReusableCellWithReuseIdentifier("imagecell", forIndexPath: indexPath) as! imagecell

    cell.imagev.image = dic["image"] as? UIImage
    return cell
}

这是我的 api 响应

(
    {
    image = "http://radio.spainmedia.es/wp-content/uploads/2015/12/esquire.jpg";
    slug = esquire;
},
    {
    image = "http://radio.spainmedia.es/wp-content/uploads/2015/12/forbes.jpg";
    slug = forbes;
},
    {
    image = "http://radio.spainmedia.es/wp-content/uploads/2015/12/tapas.jpg";
    slug = tapas;
}
)

那么如何在我的 UICollectionView 中显示这些图像

更新::在使用注释代码时遇到奇怪的问题时,我在 viewdidload 中调用我的网络服务

override func viewDidLoad() {
    super.viewDidLoad()

    webimages()

    // Do any additional setup after loading the view, typically from a nib.
}

开始调用webservice

func webimages()
{

let url = "http://radio.spainmedia.es/podcasts/"

    request(.GET, url, parameters: nil, encoding: .JSON).responseJSON { (response:Response<AnyObject, NSError>) -> Void in


           print(response.result.value)

            self.imagearray = (response.result.value) as! NSMutableArray
            print(self.imagearray)


    }

}

但是在请求它之后突然转到 cellForItemAtIndexPath 所以我的“imagearray”在那里找到了 nil。然后它返回到 webimages() 并给我 api 响应。

那我该如何解决呢?

we have array of string we are passing single string here so can you please tell me that what is the solution

我们有字符串数组,我们在这里传递单个字符串,所以你能告诉我解决方案是什么吗

enter image description here

最佳答案

您正在将 URL 字符串设置为 UIImage。您首先必须先从该 URL 检索图像。使用以下方法快速补救:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell :imagecell = collectionView.dequeueReusableCellWithReuseIdentifier("imagecell", forIndexPath: indexPath) as! imagecell
    if imagearray.count > 0 
    {
       let dic = imagearray .objectAtIndex(indexPath.row) as! NSDictionary

       let imgURL: NSString = dic!["image"] as! NSString //Get URL string
       let url = NSURL.URLWithString(imgURL); //Create URL
       var err: NSError?
       var imageData :NSData = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)! //Fetch Image Data
       var cellImage = UIImage(data:imageData) //Create UIImage from Image data
       cell.imagev.image = cellImage //Set image
    }

    return cell
}

请注意,这是在同步调用中获取图像 URL 的内容,这样会卡住您的 UI,直到下载完成。此外,这不会缓存图像,因此当您滚动并重新创建单元格时,图像将被一遍又一遍地下载。为避免这种情况,我建议缓存。

为了获得更好的结果,这是异步加载图像的方式,不会卡住 UI 并缓存图像以避免网络负载。

你首先必须像这样创建一个类:

class ImageLoader {

var cache = NSCache() //Create cache

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

func imageForUrl(urlString: String , indexPathArg:NSIndexPath!, completionHandler:(image: UIImage?, url: String,indexPathResponse:NSIndexPath?) -> ()) {

    let currentIndexPath: NSIndexPath! = indexPathArg.mutableCopy() as! NSIndexPath

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in

        let data: NSData? = self.cache.objectForKey(urlString) as? NSData
        //Check if image data for this URL already exists in Cache
        if let goodData = data {
            //data exists, no need to download it again. Just send it
            let image = UIImage(data: goodData)
            dispatch_async(dispatch_get_main_queue(), {() in
                completionHandler(image: image, url: urlString,indexPathResponse: currentIndexPath)
            })
            return
        }
        //Data does not exist, We have to download it
        let downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!,completionHandler: { (data: NSData?, response:NSURLResponse?, error: NSError?) -> Void in
            if (error != nil) {
                //Download failed
                completionHandler(image: nil, url: urlString, indexPathResponse: currentIndexPath)
                return
            }

            if data != nil {
                //Download successful,Lets save this downloaded data to our Cache and send it forward as UIImage
                let image = UIImage(data: data!)
                self.cache.setObject(data!, forKey: urlString)
                dispatch_async(dispatch_get_main_queue(), {() in
                    completionHandler(image: image, url: urlString, indexPathResponse: currentIndexPath)
                })
                return
            }

        })
        downloadTask.resume()
    })

}
}

然后您必须像这样修改您的 collectionview 委托(delegate):

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell :imagecell = collectionView.dequeueReusableCellWithReuseIdentifier("imagecell", forIndexPath: indexPath) as! imagecell
    if imagearray.count > 0 
    {
       let dic = imagearray .objectAtIndex(indexPath.row) as! NSDictionary

       let imgURL: NSString = dic!["image"] as! NSString//Get URL string
       ImageLoader.sharedLoader.imageForUrl(imgURL as String,indexPathArg: indexPath, completionHandler:{(image: UIImage?, url: String, indexPathResponse: NSIndexPath?) in


        let indexArr:NSArray = collectionView!.indexPathsForVisibleItems()

        if indexArr.containsObject(indexPathResponse!)
        {
            cell.imagev.image = image //Set image
        }

    })
    }


    return cell
}

现在它将异步加载您的图像,并且仅在必要时才下载它。巨大的成功! (引用波拉特的话)。我添加了评论,以便您可以理解我的代码和 Daniel 的代码中发生了什么:)

要解决您的崩溃问题,这不是您的原始问题的一部分,而是您创建的另一个问题,请返回部分中的项目计数以计算您的图像数组并在检索到数据后重新加载 Collection View :

func webimages()
{

let url = "http://radio.spainmedia.es/podcasts/"

    request(.GET, url, parameters: nil, encoding: .JSON).responseJSON { (response:Response<AnyObject, NSError>) -> Void in


           print(response.result.value)

            self.imagearray = (response.result.value) as! NSMutableArray
            print(self.imagearray)
            //Reload Collection view
            self.collectionView?.reloadData()

    }

}


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return imagearray.count
}

Imageloader 类的学分:Daniel Sattler

特别感谢:CouchDeveloper

关于ios - 如何从我通过 API 调用获得的 url 加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34542519/

相关文章:

swift - 如何为类别创建快速类?

ios - UIAlertController 在生成警报 View 时出错

ios - 如何在表格 View 中调整图像大小?

ios - 滚动 UIImageView 图像

ios - 如何截取屏幕截图并裁剪掉空白区域?

ios - 将 iphone 设备添加到 Codenameone 证书生成器时的 Apple Id 查询

ios - 在iOS中上传之前如何压缩视频数据

swift/Xcode : WebProcessProxy Invalid connection identifier (web process failed to launch)

iOS tableView 在单击、滚动或切换标签栏项目之前不会重新加载

ios - Swift - 在 Spotlight 搜索中获取圆形图像(即在缩略图中)