<?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 Soheil Novinfard on Medium]]></title>
        <description><![CDATA[Stories by Soheil Novinfard on Medium]]></description>
        <link>https://medium.com/@novinfard?source=rss-6bca32d7b400------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*COo7A4j_TWu_l2L41TmEzA.jpeg</url>
            <title>Stories by Soheil Novinfard on Medium</title>
            <link>https://medium.com/@novinfard?source=rss-6bca32d7b400------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 24 Apr 2026 05:52:00 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@novinfard/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[Make your iOS app compatible with Right to Left languages in SwiftUI and UIKit!]]></title>
            <link>https://novinfard.medium.com/make-your-ios-app-compatible-with-right-to-left-languages-in-swiftui-and-uikit-bdb164892ce3?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/bdb164892ce3</guid>
            <category><![CDATA[localization]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[right-to-left]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[swiftui]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Tue, 29 Jun 2021 01:50:20 GMT</pubDate>
            <atom:updated>2021-06-29T10:21:10.701Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kut1kVqPFxAxr6ool8iIkg.jpeg" /></figure><p>When you test your app, you may miss one of the important parts of the localisation: Right to Left(RTL) languages! There are a couple of languages that the direction of the text is from right to left such as Persian, Arabic, Hebrew, and more. Here we’re going to review some of the important points that by considering them you can easily have the RTL language support in your app and make your app usage even wider.</p><p>First of all, we need to know how to test the app in right to left(RTL) conditions. Before going to that matter, let’s create a sample iOS app to use as a sandbox.</p><p>The whole sample project is also available at the following Github repository:<br><a href="https://github.com/novinfard/iOSRTLSample">https://github.com/novinfard/iOSRTLSample</a></p><h3>Create a sample Sandbox for testing</h3><p>Follow these steps:</p><p>File &gt; New &gt; Project &gt; iOS tab &gt; App &gt; Interface: StoryBoard</p><p>After creating a new project, go to main.storyboard add a label and with 16 point margin from the top, left, and right in constraints:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dKp9SFMpmdgkJlvF8hGJrw.png" /><figcaption>Sample label constraints</figcaption></figure><p>In the label attributes, change the number of lines to 0, have natural as text alignment, and add the following text as a sample:</p><pre>این یک متن تست است. در این متن به بررسی عملکرد زبان های راست به چپ می‌پردازیم.</pre><p>Add an imageView below the text with 16 points margin from left and top, and 100 points for width and height constraints:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G1AvqKJ_twH4HYdVaFhSvg.png" /><figcaption>Sample Image constraints</figcaption></figure><p>In the image attributes, use one of the system icons like pencil.circle.fill .</p><p>In addition, add a new SwiftUI view to the project with ContentView name with the following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1d15765db539dc83fd3a2d05f3b565b5/href">https://medium.com/media/1d15765db539dc83fd3a2d05f3b565b5/href</a></iframe><p>The preview of this view would be as the below picture:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/630/1*L12VAyJOw8lj2PrGkfRumQ.png" /><figcaption>Preview of Sample SwiftUI view with a text and an image</figcaption></figure><p>Now we’re ready to test the app in RTL.</p><h3>Display and also Test the app in RTL</h3><p>There are a couple of different ways to see your app (or part of your app) in right to left semantic.</p><p><strong>Launch Argument</strong></p><p>One of the solutions is to set it as a launch argument. For doing so, choose the current scheme from the top bar of Xcode and press “Edit Scheme ...” :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Dna0W6H7bL-2JBaLHw2QZQ.png" /><figcaption>Edit the current scheme to set the launch argument</figcaption></figure><p>After opening the scheme window, go to the options tab, and in the “App Language” section, choose Right-to-Left Pseudolanguage instead of System Language :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hQCA0ip80oUhCT1tIQNrbg.png" /><figcaption>Choose Right to Left launch argument in Edit Scheme window</figcaption></figure><p>If you run the application now, you would see the layout has been changed to a right-to-left layout:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/748/1*HaKjpWEuBpjUEH6_i65VOg.png" /><figcaption>The sample app running in RTL mode — UIKit</figcaption></figure><p>Open the preview of the SwiftUI view and you will see a similar result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/604/1*wdLzGNmDoJCI78a_wMksOw.png" /><figcaption>The sample SwiftUI View previewing in RTL mode</figcaption></figure><p>We will come back to this layout automatic changing in the next section, but let’s now see what are the other options for testing in RTL.</p><p><strong>Force all or some of the views in the application to RTL mode</strong></p><p>For the testing purposes or in some scenarios based on the design requirement, you can force all the views in the application to use the right-to-left direction. To do so in UIKit you need to add this somewhere in AppDelegate:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/024abda55a2331ad5191fc0429837ec0/href">https://medium.com/media/024abda55a2331ad5191fc0429837ec0/href</a></iframe><p>If we want to force some specific views to change to the right-to-left direction in UIKit, just change semanticContentAttribute of that view in the app.</p><p>For having a similar approach and force all SwiftUI views to use right-to-left direction we can use the environment key named layoutDirection at topmost view of the application, somewhere in SceneDelegate for instance:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b8172bc9da4c3091103397fa4830adae/href">https://medium.com/media/b8172bc9da4c3091103397fa4830adae/href</a></iframe><p>If we want to force some specific views to change to the right-to-left direction in SwiftUI, we can change layoutDirection environment key on that view (including all sub-views of that view)</p><p>After exploring the different ways to update the app and view’s logic in the right-to-left direction, now let’s analyse the changes applied in iOS by this update.</p><p><strong>SwiftUI Previews for RTL direction</strong></p><p>We can easily display the SwiftUI previews in right-to-left and left-to-right by the following code using layoutDirection environment value:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e23f5201983fc73ef05e8d95d15468d2/href">https://medium.com/media/e23f5201983fc73ef05e8d95d15468d2/href</a></iframe><p>We used the previewLayout to just have more space for previewing, so you can remove it if you want to see it fully. The result would be as follows with a neat preview in both language directions:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/542/1*hrWxM9y7R_vaKfIJf22zxA.png" /><figcaption>The result of previewing the SwiftUI view in both RTL and LTR language direction</figcaption></figure><h3>Automatic changes by iOS for Right-to-Left languages</h3><p>The first important thing to note is that when we set the labels to have natural alignment, the OS itself changes the alignment based on the language. In our example, we can see this clearly:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zaheXAf2ZYnHbMU0gFhtkw.png" /><figcaption>Automatic label alignment update based on language direction</figcaption></figure><p>The second thing to notice is the update on auto-layout constraints. It changed the leading constraint to trailing one automatically (and of course visually):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kVprFen78FVNE0ltDQYsxA.png" /><figcaption>Automatic auto-layout update based on language direction</figcaption></figure><h3>Rotate images based on language direction</h3><p>The next thing you may want in right to left languages is to rotate the images themselves in these languages. To achieve this, we can use imageFlippedForRightToLeftLayoutDirection attribute of UIImage in UIKit.</p><p>To see it in action, in our example app, connect the imageView to ViewController class add the following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa477141ddb009d423c680764fb819a4/href">https://medium.com/media/aa477141ddb009d423c680764fb819a4/href</a></iframe><p>Now if we compare the result, we can see the image flipped horizontally:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*78O2BVdlSa-cX9NE2WCYmQ.png" /><figcaption>The result of forcing the image to rotate in UIKit</figcaption></figure><p>For having the same result in the SwiftUI view, we can use rotationEffect modifier with 90-degree value:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3a309dce390d483892f5bf1f7d87bc29/href">https://medium.com/media/3a309dce390d483892f5bf1f7d87bc29/href</a></iframe><p>The result is similar to UIKit one:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/606/1*PttB93pOMx35mxsF276svQ.png" /><figcaption>The result of forcing the image to rotate in SwiftUI</figcaption></figure><p>A point to consider here is that the general signs or trademarks should not be flipped based on language direction.</p><h3>Detect the language direction in the app</h3><p>In the previous example, we changed the rotation of the image, but we need to do this operation only when the direction is right-to-left. In this case and similar scenarios, we need to detect the language direction.</p><p>Since iOS 10, the view has the property effectiveUserInterfaceLayoutDirection that indicates the language direction. So by using it, we can update our UIKit example as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18b402e272879f8149aab94ef8e6577f/href">https://medium.com/media/18b402e272879f8149aab94ef8e6577f/href</a></iframe><p>In SwiftUI, we can define the layoutDirection environment value and read it for checking the language direction:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8345d52c089a4066771324da1a141be5/href">https://medium.com/media/8345d52c089a4066771324da1a141be5/href</a></iframe><p>Now we can see the language direction-based image rotation in the SwiftUI previews:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/544/1*VqTKbgOgbIlbp89c-bQ-6w.png" /><figcaption>The result of detecting RTL in the SwiftUI views</figcaption></figure><h3>Avoid the anti-pattern in the design to support Right-to-Left</h3><p>One of the simple, but important point to keep an eye on that in the design to make the application compatible with RTL languages is to avoid using element alignment as much as possible and keep the element natural alignment and behaviour.</p><p>For instance, let’s say we want to add the date in our blog view, in the <strong><em>right</em></strong><em> bottom</em> corner of it. One way to do so is to having the equal leading and trailing constraint for the label and set the label alignment to right. So we’ll have the view setup as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4a7k63PaJ_kxiMbHFNPmpw.png" /><figcaption>An example of an incorrect pattern for the RTL compatible layout in UIKit</figcaption></figure><p>With the above layout setup, If we run the application in an RTL environment, the result would be the below picture:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/684/1*-IHxFlk6JPOoVhspUnsCnw.png" /><figcaption>The result of an incorrect pattern for the RTL compatible layout in UIKit</figcaption></figure><p>As you might realise, it’s not a desirable layout. Because we want the date to be shown in the <strong><em>left</em></strong><em> bottom corner </em>when the user uses a Right-to-Left language.</p><p>To fix this, we can have only a trailing constraint for the label, and keep the label alignment natural :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3deW2e9E0fn7XJTHJaAQHQ.png" /><figcaption>An example of the correct pattern for the RTL compatible layout in UIKit</figcaption></figure><p>Now if we run the application again, we would see that the date label in the correct position for RTL direction:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/688/1*K3EotC1cUX1Ox0lpv5sH4w.png" /><figcaption>The result of a correct pattern for the RTL compatible layout in UIKit</figcaption></figure><p>With this small adjustment, now the layout is correct to Right-to-Left languages as well.</p><p>The same technique applies to SwiftUI. For instance, In the same scenario as above, we should try to use “Horizontal Stack” with “Label” and “Spacer” instead of set strict alignment for the label:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/546ada532dc83ceeac3c1c1848d6dbdf/href">https://medium.com/media/546ada532dc83ceeac3c1c1848d6dbdf/href</a></iframe><p>If we preview the above view in both direction environments, we will see the correct layouts:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*6Nu28tkw1nlkzKXJIts4fg.png" /><figcaption>The result of a correct pattern for the RTL compatible layout in SwiftUI</figcaption></figure><h3>Beyond the layout</h3><p>There are some consideration in right-to-left languages which are not related to layouts.</p><p>One of these considerations is about the numbers. The numbers in Persian and Arabic are different from English counterparts. Thus, the users can write with these localise versions of numbers both in normal keyboard mode and number pad:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Sv5GmhG_ACdELShmdj-3nA.jpeg" /><figcaption>Number pad of Persian language in iOS</figcaption></figure><p>So what if the user enters the number in localised keyboard for the verification code or as a mobile number? In order to avoid further issues in the system and the client or server-side logic, we should detect these cases in our app and update the numbers with the English equivalent. To achieve this, we can use number formatter in Swift. By the use of the following small helper we can convert numbers in any languages to English for integer types:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1d33d125066394a0218a90cbe0fd5b72/href">https://medium.com/media/1d33d125066394a0218a90cbe0fd5b72/href</a></iframe><p>To see how it works, we can update our SwiftUI app as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/000efb41c6f11ed641ae535cf3cdf298/href">https://medium.com/media/000efb41c6f11ed641ae535cf3cdf298/href</a></iframe><p>We can see the converted number in the preview:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/554/1*3xs7Het0_TcW_uRpW_9VBg.png" /><figcaption>The preview of an example of Persian number and its converted English equivalent</figcaption></figure><h3>Conclusion</h3><p>In this article, we covered how can support the right-to-left languages in our apps using UIKit or SwiftUI. we first made a sandbox to be able to test the right-to-left languages there. Then we talked about different ways we can display and test our app or some parts of it in RTL languages. In the following section, we analysed how iOS works in RTL and we made sure that we understand its automatic right-to-left behaviour. Then we reviewed how can detect the language direction in our code and use that to rotate the image for different language directions. Finally, we covered some cases where we need to consider the right-to-left languages beyond the layouts.</p><h3>Further Reading</h3><p>Apple’s Human Interface Guideline for Right-to-Left languages<br><a href="https://developer.apple.com/design/human-interface-guidelines/right-to-left/overview/introduction/">https://developer.apple.com/design/human-interface-guidelines/right-to-left/overview/introduction/</a></p><p>Supporting Right-to-Left Languages by Apple<br><a href="https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html">https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/SupportingRight-To-LeftLanguages/SupportingRight-To-LeftLanguages.html</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bdb164892ce3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Make the code testable in Swift]]></title>
            <link>https://novinfard.medium.com/make-the-code-testable-in-swift-4f3b1710e16b?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/4f3b1710e16b</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[unit-testing]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Sun, 29 Mar 2020 18:26:58 GMT</pubDate>
            <atom:updated>2020-03-29T18:26:58.642Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gDXfwB9rB7WAqf5CPY7yww.png" /><figcaption>Kudos to <a href="https://undraw.co/">undraw</a> and <a href="https://lukaszadam.com/illustrations">lukaszadam</a></figcaption></figure><p>Having a reliable and durable iOS app or framework depends on many things, but no one can deny the necessity of unit testing and UI testing for this purpose. The question comes up here is that are all codes tastable? No, unfortunately!</p><p>In this article, we review an example of improper code for testing and try to suggest some ways to solve the issue by applying various software techniques.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1gUUcHSnrpz1JgJsK3vUUQ.png" /><figcaption>[ Image is taken from 360logica.com ]</figcaption></figure><p>We start with an example of inappropriate code for testing purposes. After reviewing the scenario, we are going to look at how we can make it testable. The code is abstracted to focus on the main subject. You need to be familiar with CoreData beforehand to get the most of the example. But even if not, the description is sufficient to picture the problem.</p><p>We have a class named StandingsDatasource which is responsible for requesting the data from the network and load the parsed data in dataController (dataController is a sort of fetchResultController which can give you an array of data objects). We persist in CoreData in this scenario.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3395e453db31b8c781faa51610ecfe13/href">https://medium.com/media/3395e453db31b8c781faa51610ecfe13/href</a></iframe><p>Here, getEntityName defines which data object type (CoreData entity name) will be returned and getPredicate determines which objects of that type should be filtered and returned in the dataController.</p><p>The Standing data object is defined as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/583584416d5ee8344e5665c315400d54/href">https://medium.com/media/583584416d5ee8344e5665c315400d54/href</a></iframe><p>And the request class is defined as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/57afa58de04ada9da7d5a2e0a034b4d8/href">https://medium.com/media/57afa58de04ada9da7d5a2e0a034b4d8/href</a></iframe><p>We want to write some unit tests by which we parsed the data correctly. As the output of the datasource, we can fetch the desired objects in our dataController.</p><p>To start writing our tests here, we need to subclass StandingsDatasource to have our local datasource. Our local datasource is going to read its data from a JSON file rather than network response. The reason behind this is that we may have a different response (result in different parsed standing objects) as the endpoint updates time by time.</p><p>By looking at StandingsDatasource , we found the first issue: We don’t have access to request object to be able to change it to local request, because StandingsRequest is initiated inside the requestData method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y3KUROP5nqjSFhOUU6O4pA.png" /><figcaption>Figure 1 — Request is not accessible via the class</figcaption></figure><p>We can use the dependency injection technique to overcome the issue. Dependency injection means one object supplies the dependencies of another object. The “injection” refers to the passing of a dependency (a service) into the object (a client) that would use it [1].</p><p>There are three common types of dependency injection:</p><h3><strong>Method Injection</strong></h3><p>We can pass the request to our method by one of its parameters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZbBM81rAmMK323PK1hMcyg.png" /><figcaption>Figure 2 — Method Injection</figcaption></figure><p>We call this method injection, as we injected our dependency in the method declaration.</p><p>This is not the desired behavior here, because the requestData is called internally in the base class ManagedDataSource . So the only way to inject our request is the same, by overriding the method in our local datasource class.</p><h3><strong>Property Injection</strong></h3><p>We can pass the request as one of the class properties.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kwdpxKrfInQfKzH3uqvvyA.png" /><figcaption>Figure 3 — Parameter Injection</figcaption></figure><p>Here, we inject the request into the StandingsDatasource class. So after initializing the object, we can pass the request. The benefit of this way is we don’t have to change anything related to requestData when we subclass our local datasource. All the logic is encapsulated inside the method. However, it’s still not good enough. Because we have to define it as optional property, while we can’t imagine a correct datasource without a request dependency.</p><h3><strong>Constructor Injection</strong></h3><p>We can pass the request to the initializer of class:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qPP7FanrO1s3x9Xm1RBL2A.png" /><figcaption>Figure 4 — Constructor Injection</figcaption></figure><p>The request is assigned inside the class initializer, thus, every instance of StandingsDatasource and its subclasses would have the initiated request property.</p><p>We chose constructor for the dependency injection, but based on the case it can be different.</p><p>Now let’s look at the second issue. We have a single data type for our datasource request, StandingsRequest , but we have two types of requests: One of them gets the data from the endpoint and the other one fetches the data from our persistent module, CoreData.</p><p>These are two different concerns and can be encapsulated. We call this design principle in software architecture as “<em>Separation of Concerns</em>”. It asks us to separate the computer program into distinct sections such that each section addresses a separate concern. Each concern can be a set of information that affects the software [2].</p><h3>Endpoint Request</h3><p>For defining our endpoint request, let’s review the StandingsRequest implementation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UzdCXRxVLtcN_pIPBu0F0g.png" /><figcaption>Figure 5 — URL in Endpoint Request</figcaption></figure><p>As we can see, the only element needed for defining the URL is tournamentId. So any data structure has tournamentId and conforms to RequestProtocol is enough and no other constraint is needed, in other words, we have a protocol here. Now we can re-define our Endpoint request as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de1e357c9aa7f61eeaf2cef305a21499/href">https://medium.com/media/de1e357c9aa7f61eeaf2cef305a21499/href</a></iframe><p>We added default implementation for parser(parseDelegate:parentContext:) method because it is common among all implementation of the protocol, although it’s not necessary to be the same.</p><p>We declare an implementation of StandingsEndpointRequest which works with network requests.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d99680ebc85fac0239fd8e36e53632dc/href">https://medium.com/media/d99680ebc85fac0239fd8e36e53632dc/href</a></iframe><h3>Entity Request</h3><p>The second concern is about requesting the entity from our persistent module. We saw the footprint of this request inside the datasource class in two places:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FrAF0Api9s04BUEfAiDwvw.png" /><figcaption>Figure 6 — Standing Entity request footprint in StandingsDatasource</figcaption></figure><p>For requesting an entity in our persistent module (Core Data) we need to know of the entity’s name and related predicate of type NSPredicate. Thus, we can define our EntityRequest protocol for any entity request in the persistent module as below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b940daf623d145f6e2eaa8ff3578fd6/href">https://medium.com/media/5b940daf623d145f6e2eaa8ff3578fd6/href</a></iframe><p>For making a standing entity’s request, we need a predicate on Standing entity by using the groupName and tournamentId. Let’s define it as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2cbac99e81b0d44cbefb9c9adba70e92/href">https://medium.com/media/2cbac99e81b0d44cbefb9c9adba70e92/href</a></iframe><p>Now it’s time to come back to our datasource and refactor it with new StandingsEndpointRequest and StandingsEntityRequest :</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/746fe33b45edd3bfc20834ef600bd6d0/href">https://medium.com/media/746fe33b45edd3bfc20834ef600bd6d0/href</a></iframe><h3>Unit Testing</h3><p>We have refactored our code to testable version. In this section, we are going to write some unit tests to see how our changes eased the testing purpose.</p><p>We got a sample of the JSON response and saved that in a file named tournamentStandingsSample.json :</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ab79744ed065c168119d4d7c0ab33470/href">https://medium.com/media/ab79744ed065c168119d4d7c0ab33470/href</a></iframe><p>It returns 4 Standing entities. Three of them are in the tournament with id 10 and the last is in the tournament with id 21 . Two of the three standings of the tournament 10’s are in Group A, and the other one is in Group B.</p><p>We write three unit test for checking the parsing, duplicate parsing, and group filtering:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0579c9a4ae801e3e5fcf6856246a98a2/href">https://medium.com/media/0579c9a4ae801e3e5fcf6856246a98a2/href</a></iframe><p>First, we have defined StandingsEndpointLocalRequest which looks for local JSON files for endpoint requests.</p><p>We created a factory method named testDatasourceFetchStandings that has a default value for reading from our stored JSON file and tournament with id number10 without filtering groups as passed nil for it. The MemoryCoreDataController is a class that helps us create in-memory core data storage as part of our persistent module. It is a good idea to have this setting to avoid collision between the main app and the testing app’s object storage in unit tests.</p><h3>Conclusion</h3><p>New StandingsEndpointLocalRequest class can easily create a request with a local file that lets us focus on data source functionality with sample constant JSON file. If you check our initial request class, we couldn’t test it this way unless we subclass StandingsRequest.</p><p>Additionally, we didn’t subclass our datasource. Instead, we passed our local request injected in the initializer. So our implementation encapsulated and remained intact there.</p><h3>References</h3><ul><li>[1] Dependency injection <a href="https://en.wikipedia.org/wiki/Dependency_injection">https://en.wikipedia.org/wiki/Dependency_injection</a></li><li>[2] Separation of concerns<br><a href="https://en.wikipedia.org/wiki/Separation_of_concerns">https://en.wikipedia.org/wiki/Separation_of_concerns</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4f3b1710e16b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SwiftLint in Use]]></title>
            <link>https://novinfard.medium.com/swiftlint-in-use-279f44b3182e?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/279f44b3182e</guid>
            <category><![CDATA[swiftlint]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[xcode]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-development]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Sat, 16 Nov 2019 12:33:10 GMT</pubDate>
            <atom:updated>2019-11-19T16:11:38.888Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o8lUmAL40i9qg98Ok4GVwA.png" /><figcaption>Great visual comes by <a href="https://dribbble.com/charliechauvin">Charlie Chauvin</a></figcaption></figure><p>Here I’m going to give you some tips about how to use <a href="https://github.com/realm/SwiftLint">SwiftLint</a> in existing or new projects with four steps helping you to setup SwiftLint in your projects.</p><h3>What is SwiftLint?</h3><p>SwiftLint is a tool that can be used for enforcing Swift style and conventions in projects written in Swift. You can install it in many different ways such as installing in your machine or add it to your <a href="https://cocoapods.org/">CocoaPods</a> repo. Check the following link to see how do you want to install it:<br><a href="https://github.com/realm/SwiftLint#installation">https://github.com/realm/SwiftLint#installation</a></p><h3>Adding to your project</h3><p>After installing the SwiftLint, you can add it to your project by adding a shell script to the build phases. So go to Project &gt; Build Phases &gt; Press + &gt; New Run Script, and add the below code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4cfd1ffeb6b86ce418ded4b5eb441fff/href">https://medium.com/media/4cfd1ffeb6b86ce418ded4b5eb441fff/href</a></iframe><p>Try to have this phase in the very first phases of building the project. If SwiftLint has not been installed correctly you get a warning message, otherwise, it uses the configuration file you mentioned (<em>.swiftlint.yml</em>) and runs the tool. It is now located at the root of your project, in the same folder of your project configuration file (<em>.xcodeproj</em>), although it can be anywhere that you like. But what is this configuration file?</p><h3>Configuration file, the heart of SwiftLint tuning</h3><p>In the configuration, file you can add, disable or update the linting rules. You can see a sample of this file’s structure at below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c52d8927d59f964ed228b144bc389e87/href">https://medium.com/media/c52d8927d59f964ed228b144bc389e87/href</a></iframe><p>Don’t worry about it for now! I’m going to explain each bit in more detail in the next sections. Just have this as a reference.</p><p>The indentation in this file is important, so have the same indentation as you see in the above sample file.</p><p>Some rules are enabled by default. you can disable them in disabled_rules section of your configuration file. There are some other rules which are not activated by default, but you can activate them by adding to opt_in_rules section. To find out about all available rules briefly, type lint rules in the command line (Terminal).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qsMTnL-q4-hrip7nYqqz3Q.png" /><figcaption>List of SwiftLint rules</figcaption></figure><p>You can also find out about the rules in more detail at the following link:<br><a href="https://github.com/realm/SwiftLint/blob/master/Rules.md">https://github.com/realm/SwiftLint/blob/master/Rules.md</a></p><p>By following these 4 steps you can gracefully setup SwiftLint in your existing or new projects:</p><h3>1 — Exclude the code you don’t want to lint</h3><p>Some codes in your project can be added by third-party libraries that should be skipped in the linting process. In addition, you may borrow some code from an old code base that you don’t want to lint it. In these cases, you can remove a path or a specific file from the linting process in SwiftLint configuration:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/72d46e200df68f1d6c87946859d52a32/href">https://medium.com/media/72d46e200df68f1d6c87946859d52a32/href</a></iframe><p>One of the good examples is Pods directory which can contain the libraries or frameworks written by third-party developers.</p><h3><strong>2</strong> —<strong> Correct some linting issues automatically!</strong></h3><p>There is a built-in feature in SwiftLint by which can correct some type of violations automatically. So it is better to first run the related command to solve any issues can be fixed by SwiftLint itself:</p><p><em>swiftlint autocorrect</em></p><p>Just remember to have nothing in your disabled_rules section of configuration file before running this command, rather than those rules will be escaped from correcting.</p><p>If you want to see which ruled can be corrected by this feature, run swiftlint rules and see the “<em>correctable</em>” column.</p><h3>3 — Find rules which are not followed currently</h3><p>In the next step, we’re going to find out which rules are not followed in your project. To see violated rules run the swiftlint lint by command line in your project directory.</p><p>In the output, you can see the rules not followed as warnings such as:</p><blockquote>/MyProject/Scenes/MyScene/MyViewController.swift:103:64: warning: Redundant Void Return Violation: Returning Void in a function declaration is redundant. (redundant_void_return)</blockquote><p>At the end of each warning, rule identifier is written inside the parentheses (`redundant_void_return` in the example), copy them somewhere until you find all of them.</p><p>If your project has a lot of warnings, just run the following command to collect all rules:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1365c7fb06a5529740ccaab9ebd5e010/href">https://medium.com/media/1365c7fb06a5529740ccaab9ebd5e010/href</a></iframe><p>At the end of the command, you will find all violated rules with number of occurrences. If you want to see only the list of rules run this command instead:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ac4c932a984bc2742131e074dea9560/href">https://medium.com/media/3ac4c932a984bc2742131e074dea9560/href</a></iframe><p>Add these rules to disabled_rules section for now. If you run the SwiftLint you will find no warnings as you disabled all problematic lint rules in your project.</p><p>If you work in a team or want to have neat git history, now it’s time to make your very first commit and create a pull request for SwiftLint works.</p><h3>4 — Decide about disabled rules</h3><p>At this stage, you have a list of rules which are violated based on SwiftLint default rules and couldn’t be corrected automatically. When you remove them from your disabled list, you can see the warnings in Xcode.</p><p>You have four options here:</p><h4>a) Correct the lint issue for the rule</h4><p>If you think the rule is useful for you, you can check the lint issues; resolve them in the entire project and then remove it from the disabled list.</p><h4>b) Disable the rule generally in the project</h4><p>If the rule is not suited your project, you can keep it on the disabled list.</p><h4>c) Disable the rule in specific file or usage</h4><p>There are times that the rule is useful, but the code base is old and you should change a lot of files which doesn’t worth the time you should spend on. In addition, it’s possible that SwiftLint shows the error where actually no lint error happened (false positive). Moreover, there are times when you prefer to keep that special case breaking the lint rule. In this situation, you can disable the rule in the entire file or just for that special case.</p><p>In order to disable it you can use the following comment:<br>// swiftlint:disable rule_identifier<br>After this comment to the end of the file, all checking for that rule becomes disabled.</p><p>if you want to disable the rule only in the next line of code use the below comment:<br>// swiftlint:disable:next rule_identifier</p><p>Likewise, you can disable the rule in the current line and previous line with swiftlint:disable:this and swiftlint:disable:previous respectively.</p><h4>d) Change the rule setting</h4><p>Some of the rules have some setting that you can change it in the configuration to adapt your need. For example, you can set the line length in your configuration file as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fbf4816a1c7f270d563328dc0c9e57d6/href">https://medium.com/media/fbf4816a1c7f270d563328dc0c9e57d6/href</a></iframe><p>The above example overrides the default acceptable line_length from 120 to 140 characters. It also changes the error threshold (when SwiftLint stops the project of getting compiled and raises an error) to 160 characters. You can see the list of these configurable rules in the <a href="https://gist.github.com/novinfard/7cb0d12093bc8e2c8b7a646897eea908">sample configuration</a> file.</p><h4>Which rule should be resolved first?</h4><p>You can start with any of the rules and choose any order you like. There is only one point to consider, it is better to resolve line_length, function_body_length, and file_length respectively. The reason is that while you update your project for having the right balance of line length, it probably increases the body of type length and then file length too. Thus, it can make your work double if you do not keep this order for resolving the lint issues.</p><p>Now I’m going to add more tips related to using SwiftLint.</p><h3><strong>Strict mode</strong></h3><p>If you violate some linting rule, in most cases it raises warnings by default. Practically, there is a possibility that you don’t see the warnings, because they’re being raised after the project built again, not while you write your code! You can change the behaviour to raise errors by adding --strict argument when running the tool. So you can change the SwiftLint script in Xcode to the following one:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b83ba7f6ea42213f56bb382955453673/href">https://medium.com/media/b83ba7f6ea42213f56bb382955453673/href</a></iframe><p>By changing the script, you get a build error like the below picture in Xcode next time a rule is being violated:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vGOo903s5PFSACXtIVJA4Q.png" /><figcaption>An example of error raised in Xcode by enabling strict mode</figcaption></figure><h3><strong>Enable Xcode auto trim and white-space removal feature</strong></h3><p>One of the lint rules which can be seen as annoying is trailing_whitespace. By removing whitespaces you stop having extra unused spaces in your files which result in clean commits focused on main changes in your code. The good news is that there is a feature in Xcode that can help you to avoid whitespaces and keep in line with the rule. To enable it, go to preferences &gt; Text Editing &gt; Editing, and tick “Automatically trim trailing whitespace” and “Including whitespace-only lines” options.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/1*7_dH3n3MHPlh5fxUBoA5Kg.png" /><figcaption>Xcode auto trim and white-space removal options</figcaption></figure><h3>Add SwiftLint to CI /CD process</h3><p>To make sure that the code written by all team members is in the right place with linting, you should setup SwiftLint in your continues integration tools.</p><h3><strong>Use a style guide with SwiftLint</strong></h3><p>By using SwiftLint you can keep your code clean at some level by formatting it and enforcing some basic style rules, but it doesn’t ensure you that it follows the desired style until you follow a style guide with and keep an eye on it manually. You can have your own style guide and follow that in your code. Another option is to start using some currently trusted swift style guide and change them with your own needs. Here is a list of some common Swift style guides:</p><ul><li><a href="https://swift.org/documentation/api-design-guidelines/">Apple API Design Guidelines</a></li><li><a href="https://github.com/raywenderlich/swift-style-guide">Raywenderlich Swift style guide</a></li><li><a href="https://google.github.io/swift/">Google’s Swift style guide</a></li><li><a href="https://github.com/linkedin/swift-style-guide">LinkedIn’s Official Swift Style Guide</a></li><li><a href="https://github.com/airbnb/swift">Airbnb’s Swift Style Guide</a></li></ul><p>Are there any other tips or ideas that you find it useful while using SwiftLint? Please share them in the comments.</p><p>Thank you for reading! If you find it useful please share it via Twitter or LinkedIn to help the others as well.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=279f44b3182e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Adding AppStore’s Rate and Review feature to your iOS Application]]></title>
            <link>https://novinfard.medium.com/adding-appstores-rate-and-review-feature-to-your-ios-application-5d3cecbce311?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/5d3cecbce311</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Mon, 27 May 2019 19:17:44 GMT</pubDate>
            <atom:updated>2020-01-05T21:38:11.126Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-RmUcaafTFeD12I3tjsZ9w.gif" /><figcaption>Rating slider by <a href="https://dribbble.com/Cheezen">Anders Bjarnle</a></figcaption></figure><p>Getting feedback from the users is one of the most important parts of every mobile application with a business plan. The app users in iOS can provide their feedback in the form of ratings and reviews at AppStore. In this article, we are presenting an easy and effective solution to get feedback from users.</p><p>Before the arrival of iOS 10.3, developers used a create a button with a link to AppStore to provide a way for users to rate the application. The link could be created as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c0f93d1b6b530dba1c1ea1b54aa270f3/href">https://medium.com/media/c0f93d1b6b530dba1c1ea1b54aa270f3/href</a></iframe><p>If you do not know your app id follow these steps <em>[1]</em>:</p><ol><li>Log into <a href="http://appstoreconnect.apple.com">AppStore Connect</a></li><li>Click My Apps</li><li>Click on the App Icon you are interested in</li><li>Make sure you are on the App Store page</li><li>Go toApp Information section (it should automatically take you there)</li><li>At the bottom of that page, there is a blue link that says View on App Store. Click it and it will open to a blank page. Copy what is in the URL bar at the top of the page and that&#39;s your app reviews link. It will be live once the app is live.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gglvZAIzE3MNkBVymJ7YWg.png" /><figcaption>Figure 1 — Finding “App Id” in AppStore connect</figcaption></figure><p>But this led to a lot of ugly-faced rating views. Additionally, it was not easy to use and user-friendly. As a result, iOS provided a built-in view for this purpose in StoreKit Framework <em>[2]</em>. To call this view you only need to call requestReview method:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4b51707cc2beddf56c1ebea9a2659fe2/href">https://medium.com/media/4b51707cc2beddf56c1ebea9a2659fe2/href</a></iframe><p>The result will be arising of the rating view in Figure 2:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/414/1*VgHwedJhlFSAz_ZIJPoqvw.png" /><figcaption>Figure 2 — Native iOS rating and review feature</figcaption></figure><p>However, there are some vital facts about this method:</p><p>First of all, you should not call this method in a button press action or anything which triggers casually. The reason is the number of times that your app can call this method is limited to 3 times per year (365 days) <em>[3]</em></p><p>Secondly, the action triggered after calling this method is different based on where it happens:</p><p>a) In Simulator</p><p>Every time you will see the feedback view.</p><p>b) In Test Flight mode:</p><p>You never see the feedback view</p><p>c) In production mode:</p><p>It is based on OS decision to show or not show the feedback UI which as we described above is only happens 3 times annually.</p><p>Thus, we should have a strategy when and where to prompt the rating view. We should not interrupt the user while they are doing an action. You do not tend to get negative feedbacks of angry users, do you? :D</p><p>The other fact is that we should bear in mind is that we should not ask the users to rate before they spend a reasonable time in the app. Moreover, we should not waste our limited opportunity of showing the review feedback by triggering it repeatedly or without enough gap between request times.</p><p>To have an easy and suitable solution for review requests, I created the following helper:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dc21438a087be5d097678031e8a2b8d1/href">https://medium.com/media/dc21438a087be5d097678031e8a2b8d1/href</a></iframe><p>As can be seen, there are two methods that you should call in your application:</p><p><strong>Increase Engaging Count </strong>(incrementAppOpenedCount)<br>You should call this method whenever the user engaging factor of your application is increased. One of the easiest ways is to call this when the application is opened by the user. You can set this in AppDelegate :</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/88935540b051d85622f0a08ff9e6b82b/href">https://medium.com/media/88935540b051d85622f0a08ff9e6b82b/href</a></iframe><p><strong>Ask for Review</strong> (checkAndAskForReview)<br>This method should get called when the user is ready for submitting their review. For instance, I called this method when users opened their dashboard page of the application:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/774bbafc52003963179b32e7e66277b9/href">https://medium.com/media/774bbafc52003963179b32e7e66277b9/href</a></iframe><p>When will review be triggered?</p><p>By the default setting, it will be called firstly after 10 times (or more) engaging of the user with the app. The next time would be after 20, 60, 240 times and so on.</p><p>You can see an example of the above implementation in <em>Smart Wallet</em> open source app:</p><p><a href="https://github.com/novinfard/SmartWallet/">novinfard/SmartWallet</a></p><p><a href="https://github.com/novinfard/SmartWallet/commit/e0c039316a8c5ac5c92859757465fb1355ddb44e">https://github.com/novinfard/SmartWallet/commit/e0c039316a8c5ac5c92859757465fb1355ddb44e</a></p><p>As a final notice, users can opt out of appStore rating and reviews by changing the option in iOS Settings .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/1*73Rxayku0Ck38y_dpsG4qg.png" /><figcaption>Figure 3 — Enable / Disable `Ratings and Reviews` in iOS Settings</figcaption></figure><p><strong>References</strong></p><ol><li><a href="https://stackoverflow.com/a/52614442/3477974">https://stackoverflow.com/a/52614442/3477974</a></li></ol><p>2. <a href="https://developer.apple.com/documentation/storekit/skstorereviewcontroller/2851536-requestreview">https://developer.apple.com/documentation/storekit/skstorereviewcontroller/2851536-requestreview</a></p><p>3. <a href="https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/ratings-and-reviews">https://developer.apple.com/design/human-interface-guidelines/ios/system-capabilities/ratings-and-reviews</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5d3cecbce311" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Syncing multiple asynchronous tasks in Swift]]></title>
            <link>https://novinfard.medium.com/syncing-multiple-asynchronous-tasks-in-swift-4fd49453b739?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/4fd49453b739</guid>
            <category><![CDATA[gcd]]></category>
            <category><![CDATA[asynchronous]]></category>
            <category><![CDATA[promises]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Mon, 04 Mar 2019 23:55:36 GMT</pubDate>
            <atom:updated>2019-03-04T23:55:36.724Z</atom:updated>
            <content:encoded><![CDATA[<p>You may face the situations where it is needed some asynchronous tasks to be done first and then you can jump to the next stage of your swift program. In this article we are looking at different solutions we can apply to run the tasks asynchronously and get notified or get the results at the end of the process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*k96Eyn_qLCf3nSMqMoSXIg.jpeg" /></figure><p>As a common case, you may need to store the results of multiple network requests first and then display the proper data to the user.</p><p>Indeed if you have to request many network resources for performing a feature of your application, it may consume more energy of the device and you may think twice about, but it is out of this article’s interest.</p><p>Let’s say we have a sample network request function as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d269da4fd1c92c50a5a3d50bea1d5f34/href">https://medium.com/media/d269da4fd1c92c50a5a3d50bea1d5f34/href</a></iframe><p>And there are some network requests that we want to fulfill via the network:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3be55e7c5afeaa841f0e5b79224ca4f8/href">https://medium.com/media/3be55e7c5afeaa841f0e5b79224ca4f8/href</a></iframe><p>In the above example, baseUrl indicates our base endpoint URL and the endpoints are different requests from the web server.</p><h3>Multiple Independent Tasks (Concurrent Queue)</h3><p>We can have different async tasks which are independent of each other. It means we can run them in any order and the result of one is not related to the other task.</p><h3>DispatchGroup</h3><p>Grand Central Dispatch or GCD automatically manages the thread creation and balances them based on available device resources in iOS.</p><p>We can create a bunch of asynchronous tasks with DispatchGroup and continue our job when all of them is completed:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f32233da3093786368c11d2c3f5f45a3/href">https://medium.com/media/f32233da3093786368c11d2c3f5f45a3/href</a></iframe><p>We have notified the main thread when tasks are done but it could be any other threads. The following output could be the result (or any arbitrary order of completion of sub-tasks):</p><pre>Task albums is done</pre><pre>Task posts is done</pre><pre>Task todos is done</pre><pre>Task comments is done</pre><pre>Task users is done</pre><pre>Task photos is done</pre><pre><strong>All Tasks are done</strong></pre><p>As you can see, when all the tasks are processed we received the “All Tasks are done” message.</p><h3>Promises</h3><p>There is a pattern which is highly recommended to solve this issue: Promises.</p><p>Generally speaking, a promise represents the <em>eventual result</em> of an asynchronous task, respectively the <em>error reason</em> when the task fails. Similar concepts are also called <em>futures</em> (see this wiki article for more information <a href="http://en.wikipedia.org/wiki/Futures_and_promises">Futures and promises</a>).</p><p>We can suppose 3 different states of a promise:</p><p><strong><em>Pending</em></strong><em> : </em>unresolved task and the result is not yet available</p><p><strong><em>Fulfilled</em></strong> : resolved task with some value (successful response)</p><p><strong><em>Rejected</em></strong> : resolved task with error</p><p>There are a bunch of Cocoapods libraries to provide promises. One of the best implementations in Swift is Google Promises:</p><p><a href="https://github.com/google/promises">google/promises</a></p><p>Now we can update the solution using Promises:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3d234697c57f5d5e80d45587c98048ef/href">https://medium.com/media/3d234697c57f5d5e80d45587c98048ef/href</a></iframe><p>As can be seen, promises ease the async task process. In performNetworkPromise we first created a pending process that some data will be returned. It is like an empty async request container that we have initialized. The type Data in the promise determines what type of data it would be fulfilled with. Then we performed the network request. As a result, when we have a response we fill the promise with the data from that response.</p><p>We created an array of network requests in promiseSolution named networkPromises . The all class method waits for all the provided promises , here the network requests, to be fulfilled. Once all of them have been fulfilled with proper data, it will an array of all fulfilled values, [Data] .</p><p>The other promise implementation which is so popular in Swift community is PromiseKit.</p><p><a href="https://github.com/mxcl/PromiseKit">GitHub - mxcl/PromiseKit: Promises for Swift &amp; ObjC.</a></p><p>They are so similar to each other (the keywords are almost the same). You can check it out yourself. Just keep in mind that you should not use both of them in a single scope.</p><p>You can find the source code of this article at below repository:</p><p><a href="https://github.com/novinfard/SyncAsyncTasks">novinfard/SyncAsyncTasks</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4fd49453b739" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Creating custom shapes using Bezier Paths and animate them by CABasicAnimation in iOS]]></title>
            <link>https://novinfard.medium.com/creating-custom-shapes-using-bezier-paths-and-animate-them-by-cabasicanimation-in-ios-f26355c2538b?source=rss-6bca32d7b400------2</link>
            <guid isPermaLink="false">https://medium.com/p/f26355c2538b</guid>
            <category><![CDATA[uibezierpath]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[uikit]]></category>
            <category><![CDATA[cabasicanimation]]></category>
            <dc:creator><![CDATA[Soheil Novinfard]]></dc:creator>
            <pubDate>Mon, 11 Feb 2019 02:34:08 GMT</pubDate>
            <atom:updated>2019-02-11T22:15:22.921Z</atom:updated>
            <content:encoded><![CDATA[<p>You can create custom shapes in iOS with using the power of UIBezierPaths. In this tutorial, we are going to create custom arrow shape with bezier paths and then animate the degree of its edge by CABasicAnimation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TE1qd9TW6l1p-vpRyenYIg.jpeg" /></figure><p>You can use shape layers for creating UI elements. The shape layers are vector-based, so the quality doesn’t change with changing resolution. It is possible to animate the shape layers with Core Animation libraries which is another advantage of shaper layers. Additionally, the process of rendering the CAShapeLayer optimises by hardware.</p><p>Before starting to create a shape, let’s see the axis of drawing. Because UIBezierPaths uses Quartz coordinate systems, the y-axis is flipped vertically as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*mD0RVneEgCsEDkjRa5kfJA.jpeg" /><figcaption>Figure 1 — Modified coordinates used in Quartz ^1</figcaption></figure><p>The custom shape we want to draw in this example is an arrow shape which is shown in figure 2.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HhPBLTbDDWL_JSYajJSxrw.png" /><figcaption>Figure 2 — Arrow shape</figcaption></figure><p>To simplifies drawing this shape using bezier paths, we can think of edge points of the shape as the main points and then our job is to draw lines between these points. Figure 3 shows this shape according to its main points:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9YcDqLZGKYAMKzt4mgqc-w.png" /><figcaption>Figure 3 — Arrow shape annotated by its main points</figcaption></figure><p>The “Leading edge width” and “Trailing edge width” are two points in x-axis which indicates the shape of our arrow. If we consider the custom shape inside a rectangle as our view, leading and trailing edge width can be calculated a the percentage of the view’s width.</p><p>We want to create the whole arrow shape inside a UIView. The following code could draw our custom shape inside an instance of UIView :</p><pre>import UIKit</pre><pre>class ArrowView: UIView {<br>    <br>    override init(frame: CGRect) {<br>        super.init(frame: frame)<br>        self.initialConfig()<br>    }<br>    <br>    required init?(coder aDecoder: NSCoder) {<br>        super.init(coder: aDecoder)<br>        self.initialConfig()<br>    }<br>    <br>    let shapeLayer = CAShapeLayer()<br>    <br>    private var fillColor: UIColor = .black<br>    <br>    /// width percentage of space between view leading and edge leading<br>    ///<br>    /// The value should be between 0 and 100<br>    private var leadingEdgeWidthPercentage: Int8 = 20<br>    <br>    /// width percentage of space between view trailing and edge trailing<br>    ///<br>    /// The value should be between 0 and 100<br>    private var trailingEdgeWidthPercentage: Int8 = 20<br>    <br>    func initialConfig() {<br>        self.backgroundColor = .clear<br>        self.layer.addSublayer(self.shapeLayer)<br>        self.setup()<br>    }<br>    <br>    func setup(fillColor: UIColor? = nil,<br>               leadingPercentage: Int8? = nil,<br>               trailingPercentage: Int8? = nil) {<br>        <br>        if let fillColor = fillColor {<br>            self.fillColor = fillColor<br>        }<br>        <br>        if let leading = leadingPercentage,<br>            isValidPercentageRange(leading) {<br>            self.leadingEdgeWidthPercentage = leading<br>        }<br>        <br>        if let trailing = trailingPercentage,<br>            isValidPercentageRange(trailing) {<br>            self.trailingEdgeWidthPercentage = trailing<br>        }<br>    }<br>    <br>    private func changeShape() {<br>        self.shapeLayer.path = arrowShapePath().cgPath<br>        self.shapeLayer.fillColor = self.fillColor.cgColor<br>    }<br>    <br>    private func isValidPercentageRange(_ percentage: Int8) -&gt; Bool {<br>        return 0 ... 100 ~= percentage<br>    }<br>    <br>    override func layoutSubviews() {<br>        super.layoutSubviews()<br>        <br>        self.changeShape()<br>    }<br>    <br>    private func arrowShapePath() -&gt; UIBezierPath {<br>        let size = self.bounds.size<br>        let leadingEdgeWidth = size.width * CGFloat(self.leadingEdgeWidthPercentage) / 100<br>        let trailingEdgeWidth = size.width * (1 - CGFloat(self.trailingEdgeWidthPercentage) / 100)<br>        <br>        let path = UIBezierPath()<br>        <br>        // move to zero point (top-right corner)<br>        path.move(to: CGPoint(x: 0, y: 0))<br>        <br>        // move to right inner edge point<br>        path.addLine(to: CGPoint(x: leadingEdgeWidth, y: size.height/2))<br>        <br>        // move to bottom-left corner<br>        path.addLine(to: CGPoint(x: 0, y: size.height))<br>        <br>        // move to bottom-right side<br>        path.addLine(to: CGPoint(x: trailingEdgeWidth, y: size.height))<br>        <br>        // move to left outer edge point<br>        path.addLine(to: CGPoint(x: size.width, y: size.height/2))<br>        <br>        // move to top-right side<br>        path.addLine(to: CGPoint(x: trailingEdgeWidth, y: 0))<br>        <br>        // close the path. This will create the last line automatically.<br>        path.close()<br>        <br>        return path<br>    }<br>}</pre><p>As you can see, we have a shape layer which our custom shape is drawing on it. The FillColor indicates the color of the shape.</p><p>The arrowShapePath is responsible for creating the bezier path. As you can see, by using the close function of UIBezierPath it draws the last line between the first and last drawn point.</p><p>Now it’s time for the animation part. We want to change the path of the arrow every time we change the edge percentage in setup of the view. To do this, we cannot use default UIView animations. Instead, we can animate the shape with CABasicAnimation . We modify our initial code to add the animation:</p><pre>import UIKit</pre><pre>class ArrowView: UIView {<br>    <br>    override init(frame: CGRect) {<br>        super.init(frame: frame)<br>        self.initialConfig()<br>    }<br>    <br>    required init?(coder aDecoder: NSCoder) {<br>        super.init(coder: aDecoder)<br>        self.initialConfig()<br>    }<br>    <br>    let shapeLayer = CAShapeLayer()<br>    <br>    private var fillColor: UIColor = .black<br>    <br>    /// width percentage of space between view leading and edge leading<br>    ///<br>    /// The value should be between 0 and 100<br>    private var leadingEdgeWidthPercentage: Int8 = 20<br>    <br>    /// width percentage of space between view trailing and edge trailing<br>    ///<br>    /// The value should be between 0 and 100<br>    private var trailingEdgeWidthPercentage: Int8 = 20<br>    <br>    func initialConfig() {<br>        self.backgroundColor = .clear<br>        self.layer.addSublayer(self.shapeLayer)<br>        self.setup()<br>    }<br>    <br>    func setup(fillColor: UIColor? = nil,<br>               leadingPercentage: Int8? = nil,<br>               trailingPercentage: Int8? = nil,<br>               <strong>animate: Bool = false</strong>) {<br>        <br>        if let fillColor = fillColor {<br>            self.fillColor = fillColor<br>        }<br>        <br>        if let leading = leadingPercentage,<br>            isValidPercentageRange(leading) {<br>            self.leadingEdgeWidthPercentage = leading<br>        }<br>        <br>        if let trailing = trailingPercentage,<br>            isValidPercentageRange(trailing) {<br>            self.trailingEdgeWidthPercentage = trailing<br>        }<br>        <br><strong>        if animate {<br>            self.animateShape()<br>        } else {</strong><br>            self.changeShape()<br><strong>        }<br></strong>    }<br>    <br>    private func changeShape() {<br>        self.shapeLayer.path = arrowShapePath().cgPath<br>        self.shapeLayer.fillColor = self.fillColor.cgColor<br>    }<br>    <br>    private func isValidPercentageRange(_ percentage: Int8) -&gt; Bool {<br>        return 0 ... 100 ~= percentage<br>    }<br>    <br>    override func layoutSubviews() {<br>        super.layoutSubviews()<br>        <br><strong>        self.shapeLayer.removeAllAnimations()<br></strong>        self.changeShape()<br>    }</pre><pre><strong>private func animateShape() {<br>        let newShapePath = arrowShapePath().cgPath<br>        <br>        let animation = CABasicAnimation(keyPath: &quot;path&quot;)<br>        animation.duration = 2<br>        animation.toValue = newShapePath<br>        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)<br>        <br>        self.shapeLayer.add(animation, forKey: &quot;path&quot;)<br>    }</strong><br>    <br>    private func arrowShapePath() -&gt; UIBezierPath {<br>        let size = self.bounds.size<br>        let leadingEdgeWidth = size.width * CGFloat(self.leadingEdgeWidthPercentage) / 100<br>        let trailingEdgeWidth = size.width * (1 - CGFloat(self.trailingEdgeWidthPercentage) / 100)<br>        <br>        let path = UIBezierPath()<br>        <br>        // move to zero point (top-right corner)<br>        path.move(to: CGPoint(x: 0, y: 0))<br>        <br>        // move to right inner edge point<br>        path.addLine(to: CGPoint(x: leadingEdgeWidth, y: size.height/2))<br>        <br>        // move to bottom-left corner<br>        path.addLine(to: CGPoint(x: 0, y: size.height))<br>        <br>        // move to bottom-right side<br>        path.addLine(to: CGPoint(x: trailingEdgeWidth, y: size.height))<br>        <br>        // move to left outer edge point<br>        path.addLine(to: CGPoint(x: size.width, y: size.height/2))<br>        <br>        // move to top-right side<br>        path.addLine(to: CGPoint(x: trailingEdgeWidth, y: 0))<br>        <br>        // close the path. This will create the last line automatically.<br>        path.close()<br>        <br>        return path<br>    }<br>}</pre><p>After animation happened, the shape does not change its path. To apply our changes we have two options in animateShape method:</p><ol><li>Freezing the animated path:</li></ol><pre>animation.fillMode = CAMediaTimingFillMode.forwards animation.isRemovedOnCompletion = false</pre><p>This solution leads to further problems. For instance, it disables the auto-layout for redrawing the shape layer which in turn results in incorrect shape size after device rotation.</p><p>2. Using the animation ending delegate:</p><p>By using the CAAnimationDelegate , we could change the shape’s path when the animation has ended. The below code demonstrates how we can handle it:</p><pre>private func animateShape() {<br>        let newShapePath = arrowShapePath().cgPath<br>        <br>        let animation = CABasicAnimation(keyPath: &quot;path&quot;)<br>        animation.duration = 2<br>        animation.toValue = newShapePath<br>        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)<br><strong>        animation.delegate = self<br></strong>        <br>        self.shapeLayer.add(animation, forKey: &quot;path&quot;)<br>    }</pre><pre><strong>extension ArrowView: CAAnimationDelegate {<br>    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {<br>        if flag {<br>            self.changeShape()<br>        }<br>    }<br>}</strong></pre><p>To wrap-up the solution, we are going to use our arrow in a view controller with a button to trigger the animation action as follows:</p><pre>import UIKit</pre><pre>class ViewController: UIViewController {<br>    <a href="http://twitter.com/IBOutlet">@IBOutlet</a> weak var arrowView: ArrowView!<br>    private var reverseAnimation = true<br>    <br>    override func viewDidLoad() {<br>        super.viewDidLoad()<br>    }<br>    <br>    <a href="http://twitter.com/IBAction">@IBAction</a> func AnimatePressed(_ sender: AnyObject) {<br>        self.reverseAnimation.toggle()<br>        let (leadingPercentage, trailingPercentage) = self.reverseAnimation ? (Int8(0), Int8(0)) : (Int8(50), Int8(50))<br>        <br>        self.arrowView.setup(leadingPercentage: leadingPercentage,<br>                             trailingPercentage: trailingPercentage,<br>                             animate: true)<br>    }<br>}</pre><p>In this example controller, we animate the edge path percentage between 0 and 50. The result is shown in the below demo:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*cPSAl2JMG_m75AjZE_o7oA.gif" /><figcaption>Figure 4 — Animation of arrow’s edge</figcaption></figure><p>If you tend to create complex custom shapes, you can use some tools such as <a href="https://www.paintcodeapp.com">PaintCode</a>.</p><p>You can check the source code and fork it in the following Github repository:</p><p><a href="https://github.com/novinfard/BezierPath">novinfard/BezierPath</a></p><p>References:</p><ol><li><a href="https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_overview/dq_overview.html#//apple_ref/doc/uid/TP30001066-CH202-CJBBAEEC">Apple Quartz 2D Programming Guide</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f26355c2538b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>