【问题标题】:Download and Show Array of images in UICollectionView Swift3在 UICollectionView Swift3 中下载并显示图像数组
【发布时间】:2018-07-11 18:54:29
【问题描述】:

我想从服务器下载图像并在 UICollectionView 中显示。当用户第一次连接互联网时,所有图像将在后台下载并在用户离线时从本地目录显示。我正在使用 alamofire 下载图像。首先,我正在检查图像是否存在,如果它尚未下载,则我下载它。问题是该专辑在已下载时未显示。我不知道怎么。这是我的代码:

   import UIKit
   import Alamofire

   var myurl : URL!
   var imageName : String!
   var bool = false

   let docsurl = try! FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)

    override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
             if (background_imageurl.count > 0) {
                 if Reachability.isConnectedToNetwork() == true{
                    downloadAllImages(urlArray : background_imageurl)
                    }
                }
            }
     func downloadAllImages(urlArray:[String])->Void{
                 for i in 0 ..< urlArray.count  {
                       let fullName    =  urlArray[i]
                       let fullNameArr = (fullName as AnyObject).components(separatedBy: "//")
                       let imgname = fullNameArr[1]

                       let tempimgname    = imgname
                       let tempimgname2 = tempimgname.components(separatedBy: "/")

                        imageName = tempimgname2[4]

                        myurl  = docsurl.appendingPathComponent("\("guidedCellImages")/\(self.imageName!)")

                        print("\n myurl", myurl)

                        if FileManager.default.fileExists(atPath: myurl.path, isDirectory: &bool),bool.boolValue  {
                        print("\n fileExists", myurl.path)
                         }else{
                         downloadFile(url: urlArray[i] as! String)
                              }
                        }
                }

      func downloadFile(url: String)->Void{

             let destination: (URL, HTTPURLResponse) -> (URL, DownloadRequest.DownloadOptions) = {
        (temporaryURL, response) in 
         let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        let filePath = directoryURL?.appendingPathComponent("\("guidedCellImages")/\(self.imageName!)")
        return (filePath!, [.removePreviousFile, .createIntermediateDirectories])
    }

      let utilityQueue = DispatchQueue.global(qos: .utility)
      print("url", url)

        Alamofire.download(
        url,
        method: .get,
        encoding: JSONEncoding.default,
        to: destination)

        .downloadProgress(queue: utilityQueue) { progress in       
        }
        .response(completionHandler: { (DefaultDownloadResponse) in

        if (self.urlArray.count > 0){
            self.urlArray.removeFirst()
            print("self.urlArray", self.urlArray.count)
        }

        if DefaultDownloadResponse.response?.statusCode == 200 { 
                print(DefaultDownloadResponse.destinationURL!)
            }
        })
     }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell : CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CollectionViewCell

    myurl  = docsurl.appendingPathComponent("\("guidedCellImages")")

    if FileManager.default.fileExists(atPath: myurl.path, isDirectory: &bool),bool.boolValue  {

        let directoryContents = try! fileManager.contentsOfDirectory(at: myurl, includingPropertiesForKeys: nil)
        print("\ndirectoryContents", directoryContents)
        for imageURL in directoryContents where imageURL.pathExtension == "png" {
            if let image = UIImage(contentsOfFile: imageURL.path) {

                cell.tab1GuidedimageView.image = image
            } else {
                fatalError("Can't create image from file \(imageURL)")
            }
        }
    }else{
    if (background_imageurl.count > 0 ){
    cell.tab1imageView.sd_setImage(with: URL(string: background_imageurl[indexPath.row]), placeholderImage: UIImage(named: "background"),options: .refreshCached)
    }

}

    return cell
}

【问题讨论】:

  • 您是否检查了名称是否与 : print("\n myurl", myurl) 相同?它在打印什么?
  • 是的,URL 的名称打印正确。
  • 请查看答案
  • 您是否从服务器获取图像 URL?
  • 是的@JayachandraA

标签: ios swift3 alamofire nsfilemanager


【解决方案1】:

问题似乎与 self.imageName 有关。当您下载图像时,图像名称会在 for 循环中发生变化。确保每次从 url 生成图像名称。在下载和保存以及检查时。

实际上你可以将 imageName 变量的范围从全局更改为本地。

推荐使用 write 函数来获取图像名称以避免冗余。

编辑

guidedCellImages 文件夹必须存在,仅添加guidedCEllImages 不会自动创建该文件夹。确保在guidedCellImages 之前添加斜杠(/)

请查看如何在文档目录here中创建文件夹

希望对你有帮助..!!!

【讨论】:

  • 当响应来到此语句 print(DefaultDownloadResponse.destinationURL!) 时,当我在数组中有 18 个项目时,它打印了 36 次,并且当用户在 cellForItemAt IndexPath 中没有打印任何语句时离线。
  • 你能检查一下是否在文档目录中创建了以guidedCellImages命名的文件夹吗?
  • 否则您需要在保存图像之前创建一个
  • Yes 文件夹是用这个根路径创建的:file:///var/mobile/Containers/Data/Application/C1EE516C-2397-4080-BC0F-4B5146005C1B/Documents/guidedCellImages
  • 好的,但这是你的打印路径还是你检查了finder中的目录?检查模拟器,这样你就可以看到创建的实际目录
【解决方案2】:

试试这个代码

func downloadFile(url: String)-> Void {

    let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
    let filePath = directoryURL?.appendingPathComponent("\("guidedCellImages")/\(self.imageName!)")


    let data    =   NSData(contentsOf: URL(string: url)!)
    data?.write(toFile: filePath, atomically: true)

}

【讨论】:

  • 我有一个字符串数组,这个方法能帮我异步下载吗?
  • 您正在异步下载此图像,但在 downloadFile 方法中您错过了将下载的图像数据写入磁盘内的文件。正因为如此,您无法看到磁盘内的图像被保存。
【解决方案3】:

试试下面这个过程,这可能对你有帮助

struct Animal{
    var name: String
    var url: String
    var image: UIImage?
}

extension Animal{
    init(info: [String: String]) {
        self.name = info["name"]!
        self.url = info["url"]!
    }
}

class CollectionViewCell{
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var label: UILabel!
}

class ViewController: UIViewController{
    var animals = [Animal]()

    override func viewDidLoad(){
        super.viewDidLoad()
    }

    func getAnimals(){
        // hit server api to get the images
        // assuming that the following json is coming from server
        let jsonResponse = [["name":"Dog","url":"https://animals.com/images/image/dog.jpeg"],
                            ["name":"Lion","url":"https://animals.com/images/image/lion.jpeg"],
                            ["name":"Tiger","url":"https://animals.com/images/image/tiger.jpeg"],
                            ["name":"Horse","url":"https://animals.com/images/image/horse.jpeg"],
                            ["name":"Elephant","url":"https://animals.com/images/image/elephant.jpeg"]]
        for animal in jsonResponse {
            let lAnimal = Animal(info: animal)

            // get locally saved image initially from collectionview cell, if it is existed then add it to your response model
            let directoryURL = getDocumentsDirectory()
            let imageURL = URL(string: lAnimal.url)
            let imagePath = directoryURL.appendingPathComponent("animals/\(imageURL.lastPathComponent)")
            if fileManager.fileExistsAtPath(imagePAth){
                // pass locallay saved image path
                lAnimal.image = UIImage(contentsOfFile: imagePAth)
            }else{
                print("image needs to be downloaded")
            }
        }
    }

    func getDocumentsDirectory() -> URL {
        let directoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        return directoryURL!
    }
}

extension ViewController: UICollectionViewDataSource{

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

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell : CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuseIdentifier", for: indexPath) as! CollectionViewCell
        let animal = self.animals[indexPath.row]
        cell.label.text = animal.name
        if let animalImage = animal.image{
            //if animal image existis from local them simply display it
            cell.imageView.image = animalImage
        }else{
            //download image from server using simple url task or by using alamofire
            let imageURL = URL(string: animal.url)!
            let task = URLSession.shared.dataTask(with: imageURL, completionHandler: { (data, response, error) in
                if let lData = data {
                    let image = UIImage(data: lData)
                    cell.imageView.image = image
                    let filename = getDocumentsDirectory().appendingPathComponent("animals/\(imageURL.lastPathComponent)")
                    try? lData.write(to: filename)

                    //update local data model object
                    animal.image = image
                }
                if let lError = error{
                    /** Handle session error ..................... **/
                }
            })
        }
        return cell
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 2017-06-17
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多