<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Marcin Jackowski on Medium]]></title>
        <description><![CDATA[Stories by Marcin Jackowski on Medium]]></description>
        <link>https://medium.com/@marcinjackowski?source=rss-6c77af54b675------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*RjtYu-ehBJ4siTL9VmEKQA@2x.jpeg</url>
            <title>Stories by Marcin Jackowski on Medium</title>
            <link>https://medium.com/@marcinjackowski?source=rss-6c77af54b675------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 13 Jul 2026 10:33:34 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@marcinjackowski/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Unit test Network Layer]]></title>
            <link>https://medium.com/thecocoapps/unit-test-network-layer-de4280b2b0c0?source=rss-6c77af54b675------2</link>
            <guid isPermaLink="false">https://medium.com/p/de4280b2b0c0</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[apple]]></category>
            <dc:creator><![CDATA[Marcin Jackowski]]></dc:creator>
            <pubDate>Wed, 21 Nov 2018 22:52:29 GMT</pubDate>
            <atom:updated>2018-11-22T21:47:35.774Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5TRuG7tG0KrZJXKoFtHlSg.jpeg" /></figure><p>To be honest.. writing unit tests in iOS is a myth. Usually iOS developers work for small startups, which source money from investors. It is important for those investors to create a product as soon as possible. Manuall tests or application stability? Who cares… It is our obligation as a professional developers we need to change this approach and teach our clients that development process consists of two inseparable elements -code &amp; tests. If you want to learn more about this approach please check the book “The Software Craftsman: Professionalism, Pragmatism, Pride” (Robert C. Martin Series).</p><p>In this blogpost you will learn how to write unit tests of your network layer. After finishing you will see how simple it is. 👊</p><p>Before you start please fetch the latest changes from my repo because this tutorial is based on my previous post about Network Layer.</p><p><a href="https://github.com/marcinjackowski/NetworkLayer">marcinjackowski/NetworkLayer</a></p><h3>Quick and Nimble</h3><p>You may wonder why did I choose Quick and Nimble instead of XCTest framework 🤔</p><p>The answer is simple - combination of those two libraries is simply, easy to use and you can define the expected behaviour in a more readable way. Quick is a testing framework while Nimble is a matching framework. If it’s your first time with both frameworks, check GitHub documentation where you can find many examples of use.</p><ul><li>Quick-<a href="https://github.com/Quick/Quick/blob/master/Documentation/en-us/README.md">https://github.com/Quick/Quick/blob/master/Documentation/en-us/README.md</a></li><li>Nimble-<a href="https://github.com/Quick/Nimble">https://github.com/Quick/Nimble</a></li></ul><p>If you don’t understand these frameworks and don’t how to use them.. Don’t worry, just leave a comment and I will write a special blogpost about Quick and Nimble usage from the scratch 🍻</p><p>Last thing. In Quick framework there are four functions that describe tests: describe, context, it and fit. In my opinion these four don’t explain well when should they be used. To create tests that are more familiar and useful with general test representing style, create extension for Quick to transform this functions to Given, When, Then style. Check out the new syntax below:</p><ul><li>describe == given</li><li>context == when</li><li>it == then</li><li>fit == onlyThen</li></ul><p>Please create a new file QuickCustomAliases and copy those lines:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f3389c2e9e8f2e8b38840f57a2eacce6/href">https://medium.com/media/f3389c2e9e8f2e8b38840f57a2eacce6/href</a></iframe><p>As you can see, new functions better illustrate their usage and show the way how to construct tests.</p><h3>ServiceMock</h3><p>ProviderProtocol has one function request which takes two parameters: type and service. If your provider is parsing response properly, at first you have to create service mock and then example model with a simple structure to test.</p><p>Create new file ServiceMock and copy following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9e286286823f12275d7fecb6f6d7637c/href">https://medium.com/media/9e286286823f12275d7fecb6f6d7637c/href</a></iframe><ol><li>This service has four cases to test the most common things:<br> 1. <strong>jsonResponseWith200 -</strong>send plain request with json encoding. Expectations: status code 200.<br> 2. <strong>jsonResponseWithURLParametersWith200</strong>- send request with parameters with json encoding. Expectations: status code 200.<br> 3. <strong>errorWith500- </strong>Expectations: error with status code 500.</li><li>Base url cannot be empty because string url must be valid. If it is empty — the app will crash.</li><li>It is only a mock so you can write path you want.</li></ol><h3>ServiceModel</h3><p>One of the ServiceMock cases return json data in response. It would be great to write tests of module responsibles for encoding json data. To do that, it’s necessary to create mock model which conforms to Codable and Equatable. Create new file ModelMock:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/414500859cfbd3a8c786da504ae805e3/href">https://medium.com/media/414500859cfbd3a8c786da504ae805e3/href</a></iframe><h3>URLSessionDataTaskProtocol</h3><p>Before you start writing tests you have to modify current implementation of NetworkLayer just a bit. In version from previous blogpost, request function of URLSessionProtocol returns URLSessionDataTask 🤔 And that is a problem. In our test case you want to simulate resume task and return mock instead of <em>real</em> object. To do that create URLSessionDataTaskProtocol file and copy following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/31a71ff235714f4c92a4751098557897/href">https://medium.com/media/31a71ff235714f4c92a4751098557897/href</a></iframe><p>As you can see this protocol contains only one function resume. In this particular case it’s enough, but in case when you want to cancel or pause task it’s easy to extend the protocol with new variants. Moreover URLSessionDataTaskProtocol must be an extension of URLSessionDataTask.</p><p>Next you need to change return value of request function from URLSessionProtocol to URLSessionDataTaskProtocol.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b672e8a8b5d3b998c67b1d5f47514dd6/href">https://medium.com/media/b672e8a8b5d3b998c67b1d5f47514dd6/href</a></iframe><p>At the end you need to create mock which conforms to URLSessionDataTaskProtocol. You may wonder why? I will explain in in a later paragraph.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cc4943df7095f0d9b112435198ce1f36/href">https://medium.com/media/cc4943df7095f0d9b112435198ce1f36/href</a></iframe><h3>URLSessionProviderSpec</h3><p>If you have already created ServiceMock and ServiceModel now it’s time to start testing! URLSessionProvider is the most important file of network layer. To write first test please create the file URLSessionProvider with suffix Spec. Every file which conforms to QuickSpec must contain this suffix.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8290c607ca83a80b802233be636e22d4/href">https://medium.com/media/8290c607ca83a80b802233be636e22d4/href</a></iframe><h3>URLSessionProvider tests</h3><p>If you look at the function request of URLSessionProvider you can see that in the second line of this function, session is calling dataTask to send request. So let’s create our first test:</p><p>💏 When: Request is called, 👶 Then: Session should call dataTask.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b58f0a02bc5cc6b2cf5fa370200d140e/href">https://medium.com/media/b58f0a02bc5cc6b2cf5fa370200d140e/href</a></iframe><p>You may wonder how do we know if session has called function dataTask? SessionProtocol doesn’t have any properties called dataTask, only function dataTask 🤔 That’s why we love dependency inversion which is helpful in testing objects. Let’s create a new file URLSessionMock which conforms to URLSessionProtocol.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18cb2795c78663a6f84121ae79007ae7/href">https://medium.com/media/18cb2795c78663a6f84121ae79007ae7/href</a></iframe><p>As you can see you have added new property isDataTaskCalled with initial value false. If session call function dataTask you should change this property to true which means that this function was called. Furthermore to test URLSession you can’t return “real” URLSessionProtocol’s object so in init you should pass mock object and return this object in dataTask function. It’s time to complete first test and write first assertion.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b2f43dc041f5669a34fc8b1d8ef6a645/href">https://medium.com/media/b2f43dc041f5669a34fc8b1d8ef6a645/href</a></iframe><p>CMD + U ⏲️ TADA! You wrote your first test!</p><h3>Next test</h3><p>In the same scope, it would be a good idea to write another test to check if url was set properly.</p><p>💏 When: Request is called, 👶 Then: Request should set proper url.</p><p>This test also checks our extension to URLRequest for building request from ServiceProtocol. Add lastURL property to URLSessionMock and assign url from request property.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6f79141277520a3b143feaa10e8b0c06/href">https://medium.com/media/6f79141277520a3b143feaa10e8b0c06/href</a></iframe><p>New test will be easy to write.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0cca23d20edb556557a6e418017c58d5/href">https://medium.com/media/0cca23d20edb556557a6e418017c58d5/href</a></iframe><p>CMD + U ⏲️ Test succeeded!</p><h3>Next Test</h3><p>As you can see URLSessionProtocol returns URLSessionDataTaskProtocol.Can you guess what kind of test will be next? 🤔 Of course 🎊 Check if resume function was called!</p><p>💏 When: Request is called, 👶 Then: URLSessionTask should call resume function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b54d66e97f48897e781a90a22d75fcdb/href">https://medium.com/media/b54d66e97f48897e781a90a22d75fcdb/href</a></iframe><p><strong>Error:</strong> Value of type ‘URLSessionDataTaskMock’ has no member “isResumeCalled” 🤔</p><p>Do you know what to do?</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/785fd3ca84f54972780cb437dd8224c8/href">https://medium.com/media/785fd3ca84f54972780cb437dd8224c8/href</a></iframe><p>CMD + U ⏲️ Test succeeded!</p><h3>Next test</h3><p>💏 When: Request is called with json response, status code 200, 👶 Then: Request should complete with success.</p><p><strong>Info: </strong>Before you start, please copy NetworkResponseMatchers file from my repo. This file is needed to facilitate compare enum cases.</p><p>This example is much more complicated than previous one but i will explain it step by step how to write a test. In this case we want to get response with status code 200 and parse json to get ModelMock object. First we need to modify URLSessionMock. Add new property:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/55030c92da9e31d16161db91e98881fa/href">https://medium.com/media/55030c92da9e31d16161db91e98881fa/href</a></iframe><p>This property will be set from URLSessionProviderSpec and will information about tested case (for example .jsonResponseWith200). Additionally add this following function inside dataTask:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7114de36dc64a726cc6b1761e2f2dc19/href">https://medium.com/media/7114de36dc64a726cc6b1761e2f2dc19/href</a></iframe><p>This few lines switch over particular service and do some jobs. dataTask function has completionHandler which returns (Data?, URLResponse?, Error?). In .jsonResponseWith200 you need to do three things:</p><ol><li>Create ModelMock object with test value.</li><li>Encode this object.</li><li>Create response with status code 200.</li><li>Call completion handler with just created parameters.</li></ol><p>Let’s get back to URLSessionProviderSpec. What to do next? Create a new when closure, then set service case to .jsonResponseWith200.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a0c5cd8d93a12e764b06ccc2e9516d7c/href">https://medium.com/media/a0c5cd8d93a12e764b06ccc2e9516d7c/href</a></iframe><p>As you can see there is no response property. Add this property under spec function with type NetworkResponse&lt;ModelMock&gt;!. This property will keep information about response.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ca9da04354e0c76eff2f3bfff53aeea4/href">https://medium.com/media/ca9da04354e0c76eff2f3bfff53aeea4/href</a></iframe><p>CMD + U ⏲️ Test succeeded!</p><h3>Next test</h3><p>💏 When: Request is called with json response and status code 200, 👶 Then: Should return given model</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c2a1df60b32d96d31358570af03af3c/href">https://medium.com/media/5c2a1df60b32d96d31358570af03af3c/href</a></iframe><p>CMD + U ⏲️ Test succeeded!</p><h3>Homework</h3><p>It’s your turn now!</p><p>You just wrote a few tests. I hope you understand how to write unit tests for NetworkLayer and if you do — it’s time to practice. Please try to write some extra tests as your homework.</p><ol><li>💏 When: Request is called when server is down (500), 👶 Then: Request should complete with failure response</li><li>💏 When: Request is called with bad request (400), 👶 Then: Request should complete with failure response</li><li>💏 When: Request is called with json response, URL parameters, status code 200, 👶 Then: HttpBody shoud be empty</li><li>💏 When: Request is called with json response, URL parameters, status code 200, 👶 Then: URL should contains parameters</li><li>💏 When: Request is called with json response, URL parameters, status code 200, 👶 Then: Request should complete with success response</li><li>💏 When: Request is called with json response, URL parameters, status code 200, 👶 Then: Request should return given model</li></ol><p>If you are having some problems with those exercises check my repo. Or write me a private message on Twitter <a href="https://twitter.com/mtc_jackowski">@mtc_jackowski</a>.</p><p><a href="https://github.com/marcinjackowski/UnitTestNetworkLayer">marcinjackowski/UnitTestNetworkLayer</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=de4280b2b0c0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/thecocoapps/unit-test-network-layer-de4280b2b0c0">Unit test Network Layer</a> was originally published in <a href="https://medium.com/thecocoapps">thecocoapps</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dependency Inversion Swift]]></title>
            <link>https://medium.com/thecocoapps/dependency-inversion-swift-96e64a3d3a2d?source=rss-6c77af54b675------2</link>
            <guid isPermaLink="false">https://medium.com/p/96e64a3d3a2d</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[architecture]]></category>
            <category><![CDATA[unit-testing]]></category>
            <dc:creator><![CDATA[Marcin Jackowski]]></dc:creator>
            <pubDate>Mon, 10 Sep 2018 17:14:55 GMT</pubDate>
            <atom:updated>2018-09-10T17:28:46.175Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XlHjhpsmJu7PR4LEEFiwfA.png" /></figure><p>Dependency inversion is the last letter of SOLID therm. Last position doesn’t mean less important than the other, in my opinion this principle is the most important software design pattern.</p><p>The general idea of this principle is as simple as it is important:</p><blockquote>High-level modules, which provide complex logic, should be easily reusable and unaffected by changes in low-level modules, which provide utility features.</blockquote><p>In simple words — we shouldn’t use class name in any function and variable declaration. Instead of this, we should use protocols or abstract class.</p><p>Based on this idea, Robert C. Martin’s definition of the Dependency Inversion Principle consists of two parts:</p><blockquote>A. High-level modules should not depend on low-level modules. Both should depend on abstractions.</blockquote><blockquote>B. Abstractions should not depend on details. Details should depend on abstractions.</blockquote><p>If it’s your first time with DI you probably don’t understand those sentences because it sounds incomprehensible. Don’t worry! In next step i will show you the difference between traditional and inversion dependency.</p><h3>Traditional dependency</h3><p>Imagine that you have to implement screen in your app to fetch user friends from API. In traditional way you will create some service and add property to the class. Example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ca9f8ed705158559be8df0faa060efeb/href">https://medium.com/media/ca9f8ed705158559be8df0faa060efeb/href</a></iframe><p>Congrats!🙌🏻 Project manager and client are happy. But in one day requirements are changing. You have to change logic of fetch friends from API to database (CoreData) 🤔.</p><p>The service variable is of a concrete type SpecificReceiver and you invoke service method directly. This means the high level Profile depends on the low level FriendsService.</p><p>Why is this bad? Because if you were to change the FriendsService, you would have to change the Profile as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FC5W4VyAIgASaUO6XOkZeg.png" /></figure><p>So how to change the code to conform to dependency inversion principle? Let’s move to the next step.</p><h3>Dependency inversion</h3><p>To design this approach we have to start with an abstraction. You have to create protocol which service to fetch friends from API or database conform.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1ea26d0255ed3070cd221f07e2ebaa8/href">https://medium.com/media/e1ea26d0255ed3070cd221f07e2ebaa8/href</a></iframe><p>Let’s redesign Profile class.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/582c00b61a51b5e9455d33782510189f/href">https://medium.com/media/582c00b61a51b5e9455d33782510189f/href</a></iframe><p>In this scenario Profile class depends on the FriendsWorker protocol not on a concrete type FriendsService. This approach give you the opportunity to change logic without changing code in Profile class! That&#39;s awesome. If you want to fetch friends list form API, create FriendsService class conform to FriendsWorker protocol and inject this object to Profile init! What about fetch friends from Database? How to do it? In the same way!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/90befec048a3420b87ec6dd79108947b/href">https://medium.com/media/90befec048a3420b87ec6dd79108947b/href</a></iframe><p>The following diagram presents the dependency inversion. Each service or database just needs to conform to the FriendsWorker protocol in order to be used by Profile.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GFZkcZlyWZ1yRrFQgbRmKw.png" /></figure><p>That’s it. Thanks for being awesome. Please leave a comment below. Clap if you liked it ✌🏻</p><p><a href="https://github.com/marcinjackowski">marcinjackowski (Marcin Jackowski)</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=96e64a3d3a2d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/thecocoapps/dependency-inversion-swift-96e64a3d3a2d">Dependency Inversion Swift</a> was originally published in <a href="https://medium.com/thecocoapps">thecocoapps</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Network Layer in Swift 4.0]]></title>
            <link>https://medium.com/thecocoapps/network-layer-in-swift-4-0-972bf2ea5033?source=rss-6c77af54b675------2</link>
            <guid isPermaLink="false">https://medium.com/p/972bf2ea5033</guid>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[networking]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Marcin Jackowski]]></dc:creator>
            <pubDate>Thu, 06 Sep 2018 17:11:33 GMT</pubDate>
            <atom:updated>2018-09-06T17:11:33.483Z</atom:updated>
            <content:encoded><![CDATA[<p>Every time when i start a new project there is the same question. How to implement a network layer? To use external libraries like Moya, Alamofire etc. or to write it from the scratch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xxKgPqB6Hkmx6y3gJS8LwA.jpeg" /></figure><p>My answer for this question is — Use pure Swift without any third-party libraries. It’s a super simple to implement protocol-oriented layer, type safe with enum to configure endpoints and fully testable, of course. In these few points you will learn how to write protocol oriented networking layer that you can customise.</p><h3>First things first</h3><p>Before you start, it’s important to understand URLSessionand its constituent classes. In general URLSession is responsible for sending and receivng HTTPRequests. For basic requests you can use sharedsession which has no configuration object. It’s not as customisable as sessions you create by yourself, but it serves good starting point if you have very limited requirements. For other kinds of sessions, you instantiate a URLSessionwith one of three kinds of configurations:</p><ol><li>.default - session behaves as a shared session, but allows more configuration and to obtain data incrementally with a delegate.</li><li>.ephemeral - session is also similar to shared session, but don’t write caches, cookies, or credentials to disk.</li><li>.background - session let you perform uploads and downloads of content in the background while your app isn&#39;t running.</li></ol><p>URLSession returns data in two ways:</p><ol><li>completion handler</li><li>calling methods on a delegate</li></ol><p>Within a session you can create URLSessionTask to retrieve data from the server, upload photos or download files. Moreover you can also resume, suspend and cancel tasks. URLSessionTask gives opportunity to pause running task for example when user leaves app and resume it when returns. The URLSession provides three types of tasks:</p><ol><li>data - sends and receives data using Data objects. Data tasks are intended for short, often interactive requests to a server.</li><li>upload - similar to data tasks, but in general used to upload files and support background uploads while the app isn’t running.</li><li>download - retrieve data in the form of a file and support background downloads and uploads while the app isn’t running.</li></ol><p>In this tutorial you will use only first type of URLSessionTask to send request and handle response form the server.</p><p>Ok after a short recap of what URLSession can do and now let&#39;s do some practice.</p><h3>ServiceProtocol</h3><p>First you have to divide network layer to a small services. Keeping all requests in one class/enum is difficult to maintain and might transform into a monster massive thing. ServiceProtocol will be helper to create URLRequest. ServiceProtocol contains constituent components such as baseURL, path, method, headers, task and parametersEncoding. Go ahead and create your first file of simple networking layer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e7381e3be9c974b871f2697498bf2e0e/href">https://medium.com/media/e7381e3be9c974b871f2697498bf2e0e/href</a></iframe><p>HTTPMethod is an enum responsible for setting HTTP method of requests. URLRequest has property .httpMethod to set method String type.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/32218778e0a9e9156f4b73ebdb0e695d/href">https://medium.com/media/32218778e0a9e9156f4b73ebdb0e695d/href</a></iframe><p>Task is an enum responsible for configuring parameters for a specific service. You can add as many cases as are applicable to your network layer requirements. For example upload(Data), download(parameters: Parameters) etc. Example has only two cases to send plain request or with parameters.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ad78d6272733e2aac20f7b821deebb38/href">https://medium.com/media/ad78d6272733e2aac20f7b821deebb38/href</a></iframe><h3>ParametersEncoding</h3><p>ParametersEncoding is an enum responsible for setting encoding type. In this example you have to use the most popular: URL and JSON.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b4f25efc0be2828b39397c3d5b2157df/href">https://medium.com/media/b4f25efc0be2828b39397c3d5b2157df/href</a></iframe><p>Voilà! First part of creating network layer is done. Keep your head up and keep going! Let’s move to the next part — How to implement constructor of URLRequest.</p><h3>Request</h3><p>Before you send first request to the API you have to create custom request from ServiceProtocol. As you probably noticed Service has all information to construct Request. To avoid creating new class you will create an extension to URLRequest and URLComponents.</p><p>First of all: create URLComponents file. This extension will merge baseURL with path and will add parameters to the url if parameters encoding is url. Paste this code to your file:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f337b6b8bb7859d931c5bc1a73ce82d7/href">https://medium.com/media/f337b6b8bb7859d931c5bc1a73ce82d7/href</a></iframe><ol><li>To get full path of url you need to append path to base url..</li><li>Using your new url, you initialise a URLComponents.</li><li>If parameters encoding is “url” and request has parameters — create array of [URLQueryItem] for each parameter and set to the queryItems.</li></ol><p>Next step is URLRequest. Create file and add the following implementation:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/781d20f8c0845f730b35dbbedddf7d3a/href">https://medium.com/media/781d20f8c0845f730b35dbbedddf7d3a/href</a></iframe><ol><li>First create urlComponents.</li><li>Using your new urlComponents initialise a URLRequest.</li><li>Set httpMethod of the request equal to that of our ServiceProtocol.</li><li>Set headers.</li><li>If parameters encoding is “json” and request has parameters — use JSONSerialization to covert dictionary with parameters to Data. You can add try catch closure to handle the exception.</li></ol><p>Next part done! Congratulations!</p><h3>NetworkResponse</h3><p>When you get response from sent request, completion handler returns unreadable information. Optional data, response and error says nothing. You have to create enum to handle response from API and display clear message. Create two files NetworkResponse and NetworkError. There are two cases:</p><ol><li>.success - if success - returns Decodable model</li><li>.error - if error - returns error of type NetworkError.</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cdbe5ac33488c98eabfefbbbb1dc97dd/href">https://medium.com/media/cdbe5ac33488c98eabfefbbbb1dc97dd/href</a></iframe><p>For blogpost example NetworkError has only two cases:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/65a500c86a5ca68086f78ca3fa46ff67/href">https://medium.com/media/65a500c86a5ca68086f78ca3fa46ff67/href</a></iframe><h3>URLSession</h3><p>You have almost finished network layer. Last thing which need to be implement is a provider to send requests. To do that create new file ProviderProtocol and add the following implementation:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ee4b5437b118ad6f456f25c0af2220f2/href">https://medium.com/media/ee4b5437b118ad6f456f25c0af2220f2/href</a></iframe><p>ATTENTION!: T must conform to Decodable protocol.</p><p>If ProviderProtocol is done, now you can start implementing last class URLSessionProvider which is the heart of your network layer. To do that: create new file and copy following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/457d6d5e9af981128fd86697ab8e414e/href">https://medium.com/media/457d6d5e9af981128fd86697ab8e414e/href</a></iframe><ol><li>URLSessionProvider conforms to ProviderProtocol which has been created few lines earlier.</li><li>This approach is necessary to test network layer. It’s essential because in easy way you can switch session with mock file and simulate responses from API without internet connection. With the next blogpost i will explain you how to test network layer. For now please create a new file URLSessionProtocol and copy following code:</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/838de9147a63fc446007682fc976b030/href">https://medium.com/media/838de9147a63fc446007682fc976b030/href</a></iframe><p>Next you will create request function. This function is responsible for all the vital work in our network layer. Add this method to URLSessionProvider.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ad02ed259c32cf94f21c8e9258e1220/href">https://medium.com/media/3ad02ed259c32cf94f21c8e9258e1220/href</a></iframe><ol><li>Initialise request from service object.</li><li>Create URLSessionDataTask to send and receive data from API. Data tasks are intended for short, often interactive requests to a server.</li><li>Start task. Session will send request to the server and wait for the response.</li><li>handleDataResponse completionHandler returns optional values and you actually don&#39;t know if request has finished with success or error. You need extra method to parse response data and error.</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff4082cf240508164945dedce558d984/href">https://medium.com/media/ff4082cf240508164945dedce558d984/href</a></iframe><ol><li>First you have to check if an error has occurred. If your API return some information in error, add custom init to the NetworkError enum and parse it.</li><li>In this scenario all requests return a json data so if response is empty function returns error</li><li>HTTPURLResponse contains status code of sent request. In this example requests with status code between 200...299 have success status in other cases failure.</li><li>Use JSONDecoder to decode response data and return expected object with type T.</li></ol><p>That’s all! Your network layer is completed in pure Swift, no third party libraries. In next part you will find out how to create simple service and send first request.</p><h3>Demo</h3><p>In this demo you will use free API (<a href="https://jsonplaceholder.typicode.com/">https://jsonplaceholder.typicode.com</a>) which allows to fetch posts, comments and users info. First of all create file PostService and copy following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7c6c48ac44d55d0b53dd16a1b79e8160/href">https://medium.com/media/7c6c48ac44d55d0b53dd16a1b79e8160/href</a></iframe><p>PostService implements two cases: fetch all posts and comments for specific postId. For both cases you use “GET” method and “url” parameters encoding. Case “all” doesn’t require any special parameters so you can use plain request but for “comments” case you need to send request with parameters (key: “postId”, value: Int).</p><p>Finally you are ready to send your first request and use implemented provider! Open ViewController and add the following method:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ab911f61c49577094f46655dff7e6f6a/href">https://medium.com/media/ab911f61c49577094f46655dff7e6f6a/href</a></iframe><ol><li>Create property to have strong reference to the provider.</li><li>Send request with specific type. In this case you want to fetch list of posts so add Post model which conforms to Decodable and Encodable protocol.</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1b4a29c9702e826bf29912d67d8c66d9/href">https://medium.com/media/1b4a29c9702e826bf29912d67d8c66d9/href</a></iframe><p>3. Handle response! That’s all! :)</p><p>You can download the complete project for this tutorial here:</p><p><a href="https://github.com/marcinjackowski/NetworkLayer">marcinjackowski/NetworkLayer</a></p><h3>Conclusion</h3><p>As you can see to build networking layer it’s not necessary to use third-party library with complicated logic. The biggest advantage of this solution is that it’s written in pure swift. To You can download the complete project for this tutorial here.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=972bf2ea5033" width="1" height="1" alt=""><hr><p><a href="https://medium.com/thecocoapps/network-layer-in-swift-4-0-972bf2ea5033">Network Layer in Swift 4.0</a> was originally published in <a href="https://medium.com/thecocoapps">thecocoapps</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>