URLSession Networking in Swift
- Tram Ho
Through this article, you will learn:
- When to use URLSession
- What is URLSession
- Fetch data uses URLSession through a simple example
When to use URLSession
1 2 | Rất đơn giản<span class="token punctuation">,</span> bạn muốn <span class="token string">"chiếc"</span> app của bạn tương tác với Internet<span class="token punctuation">,</span> nghĩa là bạn đang muốn tạo HTTP request<span class="token punctuation">,</span> URLSession là <span class="token number">1</span> lựa chọn |
URLSession is a framework that Apple itself developed and implemented in iOS. A lot of developers use third-party libraries like Alamofire But you will soon realize that, you do not need to depend too much on a library to make a simple HTTP request, URLSession will have all the things you want.
What is URLSession
URLSession is a class that provides API to interact with protocols like HTTP, HTTPS
- URLSession creates a session, it simply looks like an open tab in your browser, it contains many HTTP request methods that users can interact with.
- URLsession is used to create URLSessionTask object, which you can retrieve data from Internet, download or upload files to webservices. There are 3 types of tasks:
- URLSessionDataTask: Use this action for HTTP GET requests to retrieve data from the server into memory.
- URLSessionUploadTask: Use this action to upload the file from disk to a web service, usually through the HTTP POST or PUT method.
- URLSessionDownloadTask: Use this action to download files from remote services to the temporary file location. You can also pause, resume, and cancel tasks. URLSessionDownloadTask has additional pause capabilities for resuming in the future.
- You can reconfigure a session with URLSesssionConfiguration for each purpose
- .default: Create a default configuration object that uses object cache, credentials, and cache.
- .ephemeral: Similar to the default configuration, except all session-related data is stored in memory. Think of this as a “private” session.
- .background:Allows the session to perform background upload or download tasks. The transition continues even if the application is suspended or terminated by the system. URLSessionConfiguration also allows you to configure session properties such as timeout values, buffer policies, and additional HTTP headers. Refer to the documentation for the complete list of configuration options
Fetch data uses URLSession
In practice, the steps to get data from the webservice:
- Initialize the HTTP Request with URLSession
- Use URLSessionDataTask send request to retrieve data
- Print the types of data to be returned
- Check there is the correct data we need and Convert the data to JSON
Initialize HTTP Request with URLSession
We need a session and a URL like this
1 2 3 | <span class="token keyword">let</span> session <span class="token operator">=</span> <span class="token builtin">URLSession</span><span class="token punctuation">.</span>shared <span class="token comment">//1</span> <span class="token keyword">let</span> url <span class="token operator">=</span> <span class="token function">URL</span><span class="token punctuation">(</span>string<span class="token punctuation">:</span> <span class="token string">"..."</span><span class="token punctuation">)</span><span class="token operator">!</span> <span class="token comment">//2</span> |
- Creates a reference to the URLSession Class with default configuration
- Create url with URL type, parameter is string
The URL used in this example is uers.json, Copy this path and paste it into the string
Use URLSessionDataTask to send request to get data
Create a dataTask with the function dataTask(with:completionHandler:)
:
1 2 3 4 5 | <span class="token keyword">let</span> task <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">dataTask</span><span class="token punctuation">(</span><span class="token keyword">with</span><span class="token operator">:</span> url<span class="token punctuation">,</span> completionHandler<span class="token operator">:</span> <span class="token punctuation">{</span> data<span class="token punctuation">,</span> response<span class="token punctuation">,</span> error <span class="token keyword">in</span> <span class="token comment">// Do something...</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
dataTask(with:completionHandler:)
has 2 parameters passed: url initialized above and 1 completionHandle
1 2 | completionHandle là gì?<span class="token punctuation">,</span> bạn có thể hiểu đơn giản nó là <span class="token number">1</span> clousure mà bắt lại <span class="token number">3</span> tham số mà bạn muốn dùng lại: <span class="token keyword">data</span><span class="token punctuation">,</span> response và error<span class="token punctuation">.</span> |
- data: type is Data, is the data you want to get from webservice,
- response: The type is URLResponse, which gives us more information about the response of the request including length, encoding, HTTP status code, …
- error: will contain error information that would occur if the request was not successful. If the request is successful, error = nil
At this point, a request has not been completed, it has just been initiated, to start sending the request add:
1 2 | task<span class="token punctuation">.</span>resume<span class="token punctuation">(</span><span class="token punctuation">)</span> |
Print the types of data to be returned
See, please print the data types that are captured in completionHandle
and see what it is
1 2 3 4 5 6 | <span class="token keyword">let</span> task <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">dataTask</span><span class="token punctuation">(</span>with<span class="token punctuation">:</span> url<span class="token punctuation">)</span> <span class="token punctuation">{</span> data<span class="token punctuation">,</span> response<span class="token punctuation">,</span> error <span class="token keyword">in</span> <span class="token function">print</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
What do we have ?:
- data:
Optional(321 bytes)
, because the data is of type Data - response: have a style NSHTTPURLResponse is the subclass of URLResponse. Include
Status Code : 200
(I’ll talk more below) and HTTP headers (you can refer here) - error:
nil
. Luckily, there was no fault
Check for the correct data we need
When making an HTTP request, you need to authenticate at least the following:
- Will there be any errors? => check error
- The HTTP response code was returned as expected => check response
- Is the data returned in the correct format? => check data hay convert data sang JSON
Check error or not?
1 2 3 4 5 6 | <span class="token keyword">if</span> <span class="token builtin">error</span> <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token comment">// OH NO! An error occurred... </span> self<span class="token punctuation">.</span><span class="token function">handleClientError</span><span class="token punctuation">(</span><span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> |
If there is an error then call a function to resolve it and exit. Or you can refer to the treatment: throw an error
Check response have OK ?
1 2 3 4 5 6 | <span class="token keyword">guard</span> <span class="token keyword">let</span> httpResponse <span class="token operator">=</span> response <span class="token keyword">as</span><span class="token operator">?</span> <span class="token builtin">HTTPURLResponse</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token number">299</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>httpResponse<span class="token punctuation">.</span>statusCode<span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">handleServerError</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> |
- Here we consider whether response is the correct type of HTTP Response and the Status code is in the range 200 – 299 or not. If not, it will exit
- The status code is the status of the request, eg {404, 400, 401, etc ..} is an error, also in the {200 … 299} of your request was successful.
Check data, convert to JSON
1 2 3 4 | <span class="token keyword">if</span> <span class="token keyword">let</span> json <span class="token operator">=</span> <span class="token keyword">try</span><span class="token operator">?</span> JSONSerialization<span class="token punctuation">.</span><span class="token function">jsonObject</span><span class="token punctuation">(</span><span class="token parameter"><span class="token keyword">with</span><span class="token operator">:</span> data<span class="token operator">!</span><span class="token punctuation">,</span> options<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span>json<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Use optional binding to cast the data type to a JSON string using the function jsonObject(with:options:)
of the class JSONSerialization
. By reading each character in the data and converting it to a JSON string, it’s like reading a book and the story will come to mind.
Another way that apple recommends using:
1 2 3 4 5 6 7 | <span class="token keyword">do</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> json <span class="token operator">=</span> <span class="token keyword">try</span> <span class="token builtin">JSONSerialization</span><span class="token punctuation">.</span><span class="token function">jsonObject</span><span class="token punctuation">(</span>with<span class="token punctuation">:</span> data<span class="token operator">!</span><span class="token punctuation">,</span> options<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span>json<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"JSON error: <span class="token interpolation"><span class="token delimiter variable">\(</span>error<span class="token punctuation">.</span>localizedDescription<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
In the above code, if in try
If the error is caught, it will be printed in catch
Oke Let’s see what the json output is, if it is the same uers.json do you expect:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token punctuation">(</span> <span class="token punctuation">{</span> age <span class="token operator">=</span> <span class="token number">5000</span><span class="token punctuation">;</span> <span class="token string">"first_name"</span> <span class="token operator">=</span> <span class="token class-name">Ford</span><span class="token punctuation">;</span> <span class="token string">"last_name"</span> <span class="token operator">=</span> <span class="token class-name">Prefect</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> age <span class="token operator">=</span> <span class="token number">999</span><span class="token punctuation">;</span> <span class="token string">"first_name"</span> <span class="token operator">=</span> <span class="token class-name">Zaphod</span><span class="token punctuation">;</span> <span class="token string">"last_name"</span> <span class="token operator">=</span> <span class="token class-name">Beeblebrox</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> age <span class="token operator">=</span> <span class="token number">42</span><span class="token punctuation">;</span> <span class="token string">"first_name"</span> <span class="token operator">=</span> <span class="token class-name">Arthur</span><span class="token punctuation">;</span> <span class="token string">"last_name"</span> <span class="token operator">=</span> <span class="token class-name">Dent</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> age <span class="token operator">=</span> <span class="token number">1234</span><span class="token punctuation">;</span> <span class="token string">"first_name"</span> <span class="token operator">=</span> <span class="token class-name">Trillian</span><span class="token punctuation">;</span> <span class="token string">"last_name"</span> <span class="token operator">=</span> <span class="token class-name">Astra</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
Summary
Awesome ! Here is the entire code that we learned all day, through which we know
- If you want at HTTP Request, use URLSession
- URLSession Apple’s built-in iOS framework provides APIs for interacting with HTTP and HTTS request methods
- How to create 1 URLSession
- How to check error, response, data
- How to convert to JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <span class="token keyword">let</span> session <span class="token operator">=</span> <span class="token builtin">URLSession</span><span class="token punctuation">.</span>shared <span class="token keyword">let</span> url <span class="token operator">=</span> <span class="token function">URL</span><span class="token punctuation">(</span>string<span class="token punctuation">:</span> <span class="token string">"..."</span><span class="token punctuation">)</span><span class="token operator">!</span> <span class="token keyword">let</span> task <span class="token operator">=</span> session<span class="token punctuation">.</span><span class="token function">dataTask</span><span class="token punctuation">(</span>with<span class="token punctuation">:</span> url<span class="token punctuation">)</span> <span class="token punctuation">{</span> data<span class="token punctuation">,</span> response<span class="token punctuation">,</span> error <span class="token keyword">in</span> <span class="token keyword">if</span> error <span class="token operator">!=</span> <span class="token constant">nil</span> <span class="token operator">||</span> data <span class="token operator">==</span> <span class="token constant">nil</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Client error!"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> response <span class="token operator">=</span> response <span class="token keyword">as</span><span class="token operator">?</span> <span class="token builtin">HTTPURLResponse</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token number">299</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span>statusCode<span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Server error!"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> mime <span class="token operator">=</span> response<span class="token punctuation">.</span>mimeType<span class="token punctuation">,</span> mime <span class="token operator">==</span> <span class="token string">"application/json"</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"Wrong MIME type!"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">do</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> json <span class="token operator">=</span> <span class="token keyword">try</span> <span class="token builtin">JSONSerialization</span><span class="token punctuation">.</span><span class="token function">jsonObject</span><span class="token punctuation">(</span>with<span class="token punctuation">:</span> data<span class="token operator">!</span><span class="token punctuation">,</span> options<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span>json<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"JSON error: <span class="token interpolation"><span class="token delimiter variable">\(</span>error<span class="token punctuation">.</span>localizedDescription<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> task<span class="token punctuation">.</span><span class="token function">resume</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
References:
https://learnappmaking.com/urlsession-swift-networking-how-to/
https://www.raywenderlich.com/567-urlsession-tutorial-getting-started
https://learnappmaking.com/swift-optionals-how-to/#optional-binding