In this tutorial, you will learn how to load a list of images from a remote server URL in Swift. Also, you will learn about UICollectionView, background thread, and more.
By the end of this tutorial, you will have a working Swift code example that you can use in your mobile application.
Step 1: Create UICollectionView Programmatically
To create a UICollectionView
programmatically, you’ll need to define its layout and properties. This involves setting up a UICollectionViewFlowLayout
and assigning it to the collection view. You’ll also register a cell class or nib to use for the collection view’s cells.
If you are new to UICollectionView check this detailed guide about creating UICollectionView in Swift Programmatically.
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) layout.itemSize = CGSize(width: 60, height: 60) myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) myCollectionView!.dataSource = self myCollectionView!.delegate = self myCollectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell") myCollectionView!.backgroundColor = UIColor.white self.view.addSubview(myCollectionView!) loadListOfImages() }
Step 2: Implement UICollectionView Delegate Method
To handle taps on the collection view items, you need to implement the collectionView(_:didSelectItemAt:)
delegate method. This method is called whenever a user taps on an item in the collection view.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("User tapped on item \(indexPath.row)") let imageDictionary = self.images[indexPath.row] as! NSDictionary let imageUrlString = imageDictionary.object(forKey: "url") as! String print("Image url = \(imageUrlString)") }
Step 3: Load the list of images from a remote server
To load a list of images from a remote server, you’ll need to make an HTTP GET request. This is done using URLSession.shared.dataTask(with: request)
.
func loadListOfImages() { let scriptUrl = "https://jsonplaceholder.typicode.com/photos" let myUrl = URL(string: scriptUrl); var request = URLRequest(url:myUrl!) request.httpMethod = "GET" let task = URLSession.shared.dataTask(with: request) { data, response, error in if error != nil { print("error=\(String(describing: error))") return } do { if let convertedJsonIntoArray = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray { self.images = convertedJsonIntoArray as [AnyObject] DispatchQueue.main.async { self.myCollectionView!.reloadData() } } } catch let error as NSError { print(error.localizedDescription) } } task.resume() }
When you get a response back from the server it returns JSON. You need to convert this JSON to NSDictionary to show the image to your UI. Check this details guide on how to convert JSON string to NSDictionary in Swift.
Step 4: Create UIImageView
Inside the collectionView(_:cellForItemAt:)
method, you create an UIImageView
to display the image. This is done by creating a new UIImageView
instance, setting its frame to match the cell’s size, and then adding it to the cell.
let imageView = UIImageView(frame: CGRect(x:0, y:0, width:myCell.frame.size.width, height:myCell.frame.size.height))
Step 5: Create UIImageData and Load Image from a Remote URL
To load an image from a remote URL, you first convert the URL to Data
using NSData(contentsOf: imageUrl as URL)
. Then, you create a UIImage
from this data.
DispatchQueue.global(qos: .userInitiated).async { let imageData:NSData = NSData(contentsOf: imageUrl as URL)! DispatchQueue.main.async { let image = UIImage(data: imageData as Data) imageView.image = image imageView.contentMode = UIView.ContentMode.scaleAspectFit myCell.addSubview(imageView) } }
Notice the use of DispatchQueue.global
. It helps to load image data in a background thread.
Loading images in a background thread ensures that the main application remains responsive. This is achieved by dispatching the image loading task to a global queue with a quality of service class and then updating the UI on the main queue.
DispatchQueue.global(qos: .userInitiated).async { // Load image data DispatchQueue.main.async { // Update UI } }
To learn more about background threads check this tutorial on Time Consuming Task in Background Thread in Swift
Step 7: Add UIImageView as a Subview to UICollectionViewCell
Finally, you add the UIImageView
as a subview to the UICollectionViewCell
. This is done after the image has been loaded and the UI is updated on the main queue.
myCell.addSubview(imageView)
Complete Code Example
Here’s how all the steps come together in a complete example.
import UIKit class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { var images = [AnyObject]() var myCollectionView:UICollectionView? override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10) layout.itemSize = CGSize(width: 60, height: 60) myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) myCollectionView!.dataSource = self myCollectionView!.delegate = self myCollectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell") myCollectionView!.backgroundColor = UIColor.white self.view.addSubview(myCollectionView!) loadListOfImages() } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.images.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath) myCell.backgroundColor = UIColor.black let imageDictionary = self.images[indexPath.row] as! NSDictionary let imageUrlString = imageDictionary.object(forKey: "url") as! String let imageUrl:NSURL = NSURL(string: imageUrlString)! DispatchQueue.global(qos: .userInitiated).async { let imageData:NSData = NSData(contentsOf: imageUrl as URL)! DispatchQueue.main.async { let imageView = UIImageView(frame: CGRect(x:0, y:0, width:myCell.frame.size.width, height:myCell.frame.size.height)) let image = UIImage(data: imageData as Data) imageView.image = image imageView.contentMode = UIView.ContentMode.scaleAspectFit myCell.addSubview(imageView) } } return myCell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("User tapped on item \(indexPath.row)") let imageDictionary = self.images[indexPath.row] as! NSDictionary let imageUrlString = imageDictionary.object(forKey: "url") as! String print("Image url = \(imageUrlString)") } func loadListOfImages() { // Send HTTP GET Request // Define server side script URL let scriptUrl = "https://jsonplaceholder.typicode.com/photos" // Create NSURL Ibject let myUrl = URL(string: scriptUrl); // Creaste URL Request var request = URLRequest(url:myUrl!) // Set request HTTP method to GET. It could be POST as well request.httpMethod = "GET" // Excute HTTP Request let task = URLSession.shared.dataTask(with: request) { data, response, error in // Check for error if error != nil { print("error=\(String(describing: error))") return } // Convert server json response to NSDictionary do { if let convertedJsonIntoArray = try JSONSerialization.jsonObject(with: data!, options: []) as? NSArray { self.images = convertedJsonIntoArray as [AnyObject] DispatchQueue.main.async { self.myCollectionView!.reloadData() } } } catch let error as NSError { print(error.localizedDescription) } } task.resume() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }
Conclusion
I hope this tutorial was helpful for you. There are a lot more Swift code examples on this website if you check the Swift Code Examples page.
Additionally, you might also want to check a list of recent Swift tutorials where you will also find a list of useful resources for iOS mobile app developers.