Upload Photo Button Swift Xcode Lets Make That App
About applications need to fetch data from a remote server and downloading images is a very common chore applications need to perform. In this series, I prove y'all how to download images using Swift. Nosotros accept a look at several solutions. I prove you the pros and cons of each solution and, most chiefly, which pitfalls to avoid.
Downloading an Image From a URL
This postal service focuses on the basics, that is, How does an application download an image from a URL in Swift? Allow'south start with a blank Xcode project. Select New > Project... from Xcode's File menu and choose the Single View App template from the iOS > Application department.
Name the project Images and set User Interface to Storyboard. Leave the checkboxes at the bottom unchecked. Tell Xcode where you would similar to salve the project and click the Create button.
Nosotros keep the awarding simple. Open ViewController.swift and create an outlet with name imageView
of blazon UIImageView!
, an implicitly unwrapped optional. The thought is elementary. The view controller downloads an image from a URL and displays it in its image view.
import UIKit course ViewController: UIViewController { // MARK: - Backdrop @IBOutlet var imageView: UIImageView! // MARK: - View Life Bike override func viewDidLoad() { super.viewDidLoad() } }
Open Primary.storyboard, click the Library button in the top correct, and add an image view to the View Controller scene. Pivot the image view to the edges of the view controller's view.
Select the view controller in the storyboard and open up the Connections Inspector on the right. Connect the imageView
outlet to the image view in the View Controller scene.
Before nosotros move on, we need to configure the image view. Select the image view, open the Attributes Inspector on the right, and fix Content Manner to Attribute Fit.
Downloading Image Data
With the user interface in place, nosotros tin can focus on downloading an image and displaying it in the image view. Open up ViewController.swift and navigate to the viewDidLoad()
method. When information technology'due south appropriate for an application to download remote resources, such as images, differs from application to awarding. Nosotros download an image in the view controller'southward viewDidLoad()
method, but this is usually not what you desire.
Nosotros showtime past creating a URL
object that points to the remote image. Your awarding normally obtains the URL of the remote image from an API of some sort. You should not hard code the URL of a remote resource in the project if you tin avoid it.
Notice that we forced unwrap the result of the initialization. This is an case and then we are not focused on safety.
// MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL let url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/above-the-clouds.jpg")! }
Strategy 1: Using the Data Struct to Download Images
I want to evidence you two strategies to download an image from a remote server. The commencement strategy is every bit simple as it gets. We initialize a Data
object by invoking the init(contentsOf:)
initializer. Considering the initializer is throwing, we use the try?
keyword and optional binding to safely access the result of the initialization.
// Marker: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL let url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/above-the-clouds.jpg")! // Fetch Prototype Information if let data = effort? Information(contentsOf: url) { // Create Image and Update Image View imageView.image = UIImage(data: data) } }
In the body of the if
statement, the view controller uses the Data
object to create a UIImage
instance. Information technology assigns the UIImage
case to the image
property of its prototype view. That's it. Build and run the application in the simulator to encounter the result.
This looks fine, but there is 1 important problem. The paradigm data is fetched synchronously and the operation blocks the principal thread. Wait. What? This simply means that the execution of the application is interrupted as long as the image data is being downloaded. This may non seem similar a big problem, but I can assure you that this is something you demand to avert at any price. If the device suffers from a slow network connection, so this subtle issue turns into a major problem. As long every bit the application is downloading the remote resource, the user isn't able to interact with the application. That'south a trouble. Right?
Strategy 2: Using the URLSession API to Download Images
Permit'due south have a look at the second strategy. We employ the URLSession API to fetch the epitome data. This is a bit more involved, only it isn't circuitous. We obtain a reference to the shared URLSession
instance through the shared
course method. Nosotros invoke the dataTask(with:completionHandler:)
method on the URLSession
case, passing in the URL
object as the outset argument and a closure equally the second statement. We store the result of dataTask(with:completionHandler:)
in a constant with name dataTask
.
// Marking: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL let url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/in a higher place-the-clouds.jpg")! // Create Data Task let dataTask = URLSession.shared.dataTask(with: url) { (data, _, _) in } }
The completion handler, a closure, is executed when the request to fetch the paradigm information completes, successfully or unsuccessfully. The closure accepts 3 arguments. We are interested in the first argument for now, the Information
object that holds the image data. In the closure, we safely unwrap the Information
object and use it to create a UIImage
case. We use the UIImage
instance to update the image
property of the view controller's image view.
The closure keeps a strong reference to self
, the view controller. That isn't what we desire, though. We utilize a capture list to weakly reference self
in the closure.
// MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL let url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/higher up-the-clouds.jpg")! // Create Data Task let dataTask = URLSession.shared.dataTask(with: url) { [weak self] (information, _, _) in if let data = data { // Create Image and Update Image View self?.imageView.epitome = UIImage(data: data) } } }
To start the data chore, we invoke resume()
on the URLSessionDataTask
instance.
// MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL allow url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/above-the-clouds.jpg")! // Create Data Job let dataTask = URLSession.shared.dataTask(with: url) { [weak self] (information, _, _) in if let data = data { // Create Image and Update Epitome View self?.imageView.image = UIImage(information: data) } } // Start Data Task dataTask.resume() }
There is i last trouble we need to resolve. The completion handler we pass to the dataTask(with:completionHandler:)
method is executed on a background thread. You probably know that the user interface should e'er be updated from the main thread. Fortunately, the solution is simple. We use Grand Central Acceleration to update the prototype view on the primary thread.
// MARK: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL permit url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/above-the-clouds.jpg")! // Create Information Task let dataTask = URLSession.shared.dataTask(with: url) { [weak self] (data, _, _) in if permit data = information { DispatchQueue.main.async { // Create Prototype and Update Prototype View self?.imageView.image = UIImage(data: data) } } } // Start Information Task dataTask.resume() }
Similar I said, the second strategy is more involved, but it is more robust and doesn't cake the main thread. Nosotros can ready the result we encountered using the first strategy by creating the Data
object on a background thread, using K Cardinal Dispatch. The solution looks something similar this.
// Marker: - View Life Cycle override func viewDidLoad() { super.viewDidLoad() // Create URL let url = URL(string: "https://cdn.cocoacasts.com/cc00ceb0c6bff0d536f25454d50223875d5c79f1/above-the-clouds.jpg")! DispatchQueue.global().async { // Fetch Prototype Data if let data = try? Data(contentsOf: url) { DispatchQueue.primary.async { // Create Image and Update Image View self.imageView.epitome = UIImage(information: data) } } } }
Notice that we still update the image view from the main thread using Grand Cardinal Acceleration. It's a small-scale just important particular.
stonemanbrint1954.blogspot.com
Source: https://cocoacasts.com/fm-3-download-an-image-from-a-url-in-swift
0 Response to "Upload Photo Button Swift Xcode Lets Make That App"
Post a Comment