0

I'm displaying 2 images in a collectionview using 2 URL's like so...

var sampleURLArray: [NSURL] = []

sampleURLArray = [NSURL(string: "http://myApp.abc.com/products/123_45_6_image_123456")!,NSURL(string: "http://myApp.abc.com/products/789_45_6_image_654321")!]

And I'm iterating through the URL's and assigning the images to an array like so...

    for imageNumber in self.sampleURLArray {

        let imageurl1 = imageNumber
        let url = imageurl1

        let data = try? Data(contentsOf: url as URL)
        self.sampleImageView.image = UIImage(data: data!)
        self.arrayOfURLImages.append(self.sampleImageView.image!)
 }

The images are now properly shown. But I am not to display images in such a hard-coded fashion and I have to display the images from the url's I'm getting from my json response which I'm doing like so...

      if let projectData = result["Productdata"] as? [[String:Any]] {

     let productIds = projectData.flatMap({ $0["product_id"] as? String })
     let images = projectData.flatMap({ $0["product_images"] as? [[String: Any]] }).flatMap({ $0 })
     let imageIds = images.flatMap({ $0["image"] as? String })

    self.appDelegate.commonArrForCollectionViewImgs = imageIds //I'll get each URL from self.appDelegate.commonArrForCollectionViewImgs

         }
//CommonArrForCollectionViewImgs is set as  var commonArrForCollectionViewImgs = [String]()  
       for imageNumber in self.appDelegate.commonArrForCollectionViewImgs {

       let imageurl1 = imageNumber
       let url = URL(string: imageurl1)
       print(url)
       if let dataOfUrl = try? Data(contentsOf: url!) {
       let data = dataOfUrl
       self.sampleImageView.image = UIImage(data: data)
      }

       self.arrayOfURLImages.append(self.sampleImageView.image!)


     }

But when this is done, the images are not shown in the collectionview though I am able to parse all url's properly. Also, I'm doing the json parsing if I'm getting success in the API request. I'm not able to figure out what the issue is. Does this have to do anything with where the collectionview is set up...?

1 Answers1

0

As far as I can see you are using the Data(contentsOf: url!) initializer for fetching remote resources. This method is intended to be used for local resources only. Don't be mistaken by the URL part. URL can also point to the local resources.

According to the Apple documentation

Important

Don't use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.

Instead, for non-file URLs, consider using the dataTask(with:completionHandler:) method of the NSURLSession class. See URL Session Programming Guide for details.

However, if you really wish to use this method you can fetch your resources like this.

    DispatchQueue.global(qos: .background).async
    {
        for url in urls {
            let data = try? Data(contentsOf: url!)
            self.images.append(UIImage(data: data!)!)

            DispatchQueue.main.async {
                self.collectionView.reloadData()
            }
        }
    }
Kamil Szostakowski
  • 2,113
  • 12
  • 18
  • But apart from poor user experience does it cause images to not show up entirely on the collection view...? –  Sep 27 '17 at 12:10
  • No apart from that the image should be displayed properly. But using this method you won't be notified about any network conditions which may influence the image loading. If they don't appear, please check if you can display them in the browser. Don't you need to include any authentication headers to be able to access them? – Kamil Szostakowski Sep 27 '17 at 12:22
  • you mean the parameters that are to be passed while making the request..? –  Sep 27 '17 at 12:29
  • Yes. I don't know the specifics of your backend. If it requires authentication it may also require passing auth token when fetching resources. The easiest check is to try the URL from the browser. If the browser will load the image it's not the case. – Kamil Szostakowski Sep 27 '17 at 12:34
  • Yes...the image is shown when loaded in the browser...Also a couple of parameters related to images are 'limit' and 'page' which is the number of images to be shown and the total number of pages. But I don't think they have anything to do with the images not being shown... –  Sep 27 '17 at 12:52
  • I created a sample project with collection view and remote images and everything works. Could you please post the code where you configure the collection view? Maybe you have to call `collectionView.reloadData()` after all? – Kamil Szostakowski Sep 27 '17 at 13:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155426/discussion-between-kamil-szostakowski-and-user-bw). – Kamil Szostakowski Sep 27 '17 at 13:15