1

When i run this code it shows nothing in my collectionView. My code -

   class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

        @IBOutlet weak var collectionView: UICollectionView!
        var AllImage: [String] = []
          var boolValue = false

        override func viewDidLoad() {
            super.viewDidLoad()

            collectionView.delegate = self
            collectionView.dataSource = self

            downloadJson()
        }

        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            print("Found - \(AllImage.count)")
            return AllImage.count
        }

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell:CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
            cell.myImage.image = UIImage(named: AllImage[indexPath.row])
            return cell

        }

        //MARK: Image
        func downloadJson(){
            var access_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwMjc2LCJpc3MiOiJodHRwczovL2hvbWlpdGVzdC5jby56YS9hcGkvbG9naW4iLCJpYXQiOjE1NTIxOTYwMjIsImV4cCI6MTU1NDc4ODAyMiwibmJmIjoxNTUyMTk2MDIyLCJqdGkiOiJBeTY5R0JkZDA5dWdFTDBhIn0.czpQQsC08vuTB8iGdTeEjjQUmzl6I5Cs0VQ8WeA5VaY"
            let headers = ["Authorization": "Bearer "+access_token+"", "Content-Type": "application/json"]
            Alamofire.request("https://homiitest.co.za/api/gallery", method: .get,  parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
                if response.result.isSuccess{
                    print(response)

                    let swiftyJson = JSON(response.data!)

                    let productTemplate = swiftyJson["data"].array
                    print("hello there - \(productTemplate)")

                    for product in productTemplate! {

                        if let data = product["data"].bool {
                            continue
                        } else
                        {
                            print("I am in this block")
                            self.AllImage.append(product.stringValue)

                        }
                        self.collectionView!.reloadData()
                    }

                }

            }

        }
    }

Response - enter image description here

Nikunj Kumbhani
  • 3,758
  • 2
  • 26
  • 51
Rashed
  • 2,349
  • 11
  • 26

5 Answers5

1

UIImage(named: String) loads an image from the Asset Catalog. As AllImage contains urls of images, you'll need to download each image first before displaying it. I'd recommend using a library (Kingfisher is a great one and fairly easy to use). You'll need to replace this line of code

cell.myImage.image = UIImage(named: AllImage[indexPath.row])

with

let url = URL(string: AllImage[indexPath.row])
cell.myImage.kf.setImage(with: url)
  • I have to install the Kingfisher before i use your code. Right? – Rashed Mar 11 '19 at 07:21
  • @MdRashedPervez Cant need to use any third-party library for this simple thing use this one https://stackoverflow.com/a/51746517/10150796 by just add that function. – Nikunj Kumbhani Mar 11 '19 at 07:23
  • Yes you'll need to install it using Cocoapods or Carthage, whichever you use. – Fady A. Ackad Mar 11 '19 at 07:24
  • @NikunjKumbhani Well, Kingfisher has other benefits too, like caching and cancelling requests when reusing cells so no image is displayed in the wrong cell. I prefer to avoid a lot of boilerplate code, that's why I recommended it. Cheers. – Fady A. Ackad Mar 11 '19 at 07:29
  • @FadyA.Ackad Right, I know but my function also cashing the downloaded images and also display placeholder image until load the actual image. – Nikunj Kumbhani Mar 11 '19 at 07:31
  • @FadyA.Ackad i am getting this - Value of optional type 'UIImage?' must be unwrapped to refer to member 'kf' of wrapped base type 'UIImage' – Rashed Mar 11 '19 at 07:34
  • @NikunjKumbhani but it does not cancel the request when a cell is reused therefore this will cause a racing issue where two requests are loading for the same imageView which will cause one to override the other. Whichever takes longer – Fady A. Ackad Mar 11 '19 at 07:34
  • @MdRashedPervez Sorry there was an error in my code. I corrected it. Try it now – Fady A. Ackad Mar 11 '19 at 07:36
1

Just add this function

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!
                        }
                    }
                }
            }
        }
    }
}

Just Replace

cell.myImage.image = UIImage(named: AllImage[indexPath.row])

with

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

NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: cell.myImage, imgUrl: AllImage[indexPath.row]) { (image) in }

This one is your first image of an array.

enter image description here

Nikunj Kumbhani
  • 3,758
  • 2
  • 26
  • 51
  • bro..it gives me a blank screen just like before. – Rashed Mar 11 '19 at 07:30
  • @MdRashedPervez can you please share me anyone URL from your **AllImage** array? Because it's working code in my **swift 4** project. – Nikunj Kumbhani Mar 11 '19 at 07:32
  • 1
    @MdRashedPervez I update your first image in my answer which getting by this function it's working fine jo just check it or share your code after use this function. – Nikunj Kumbhani Mar 11 '19 at 07:43
  • I add your function in my existing code and replace the code in my cellForItemAt indexPath ..but brother i didn't get any output to see. – Rashed Mar 11 '19 at 07:48
  • @MdRashedPervez make sure IBOutlet of Imageview must be connected because you see the output is here it's working fine. – Nikunj Kumbhani Mar 11 '19 at 07:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189799/discussion-between-nikunj-kumbhani-and-md-rashed-pervez). – Nikunj Kumbhani Mar 11 '19 at 09:05
1

Please format your download code you are not saving URL string into array to load images properly. I have updated the code. Please refer below.

//MARK: Image
    func downloadJson(){
        let access_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjEwMjc2LCJpc3MiOiJodHRwczovL2hvbWlpdGVzdC5jby56YS9hcGkvbG9naW4iLCJpYXQiOjE1NTIxOTYwMjIsImV4cCI6MTU1NDc4ODAyMiwibmJmIjoxNTUyMTk2MDIyLCJqdGkiOiJBeTY5R0JkZDA5dWdFTDBhIn0.czpQQsC08vuTB8iGdTeEjjQUmzl6I5Cs0VQ8WeA5VaY"
        let headers = ["Authorization": "Bearer "+access_token+"", "Content-Type": "application/json"]
        Alamofire.request("https://homiitest.co.za/api/gallery", method: .get,  parameters: nil, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
            if response.result.isSuccess{
                //print(response)

                let swiftyJson = JSON(response.data!)

                let productTemplate = swiftyJson["data"].array
                //print("hello there - \(productTemplate)")

                for product in productTemplate! {
                    // print(product["image_medium"].stringValue)
                    self.AllImage.append(product.stringValue)
                    print("this is data - \(product.stringValue)")
                }
                self.collectionView!.reloadData()

            }

        }

    }
Vinodh
  • 5,262
  • 4
  • 38
  • 68
0

Try this if you do not want to install pod. let imageCache = NSCache()

extension UIImageView {

    func imageFromServerURL(_ URLString: String, placeHolder: UIImage?) {

        self.image = nil
        if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
            self.image = cachedImage
            return
        }

        self.image = placeHolder

        if let url = URL(string: URLString) {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
                if error != nil {
                    print("ERROR LOADING IMAGES FROM URL: \(String(describing: error))")
                    return
                }
                DispatchQueue.main.async {
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }
}

Use :

cell.myImage.imageFromServerURL(AllImage[indexPath.row], placeHolder:PLACEHOLDER_IMAGE)

let me know if you have any doubts.

0

You can still use Alamofire if you dont want to use another library like AlamofireImage,AFNetworking,SDWebImage, etc.

extension UIImageView {

func showImages(imageURL: String) {
    Alamofire.request(imageURL, method: .get)
        .validate()
        .responseData(completionHandler: { (responseData) in
            self.image = UIImage(data: responseData.data!)
        })
}}

You can use it like this :

cell.myImage.showImages(AllImage[indexPath.row])
Hendy Evan
  • 653
  • 7
  • 12