I want to download images from server and display in UICollectionView. First time when user connect with internet than all images will download in background and display from local directory when user is offline. I am using alamofire to download the images. Firstly i am checking existence of image, if it is not already dowloaded than i download it. The problem is that the album is not showing when it is already downloaded. I do not know how. Here is my code:
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
}
The issue seems with self.imageName. When you are downloading image, the imageName Would have changed in the for loop. Make sure to generate the image name each time from url. while downloading and saving and also while checking.
In fact you can change the scope of imageName variable from global to local.
Recommended is write function to get the image name to avoid redundancy.
EDIT
The guidedCellImages folder must exists, just by adding guidedCEllImages will not create the folder automatically. make sure to add slash (/) before the guidedCellImages
Please check how to create the folder inside document directory here
Hope it helps..!!!
Try this code
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)
}
Try this below procedure, this might helps you
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
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.