<?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"><channel><title><![CDATA[Irem Karaoglu's Blog]]></title><description><![CDATA[Irem Karaoglu's Blog]]></description><link>https://iremkaraoglu.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 05:20:05 GMT</lastBuildDate><atom:link href="https://iremkaraoglu.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Where have I been since the last blog post]]></title><description><![CDATA[Hi, it’s been a while since I last posted a blog. It feels strange because I used to post often, and they were generally about technical topics. This time, I'm sharing with you as if speaking to a friend. So, where have I been since our last conversa...]]></description><link>https://iremkaraoglu.com/where-have-i-been-since-the-last-blog-post</link><guid isPermaLink="true">https://iremkaraoglu.com/where-have-i-been-since-the-last-blog-post</guid><category><![CDATA[iOS]]></category><category><![CDATA[indiedev]]></category><category><![CDATA[SwiftUI]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Tue, 22 Apr 2025 05:25:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/zWOQD6fFCBs/upload/84720d4ff1cabdd247670a6900b12868.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi, it’s been a while since I last posted a blog. It feels strange because I used to post often, and they were generally about technical topics. This time, I'm sharing with you as if speaking to a friend. So, where have I been since our last conversation?</p>
<p>First of all, my blog post frequency decreased significantly after changing jobs. In my previous job, I wasn’t learning much, and I was writing to learn more. My new (current) job has changed my life significantly, and fortunately, in a good way. It was a milestone in my life. I wanted to work remotely, without being tied to a specific city. This job allowed me to travel more and work from different places. On a deeper level, I really like to feel like a bird. I don’t want to be in a cage, so it was a nice opportunity for my soul.</p>
<p>In my previous job, I was working on a hybrid app, not a native iOS app. This job involves a native iOS app used by millions of people. In my previous job, there was only one co-worker who could mentor me. My current job has wonderful, genius people who love learning and teaching. This job has helped me learn more about my field and my interests, so I didn’t feel the need to write blog posts because my job was already feeding my desire to learn.</p>
<p>In these almost three years, I built two apps on my own to improve myself. Software development is not only about writing blog posts; I needed more coding experience. During this time, I also gave three talks at the Devnot Mobile Conference in Istanbul, Turkey.</p>
<p>Writing was like a comfort zone for me. I tried new zones, new experiences, faced public speaking anxiety, started new hobbies, and returned to old hobbies. And… here I am. I feel like I’ve learned a lot during these three years. I can’t wait to share everything, one by one. I needed to experience more to write more. Here I am.</p>
<p>I can’t wait to share some technical insights and my experiences, like the mistakes I made when I released my first app. Please subscribe to my mailing list to get notified when I post. Don’t worry, I won’t spam you! Until next time, take care! 🙋🏻‍♀️</p>
]]></content:encoded></item><item><title><![CDATA[Notes to myself about SwiftUI - 1🐦]]></title><description><![CDATA[I've been studying Stoicism, and one of the important books on this topic is 'Meditations' by Marcus Aurelius, who was a wise emperor and philosopher. In his book, he wrote notes to himself, creating a valuable guide to Stoicism. He talks to himself ...]]></description><link>https://iremkaraoglu.com/notes-to-myself-about-swiftui-1</link><guid isPermaLink="true">https://iremkaraoglu.com/notes-to-myself-about-swiftui-1</guid><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Fri, 08 Sep 2023 10:27:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/f-3mUXFLY2o/upload/90c4528164fe3c0809fb3becf235be6f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've been studying Stoicism, and one of the important books on this topic is 'Meditations' by Marcus Aurelius, who was a wise emperor and philosopher. In his book, he wrote notes to himself, creating a valuable guide to Stoicism. He talks to himself in these notes. Now, in this article, I'll be writing notes to myself, while focusing on using SwiftUI.</p>
<h3 id="heading-ui-development">UI development</h3>
<ul>
<li><p>ContentView is the root view in the hierarchy.</p>
</li>
<li><p>There can be a maximum of 10 views inside a VStack.</p>
</li>
<li><p>The default layout priority is 0. The higher the number, the higher the priority to have enough space to not be truncated.</p>
</li>
<li><p>You can add layers on top (<code>.overlay()</code>), behind (<code>.background()</code>)</p>
</li>
<li><p>All the modifiers (such as padding, background...) create new layers in the view tree, their sequence often matters. Calling <code>.padding().background(..)</code> is different than calling <code>.background(..).padding()</code>.</p>
</li>
<li><p>In view builders, you can only write a very limited subset of Swift. For example, you cannot write loops, guards, or if let's. However, you can write simple Bool if statements.</p>
</li>
<li><p>When we are talking about views, we are talking about values conforming to the View protocol.</p>
</li>
<li><p>Calling APIs like <code>.frame</code> and <code>.offset</code> does not modify the properties of the view but rather wraps the view in a modifier.</p>
</li>
<li><p>Stop using <strong>UIScreen.main.bounds</strong>. Be open to using <strong>GeometryReader</strong>. GeometryReader is a container view to inspect and use properties that can help with positioning other views within it. We can access properties like height, width and safe area insets.</p>
</li>
<li><p>If we would like to update what's onscreen, we can't update it directly. Instead, we have to modify properties that marked with the following attributes <code>@State</code>, <code>@ObservedObject</code> or <code>@EnvironmentObject</code> and let SwiftUI figure out how the view tree has changed.</p>
</li>
<li><p>Changing state properties is the only way to trigger a view update in SwiftUI.</p>
</li>
<li><p>SwiftUI views are values, not objects. They are immutable, transient descriptions of what should be onscreen.</p>
</li>
<li><p>A binding is essentially a getter and a setter for a captured variable. SwiftUI's property wrappers have a corresponding binding that you can access by using the $ prefix.</p>
</li>
<li><p>In property wrapper terminology, the binding is called a projected value.</p>
</li>
<li><p>All the property wrappers SwiftUI uses for triggering view updates conform to the DynamicProperty protocol.</p>
</li>
</ul>
<h3 id="heading-performance-related">Performance related</h3>
<ul>
<li><p><code>VStack</code> loads all child views when displayed. When we use <code>LazyVStack</code>, SwiftUI will not load them unless it needs to show them on the screen. Using <code>LazyVStack</code> increases performance. We are also able to pin a section header and footer. (VStack doesn't allow this.)</p>
</li>
<li><p>AnyView can contain completely arbitrary view trees with no requirement that their type be statically fixed at compile time. While this gives us a lot of freedom, AnyView should be something we only use as a last resort. This is because using AnyView takes away essential static-type information about the view tree that otherwise helps SwiftUI perform efficient updates.</p>
</li>
<li><p>We can best make use of SwiftUI’s smart view tree updates when we place state properties as locally as possible. Conversely, it’s the worst possible option to represent all model states with one state property on the root view and pass all data down the view tree in the form of simple parameters, as this will cause many more views to be needlessly reconstructed.</p>
</li>
<li><p>The State type also enables dependency tracking. When a view’s body accesses the wrappedValue of a State variable, a dependency is added between that view and the State variable. This means SwiftUI knows which views to update when the wrappedValue changes.</p>
</li>
</ul>
<h3 id="heading-testing">Testing</h3>
<ul>
<li><p>You can add different devices to previews to see various devices by writing <code>.previewDevice("iPad Pro (9.7 inch)")</code></p>
</li>
<li><p>You can add different orientations to previews by writing</p>
<p>  <code>.previewInterfaceOrientation(.landscapeLeft)</code></p>
</li>
<li><p>The List component uses UITableView in iOS 15, and UICollectionView in iOS 16. If you are using List, there might be bugs about this difference.</p>
</li>
<li><p>Make sure you test on different iOS versions because most probably there will be unexpected bugs.</p>
</li>
<li><p>Testing on a physical device is always worth it.</p>
</li>
</ul>
<p><strong>Programming mentality in general</strong></p>
<ul>
<li>If you see something new and don't understand why it's used in your codebase, research about it.</li>
</ul>
<hr />
<p>Some notes are based on my experiences, some of them are taken from <a target="_blank" href="https://www.objc.io/books/thinking-in-swiftui/#bundles">Thinking in SwiftUI book</a> and <a target="_blank" href="https://www.bigmountainstudio.com/swiftui-views-book-14">SwiftUI Views Mastery</a> book. Hope you enjoyed this article, looking forward to publish part 2. Happy coding!</p>
]]></content:encoded></item><item><title><![CDATA[Debugging in iOS development]]></title><description><![CDATA[It is not the case that we work every day on creating new features for our application. The tasks listed on our JIRA board are not solely focused on adding new features; we also receive tasks related to fixing bugs. Additionally, while we are in the ...]]></description><link>https://iremkaraoglu.com/debugging-in-ios-development</link><guid isPermaLink="true">https://iremkaraoglu.com/debugging-in-ios-development</guid><category><![CDATA[DebuggingFeb]]></category><category><![CDATA[iOS]]></category><category><![CDATA[debugging]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[Swift]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Thu, 16 Feb 2023 07:53:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/hGV2TfOh0ns/upload/1afbc16b7cdc016b84b32db88191cbb8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is not the case that we work every day on creating new features for our application. The tasks listed on our JIRA board are not solely focused on adding new features; we also receive tasks related to fixing bugs. Additionally, while we are in the process of developing a new feature, it's common to encounter bugs. In this article, I want to offer my insights on debugging to assist you in finding solutions more efficiently.</p>
<p>While my insights might be iOS development specific, if you are a mobile developer or front-end developer, I believe you'll find them relatable at many points.</p>
<h3 id="heading-identify-the-problem-first"><strong>Identify the problem first.</strong></h3>
<p>A clear understanding of the problem is essential for developing an effective solution. To gain this understanding, it is necessary to conduct a thorough analysis of the problem. During the analysis process, it is important to ask questions to gain a deeper understanding of the problem.</p>
<p>For example, if the problem is related to a user interface, it is necessary to determine whether the issue is a bug or a data-related issue. Additionally, it is important to determine if the problem is limited to one specific type of device or if it occurs on other types of devices as well. Furthermore, it should be considered to identify the operating system version in which the problem occurs, as this information can provide valuable insights into the cause of the problem. By asking the right questions, we can gain a clear understanding of the problem.</p>
<p>Some questions that I frequently think about when I encounter a UI bug are the following.</p>
<ul>
<li><p>Does this problem occur on every device (every model of iPhone)?</p>
</li>
<li><p>Does this problem occur on every iOS version?</p>
</li>
<li><p>Does this problem occur in the simulator?</p>
</li>
<li><p>Does this problem occur on physical devices?</p>
</li>
<li><p>Do other components of the UI match the design?</p>
</li>
<li><p>Could it be related to the dark theme or the light theme?</p>
</li>
<li><p>Could it be related to the system settings?</p>
</li>
</ul>
<p>In addition to code review or testing on different devices, I use two tools to find the problem and the solution. One of them is a Figma plugin that I developed, and the other one is Visual Debugger on Xcode, which we will talk about later on.</p>
<p>To measure the size of components, paddings, and other details, I use <a target="_blank" href="https://www.figma.com/community/plugin/1107993996626134259/Screenshot-Resizer">Screenshot Resizer</a>. It is not directly a tool to measure components. I take a screenshot of the simulator or physical device, add it to a Figma canvas, run the plugin, create a new frame on that canvas, and place it where I want to measure. I wrote <a target="_blank" href="https://iremkaraoglu.com/a-figma-plugin-for-resizing-screenshots">an article</a> that covers the story behind that plugin and how to use it.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.figma.com/community/plugin/1107993996626134259">https://www.figma.com/community/plugin/1107993996626134259</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://iremkaraoglu.com/a-figma-plugin-for-resizing-screenshots">https://iremkaraoglu.com/a-figma-plugin-for-resizing-screenshots</a></div>
<p> </p>
<hr />
<p>Before we start to Xcode's capabilities for debugging, I would like to share a recent UI-related debug story that I won't forget.</p>
<p>Recently, while developing a screen, I encountered UI bugs. The issue involved distortion on the physical device, but when I tested the screen on the iPhone 14 simulator, everything was properly displayed in the correct place and size. However, when I checked the physical iPhone 14 device, I noticed excessive padding and truncated text that made it difficult to understand. Since the project is confidential, I was not able to share the UI with the developer community and get opinions about the problem from them. I investigated the issue, trying to determine the cause, but the problem was not limited to a single component. Instead, it was occurring in multiple components, and I attempted to identify a pattern or common component that may be contributing to the issue. After spending many hours investigating, checking iOS versions, and testing other iPhone models, I finally found the problem. The font size on my device was set larger than the default one in system settings, which distorted the UI. After discovering this, I felt a great sense of relief. 🤗 This was a valuable lesson for me, as it taught me that not every issue is caused by code; sometimes it can be an accessibility issue by not making the components dynamic size to the system settings.</p>
<h3 id="heading-debugging-on-xcode">Debugging on Xcode</h3>
<p>In two previous articles, we covered the <strong>Screenshot Resizer</strong> Figma plugin, which makes it easy to measure component size and paddings easily. Another way to debug for UI issues is to check View Hierarchy on Xcode. When you run the app and then click View Hierarchy, it takes a snapshot of the current screen and lets you inspect the layers. This allows you to see whether a component is rendered or not, which layer is on top, the frame size of a component, and more. Sounds interesting? If you'd like to learn more about Visual Debugger on Xcode, Sean Allen's following video is really helpful.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=-o2BwAsvoH4">https://www.youtube.com/watch?v=-o2BwAsvoH4</a></div>
<p> </p>
<hr />
<p>Working at a startup for over 2 years gave me some nice development skills and helped me to become a product-minded developer. Now, as I change my job and work in an enterprise company, being a member of an iOS team with talented people has brought me new skills and new perspectives. During our pair programming sessions, I realize that they debug on Xcode effectively. I used to be the type of person who added print statements inside functions to see if they worked. Now, I use breakpoints more than ever. I have added two helpful videos to learn more about debugging tricks on Xcode. I believe that learning the IDE's capabilities and features better helps us to code more effectively.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/qPWfOkHcKdU">https://youtu.be/qPWfOkHcKdU</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=ZAqnJQn7xp4">https://www.youtube.com/watch?v=ZAqnJQn7xp4</a></div>
<p> </p>
<p>Friendly reminder: If these don't work for you, and you are stuck at some point, it is okay to ask for help 💙</p>
<p>I would like to finish my article with a quote by Nicholas Negroponte: "Programming allows you to think about thinking, and while debugging you learn learning." We all need to improve our debugging skills for greater productivity. I hope you enjoyed this article and the resources that I recommend. If you have any feedback, do not hesitate to write me via <em>hi@iremkaraoglu.com</em>. If you would like to be notified when I publish new articles, please subscribe to my newsletter. Until next time, take care! 🍀</p>
]]></content:encoded></item><item><title><![CDATA[Creating a bounce effect on Swift with UIBezierPath]]></title><description><![CDATA[Creating aesthetic aspects on a digital product is vital to boost interaction with people. To add amusing features to them, animations or images can be used. We create entertaining and instructive mobile applications for kids at Otsimo, where I work ...]]></description><link>https://iremkaraoglu.com/creating-a-bounce-effect-on-swift-with-uibezierpath</link><guid isPermaLink="true">https://iremkaraoglu.com/creating-a-bounce-effect-on-swift-with-uibezierpath</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week4]]></category><category><![CDATA[Swift]]></category><category><![CDATA[animation]]></category><category><![CDATA[uibezierpath]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Fri, 09 Sep 2022 05:30:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662274999992/t406qZurY.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating aesthetic aspects on a digital product is vital to boost interaction with people. To add amusing features to them, animations or images can be used. We create entertaining and instructive mobile applications for kids at Otsimo, where I work as a mobile application developer. In April 2022, we launched the Sago Mini First Words app, and we continue to add new features every day. Sago Mini First Words helps children say their first words or to make speech improvements. We just introduced a brand-new category called Songs! Compared to other categories, the songs category offers a distinctive experience, and the Songs category is featured on Apple App Store 🚀 The song has lyrics that the child can sing along to. In this article, I am going to show you how to achieve the bounce effect on these lyrics that I used during the implementation of the Songs category. First, let's watch a video from our application to understand what we are going to do throughout this tutorial.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/ZrqfgFqkId8">https://youtu.be/ZrqfgFqkId8</a></div>
<p> </p>
<p>Creating engaging apps is what I do every day. It could be challenging to include amusing components while developing an app. Whenever I manage a complicated design, I use UIBezierPath as a solution. You don't need to worry if you are unsure of what it is. In this article, you will find the answer to UIBezierPath.</p>
<p>To fully describe it for this blog, I made a simple demo application. I won't go through each line step by step. I'll try to give you the idea, but feel free to look through my source code and use this demo program however you like.</p>
<p>This is how the demo application looks:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/aHqT1TU_edI">https://youtu.be/aHqT1TU_edI</a></div>
<p> </p>
<p>To result in the same application, what you need to do is</p>
<ul>
<li><p>create separate UILabels</p>
</li>
<li><p>create a ball as UIView</p>
</li>
<li><p>create a path for the ball to travel through</p>
</li>
<li><p>assign animation durations to the spots the ball will bounce on.</p>
</li>
</ul>
<p>I start by including dummy labels like "Lorem Ipsum Dolor Sit Amet." Every word in the sentence is actually a UILabel, and I provide a certain distance between each one. I won't go into these because I want to concentrate on the bounce effect, but you may check the source code as described above.</p>
<p>Then, let's create a ball as a UIView since it will be crucial to our efforts. We will bounce this ball by building a UIBezierPath because it needs a path to travel through; however, we will get to that part of the discussion later.</p>
<pre><code class="lang-plaintext">    func addDot() {
        let ball = UIView()
        ball.layer.cornerRadius = dotSize/2
        ball.backgroundColor = UIColor(red: 242/255, green: 141/255, blue: 10/255, alpha: 1)
        ball.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(ball)
        self.dot = ball

        NSLayoutConstraint.activate([
            ball.widthAnchor.constraint(equalToConstant: dotSize),
            ball.heightAnchor.constraint(equalToConstant: dotSize),
            ball.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: initialPoint.x),
            ball.topAnchor.constraint(equalTo: view.topAnchor, constant: initialPoint.y),
        ])
    }
</code></pre>
<p>The ball on the screen is made with the code snippet below. Let's go on to the section where the ball should land. I want the ball to bounce at each of the label's middle places in this demo application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662565328268/voOU0Oki9.png" alt="Screen Shot 2022-09-07 at 18.42.01.png" /></p>
<p>We must calculate the points where the ball bounces in order to understand them. The UILabel's width is returned by the next function, which retrieves a UILabel.</p>
<pre><code class="lang-plaintext">   func findWidthOfEachLabel(label: UILabel) -&gt; CGFloat {
       // returns the width of a given UILabel
       let width = label.text?.size(withAttributes:[.font: label.font as Any]).width ?? 30
       return width
   }
</code></pre>
<p>The path must now be drawn. The ball must traverse curves. As a result, we make curves like this:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/R8a3AMvMBEE">https://youtu.be/R8a3AMvMBEE</a></div>
<p> </p>
<p>We use UIBezierPath in order to produce this curve graphic. UIBezierPath is a class by UIKit and Apple’s developer docs put it this way: “UIBezierPath is a path that consists of straight and curved line segments that you can render in your custom views.” We can draw vectors thanks to it. In the below code snippet, we check the labels which we created and we have a starting point for labels. Then, we move the path to the point where we start the path. Since I preferred to observe the ball arrive at the first label—in our case, "Lorem"—from the outside, I made the decision to begin this path before the label.</p>
<pre><code class="lang-plaintext">      func createBezierPath() -&gt; UIBezierPath? {
        guard !labelWidths.isEmpty else { return nil }

        let path = UIBezierPath()
        var point = initialPoint
        point.x = initialPoint.x + labelWidths[0]/2 - 10
        var previousLabelWidth = 10.0
        var deltaX = 0.0

        for index in 0..&lt;labels.count {
            deltaX = (previousLabelWidth  + (space*2) + labelWidths[index])/2

            if index == 0 {
                path.move(to: point)
            }

            let controlPoint1 = CGPoint(x: point.x + deltaX/2,
                                        y: point.y - dotYvalue)
            let controlPoint2 = CGPoint(x: point.x + deltaX/2,
                                        y: point.y - dotYvalue)
            let destination = CGPoint(x: point.x + deltaX,
                                      y: point.y)
            point = destination
            points.append(destination)
            path.addCurve(to: destination, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
            previousLabelWidth = labelWidths[index]
            durations.append(0.3)
        }
        // last bounce
        let controlPoint1 = CGPoint(x:  point.x + lastBounceX/2,
                                    y: point.y - dotYvalue)
        let controlPoint2 = CGPoint(x:  point.x + lastBounceX/2,
                                    y: point.y - dotYvalue)
        let destination = CGPoint(x:  point.x + lastBounceX,
                                  y: point.y)
        point = destination
        points.append(destination)
        path.addCurve(to: destination, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
        durations.append(0.3)

        return path

    }
</code></pre>
<p>Now, the path is available but not the animation. We first establish the aforementioned path in order to witness the animation. We construct CAKeyframeAnimation, which is yet another UIKit class that is described as "An object that provides keyframe animation capabilities for a layer object" in the Apple documentation. Our UIBezierPath object's cgPath is passed to the animation's path attribute, and keyTimes is assigned to help determine how long each curve animation will last.</p>
<pre><code class="lang-plaintext">func startDotAnimation() {

        let path = createBezierPath()

        let animation = CAKeyframeAnimation(keyPath: "position")
        animation.path = path?.cgPath

        animation.duration = durations.reduce(0, { partialResult, v in
            partialResult + v
        })

        var cd = 0.0

        let times: [NSNumber] = durations.enumerated().compactMap({ index, duration in
            cd = cd + duration
            let xd = cd - duration*0.5
            return index + 1 == durations.count ? 1.0 : xd / animation.duration as NSNumber
        })

        animation.keyTimes = [0.0] + times
        self.dot?.layer.add(animation, forKey: "bezier")
        self.dot?.alpha = 1
        self.dot?.center = self.points.last!

    }
</code></pre>
<p>For each label, I specified values of 0.3 seconds when I wrote the UIBezierPath. You are able to alter it as you work on it. Also, if you would like to see the path you created during your implementation, you may use the following function.</p>
<pre><code class="lang-plaintext">func showPath(_ path: UIBezierPath) {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        shapeLayer.fillColor = UIColor(red: 222/255, green: 120/255, blue: 180/255, alpha: 0.3).cgColor
        shapeLayer.strokeColor = UIColor(red: 222/255, green: 120/255, blue: 180/255, alpha: 0.9).cgColor
        shapeLayer.lineWidth = 3.0
        view.layer.addSublayer(shapeLayer)
    }
</code></pre>
<p>This function adds a CAShapeLayer to your screen and shows the path we created. You may call this function inside the startDotAnimation function since we create the path there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662700830394/j-lR61Vs7.png" alt="Screen Shot 2022-09-09 at 07.59.58.png" /></p>
<p>During this article, I tried to give you the general idea of achieving the bounce effect. I hope this article helps you to learn about the animations and the UIBezierPath. You may work on <a target="_blank" href="https://github.com/iremkaraoglu/iOS-Bounce-Animation">this demo app's source code</a>. Thank you for reading, if you have any feedback you may reach me at the comments below or via hi@iremkaraoglu.com. If you like this article, please add some reaction 🦄 Thank you, see you in the next article!</p>
]]></content:encoded></item><item><title><![CDATA[Meet my latest project: a Figma Plugin for resizing screenshots]]></title><description><![CDATA[I was at the beginning of my career and wanted to build a product. I was planning to build an iOS application as my first product. However, things changed and I decided to develop a Figma Plugin.
Before we start, you may access the plugin that I buil...]]></description><link>https://iremkaraoglu.com/a-figma-plugin-for-resizing-screenshots</link><guid isPermaLink="true">https://iremkaraoglu.com/a-figma-plugin-for-resizing-screenshots</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week3]]></category><category><![CDATA[figma]]></category><category><![CDATA[plugins]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Thu, 01 Sep 2022 04:13:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/4tXfdctTcWs/upload/v1668255635667/vr-vr3mnZ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I was at the beginning of my career and wanted to build a product. I was planning to build an iOS application as my first product. However, things changed and I decided to develop a Figma Plugin.</p>
<p>Before we start, you may access the plugin that I built - called Screenshot Resizer - from <a target="_blank" href="https://www.figma.com/community/plugin/1107993996626134259">here</a> and the demo video is <a target="_blank" href="https://www.youtube.com/watch?v=gOq0llL70po">here</a>. In this article, I am going to share the story of that product, the process of building it in TypeScript, and the useful resources that I have used throughout this journey.  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662005246436/Tb5GYqM0l.png" alt="183249361-8a8f62d8-d671-41c9-81af-24ee8cd20e05.png" /></p>
<h3 id="heading-background-story">Background Story</h3>
<p>As a mobile developer, I use design tools a lot to get the design from the design team in our company. I got a request from one of my designer co-workers, Ersin Kıymaz, about developing a Sketch plugin when using Sketch in our company. To be honest, I procrastinated it. Then, after a year, we switched to using Figma in our company instead of Sketch and he again requested a plugin from me for Figma.</p>
<h3 id="heading-identifying-the-problem">Identifying the problem</h3>
<p>During his design process, he often takes screenshots from the mobile applications on his phone and imports them into Figma. He checks for the widths, heights, margins, paddings, and so on. The problem here is when you add a screenshot to Figma, it seems a lot bigger because it imports according to the device’s physical width and height. Let’s dive in to understand clearly. </p>
<p>There are two concepts here, point and pixel. A point consists of pixels. If a point has more pixels, the screen looks sharper. The below image gives an example of some devices. iPhone 6 Plus looks sharper than iPhone 6 because it has more pixels.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662004818703/0WfPs9bFx.jpeg" alt="1520128516783.jpeg" />
Source: https://www.linkedin.com/pulse/difference-between-point-pixel-charanjeet-singh/</p>
<p>For instance, let’s say we have iPhone 13 Pro Max. This device’s screen has 1284 points in width and 2778 points in height. If you create a prototype on Figma for iPhone 13 Pro Max, it’s going to be 428 x 926 because it is a logical size. There is a scale factor of 3. So, each one of the 428 points has 3 pixels. Therefore, the physical size is the logical size’s multiplication by 3. The scale factor changes according to the device and it’s hard to remember this for all of the iOS devices. You may check online the device’s scale factor and update the frame’s size on Figma, yes that’s an option but we wanted to make it automated and a basic thing as a first product.</p>
<h3 id="heading-use-case">Use case</h3>
<p>As a mobile developer, I use this plugin in order to see if I developed the app’s UI correctly. My designer friend, Ersin, also checks the app to give feedback to the development team. In addition to them, Ersin also takes screenshots from other applications, imports them to Figma, and observes the size of the components, margins, and paddings.</p>
<h3 id="heading-finding-the-solution">Finding the Solution</h3>
<p>The solution was clear actually. We have the screenshots. We know devices’ physical size, scale factors, and logical size. We thought there should be something to convert the screenshot’s frame size ( physical size in this case) to the logical size. </p>
<p>We planned to save all of the iOS devices’ physical sizes in our plugin’s codebase and when a screenshot is selected on Figma, run the plugin, and resize the screenshot to the logical size by diving by the scale factor. </p>
<h3 id="heading-lets-start-building-a-figma-plugin">Let’s start building a Figma Plugin</h3>
<p>My favorite two resources during this journey were:</p>
<ul>
<li>A video on <a target="_blank" href="https://youtu.be/pFGhMr6rDhc">Youtube</a></li>
<li>Documentation of <a target="_blank" href="https://www.figma.com/plugin-docs/setup/">Figma’s Plugin API</a></li>
<li>Apple Devices’ <a target="_blank" href="https://www.ios-resolution.com">Resolution list</a></li>
</ul>
<p>If you haven’t already installed VSCode, Node.js, TypeScript, and Figma Desktop applications, I recommend you install them before you start developing. For this, you can follow Figma Plugin’s <a target="_blank" href="https://www.figma.com/plugin-docs/setup/">Setup Guide.</a></p>
<h3 id="heading-get-know-how">Get Know - How</h3>
<p>Before diving into the development of my product, I watched the Beforementioned tutorial and followed the steps in the tutorial. I learned how to develop a Figma plugin with that tutorial and while I was watching that, I was already thinking and planning about how I would develop my product.</p>
<h3 id="heading-implementation">Implementation</h3>
<p>I first understood the Figma API during the example projects. During the implementation, I was communicating with my product partner Ersin about this product. I shared what I learned with him and we discussed whether the plugin should have a UI or not. He suggested not having a user interface. </p>
<p>Then, I checked if I am able to get the frame’s size and yes, I am able to. So, I started with getting the frame’s size information and then save all of the device sizes which I get help from <a target="_blank" href="https://www.ios-resolution.com">iOS Resolution</a> I also, saved the information for the device model and the scale factor. The reason for saving the device information is just to note down which devices this plugin is going to support and see the same size devices clearly on the codebase. Therefore, in a few weeks people will be able to see if we support the new iPhone 14 - Hopefully, iPhone 14 will be released on September 7, 2022. The reason for saving the scale factor is, that we planned to divide the frame size by the scale factor to reach the logical size. Then, I implemented the way we were thinking. Developing a Figma Plugin requires knowledge of TypeScript. Since I know TypeScript I didn't get help from any resource at this point.Finally, it is done. We started it with iOS devices because Android has various devices of different sizes. We made the plugin open source by releasing the source code, so it is open to contribution. You may reach the source code from <a target="_blank" href="https://github.com/iremkaraoglu/Screenshot-Resizer">here.</a> </p>
<p>So, let’s watch the demo video and make it more visual. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=gOq0llL70po">https://www.youtube.com/watch?v=gOq0llL70po</a></div>
<p>Here, I took the screenshots from Xcode’s simulator and I created the same device’s prototype frames on Figma. I import the screenshots and they are bigger than they should be. So, I run the plugin and the size automatically changes according to the scale factor. I use this plugin to see if I met the design correctly. I take a screenshot from the app that I am developing and check it with the design. It made my job easier because now they have the same sizes. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662005109699/c7WaW68x8.jpg" alt="sigmund-TJxotQTUr8o-unsplash.jpg" />Source: Photo by <a target="_blank" href="https://unsplash.com/@sigmund?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Sigmund</a> on <a target="_blank" href="https://unsplash.com">Unsplash</a></p>
<p>Since my childhood, I have always loved creating things. I created this plugin in a day and in the following days just did some tiny improvements but it’s created in a day. I was feeling accomplished when I went to bed. I was also regretting why I procrastinated in the first place. So, If you would like to build something but procrastinate, start today. It is such a good feeling that I created the product that I use almost daily in my work and it is nice to see other people use it as well. I hope you liked this article, if you have any feedback about the plugin or this article, meet me in the comments below. If you enjoy my articles, please react or subscribe to my newsletter. Thanks for reading, happy coding!  👩🏻‍💻</p>
]]></content:encoded></item><item><title><![CDATA[What if I am stuck at some point during coding?]]></title><description><![CDATA[During the day, we as developers have often been stuck at some point and don't know what to do. It might be a bug, a problem during the development of a new feature, or an error that you don't know how to solve. We often experience that and it might ...]]></description><link>https://iremkaraoglu.com/what-if-i-am-stuck-at-some-point-during-coding</link><guid isPermaLink="true">https://iremkaraoglu.com/what-if-i-am-stuck-at-some-point-during-coding</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[#week2]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 24 Aug 2022 05:00:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ccpOiDUmeo0/upload/v1660666163857/_984yp-EN.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>During the day, we as developers have often been stuck at some point and don't know what to do. It might be a bug, a problem during the development of a new feature, or an error that you don't know how to solve. We often experience that and it might be frustrating sometimes. Today, I will share some tips that will help you solve your problem because it helps me to solve mine. Not every tip may be applicable to your case, but I hope you can find what suits you the best. Let's dive in!</p>
<h3 id="heading-writing">Writing</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661174662157/Fc5BN3QwM.png" alt="Untitled_Artwork 2 1.png" />
<em>An illustration by me 😊</em></p>
<p>The thoughts in our heads become clear when we write them down. Personally, when I am doing some calculation or figuring out a problem in an algorithm, I like using pen and paper while focusing on the problem, and writing everything down one by one. Also, a good alternative is to use a digital tablet for the same purpose - I like using Apple Notes or GoodNotes on the iPad. Another option might be using a whiteboard. It is also a convenient way to write and draw something since it has a larger area. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661085239186/WDaouRfnR.png" alt="thisisengineering-raeng-4dR9LmMzhT0-unsplash 1.png" />
Photo by <a target="_blank" href="https://unsplash.com/@thisisengineering?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">ThisisEngineering RAEng</a> on <a target="_blank" href="https://unsplash.com">Unsplash</a></p>
<h3 id="heading-stackoverflow">StackOverflow</h3>
<p>Stack Overflow is a question-and-answer website. If you're a developer, most probably you know that but I didn't want to take it for granted. StackOverflow is full of people that are having problems and giving solutions. If we search our problem/error clearly, we are more likely to find our answer. </p>
<p>For writing a better search query in StackOverflow, you may check <a target="_blank" href="https://www.informationninja.org/how-to-search-in-stack-overflow/">here</a></p>
<p>It's okay if we couldn't find the similar or the same problem as ours on StackOverflow, we are able to ask about our own problems in public. You may check a resource to how to write well our questions in <a target="_blank" href="https://www.dataschool.io/how-to-ask-for-coding-help-online/">here</a></p>
<h3 id="heading-friends">Friends</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661176159936/obSLAKlye.jpg" alt="mimi-thian-slWBjTGhREQ-unsplash-2.jpg" />
Photo by <a target="_blank" href="https://unsplash.com/@mimithian?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mimi Thian</a> on <a target="_blank" href="https://unsplash.com/">Unsplash</a></p>
<p>Another way to find a solution is basically to get help from our friends/coworkers. We can ask them to spare some time with us to debug our code or ask if they have ever experienced the same problem. It is a nice way to speak about the problem and solve it, also it bonds us and supports our communication. If we are in the same place with that person, I like to do pair programming. If we are in different places, having a call and screen sharing is also a good option. Also, we may consider asking our mentors/supervisors in the company as well.</p>
<h3 id="heading-rubber-duck-debugging">Rubber duck debugging</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661081644226/yLHQCOeYH.png" alt="DALL·E 2022-08-20 21.32 1.png" /></p>
<p>Generally, developers solve problems more easily when they speak about the problem out loud. It is a good method to talk about the problem and solve it. It is common and it's actually called Rubber duck debugging in <strong>The Pragmatic Programmer</strong> book. It is about talking to a rubber duck to solve the encountered problem while skimming through the code line-by-line. Talking through the process helps us to slow down and see our code's wider picture, which makes it simpler to identify issues because we speak more slowly than we think.</p>
<h3 id="heading-discord-servers">Discord servers</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661282643729/DUhdXoM2I.png" alt="Untitled_Artwork 5 1.png" />
<em>An illustration by me 😊</em></p>
<p>Discord is a platform for voice, text, and video chatting which is also suitable for communities. There are many discord servers for developers. I believe you may find some servers related to your domain. Me, as a mobile developer and more specifically an iOS developer, I am a member of various mobile development Discord servers both in Turkish and English. There are some channels for people to ask questions there. I sometimes ask questions on these active discord channels.</p>
<p>For example; one day, I had a problem with SpriteKit (SpriteKit is a 2D game development framework by Apple and there is not a big community for it). I wrote my question on one of the iOS development servers and I hoped someone would give me an answer. Luckily, I found someone that is interested in SpriteKit as well, he helped me to solve my problem. Also, I try to help people as well when I have free time. This is actually how the community grows. </p>
<p>I would love to share the iOS development discord server's link here but it was a server from students of a Udemy Course and the discord invitation is disabled. However, I may share another Discord server for iOS developers: https://discord.gg/69xeSDCf9y</p>
<p>For your particular domain, you can google relevant discord servers.</p>
<h3 id="heading-twitter-communities">Twitter Communities</h3>
<p>After the release of the Twitter Communities feature, people started to have their own communities. I am a member of some mobile developer communities both in Turkish or English like Discord. Similarly, I am able to ask any question, answer someone's question or read someone's problem and answer. I am an active user of Twitter and I always check it during the day. I rarely ask questions but when I do, I get answers immediately. It is such a relief that there is someone on this planet, who knows the answer to my problem and chooses to help me with it. </p>
<p>Unfortunately, because it's on Twitter, it doesn't allow a good service for sharing videos, having calls with people, or sharing the screen. I like using Twitter Communities because it's the platform that I use every day and I think people are more active on Twitter. It is important to choose the platform according to your needs. For example, if you would like to share a screen recording, Twitter may not be the best place for that. Because of the fact that Twitter compresses the videos you upload to reduce their bandwidth. Hence, making the uploaded video of your screen record really low-resolution one. That was one of the mistakes that I made back in the time. However, I still like to use Twitter Communities.</p>
<p>My favorite iOS developer community on Twitter is <a target="_blank" href="https://twitter.com/i/communities/1508884825905770496">this</a></p>
<p>My favorite React Native developer community on Twitter is <a target="_blank" href="https://twitter.com/i/communities/1509407040095068166">this</a></p>
<h3 id="heading-telegram-groups">Telegram Groups</h3>
<p>Telegram is again a chat application and another option for the communities. I am a member of some of them. Similarly, people ask their question and get answers from the members of the group. My favorite one is for iOS development and it's in Turkish. If you are interested you may join <a target="_blank" href="https://t.me/swiftakademi">here</a></p>
<h3 id="heading-similar-projects-on-github">Similar projects on GitHub</h3>
<p>GitHub is an online software development platform used for storing, tracking, and collaborating on software projects. If you are building something new, you can find similar projects to be inspired and learn from them. You can find answers to questions like: How do they make the structure? Which version of any third-party library do they use? Again, you need to search clearly to find these projects. To be honest, it is not an option that I choose every single day but I sometimes use this tip.</p>
<h3 id="heading-take-a-break-and-go-for-a-walk">Take a break and go for a walk</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661282710485/zGQ4Gp6W6.png" alt="Untitled_Artwork 7 1.png" />
<em>An illustration by me 😊</em></p>
<p>Up until here, we generally considered getting help from other people. This one doesn't require any people. It is a good practice to take a break when we are stuck on solving a problem. Go for a walk, go grab some coffee, or talk with your loved ones. That's what I try to do. Sometimes, I got stuck at some points and time passes without noticing it. It is nice to have a break and move my body. I recommend it to you as well. Just spend some time without looking at your screen, come back to the screen with a fresh mind, and try to solve your problem again. It is scientifically proven that walking improves creativity. For reference, I am attaching an article <a target="_blank" href="https://news.stanford.edu/2014/04/24/walking-vs-sitting-042414/">here</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1661176312842/_3DSppflN.jpg" alt="tai-bui-GrcMd1FvucY-unsplash.jpg" />
Photo by <a target="_blank" href="https://unsplash.com/@agforl24?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Tai Bui</a> on <a target="_blank" href="https://unsplash.com/">Unsplash</a></p>
<p>To conclude, there are various ways to solve our problems when we are stuck at some point. Today, we have covered rubber duck debugging, walking, writing, StackOverflow, Discord, Github, Twitter, and Telegram. Choosing the best one depends on the situation. Each one of them has pros and cons. We don't have to choose only one of the options beforementioned. We can keep trying new ones till we succeed. I hope these tips are helpful for you and you solve your problems easier than before. If you have another tip, please share it with me and other readers in the comments section below. Happy coding! 🐝</p>
]]></content:encoded></item><item><title><![CDATA[The most valuable feedback from my failed interview]]></title><description><![CDATA[As a software developer, I recommend my colleagues to have interviews with other companies to gain interview experiences, even though they are not looking for a job. It has some benefits for them and for their career. I think it is an underrated piec...]]></description><link>https://iremkaraoglu.com/the-most-valuable-feedback-from-my-failed-interview</link><guid isPermaLink="true">https://iremkaraoglu.com/the-most-valuable-feedback-from-my-failed-interview</guid><category><![CDATA[4articles4weeks]]></category><category><![CDATA[week1]]></category><category><![CDATA[interview]]></category><category><![CDATA[React Native]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 17 Aug 2022 06:13:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/UN4PadDppAU/upload/v1660632218478/0rNLIxm2F3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a software developer, I recommend my colleagues to have interviews with other companies to gain interview experiences, even though they are not looking for a job. It has some benefits for them and for their career. I think it is an underrated piece of advice and I would like to focus on these benefits.</p>
<p>By applying and having interviews;</p>
<ul>
<li>You become more comfortable in each interview because you are getting used to having interviews.</li>
<li>You get to know this position and the company better and your opinion about looking for a job may change for the positive.</li>
<li>You learn what the companies ask for and what they evaluate.</li>
<li>You may learn the salary range in different companies.</li>
<li>You get to know people and in the future, they can reach out to you.</li>
<li>You are given tasks and you learn something by doing them.</li>
<li>If you are lucky, even if it ends up with failure they give you feedback.</li>
</ul>
<p>Today, I would like to share with you the most valuable feedback that I have received from an unsuccessful interview.
A few years ago,  I applied for a position in a company and they assigned me a task. Even though I couldn't finish the whole task due to it being too hard for me, I still submitted the project and had a technical interview with the CTO and the Tech Lead of that company. Two days later, I received an e-mail from the CTO and it was a reject e-mail but with more feedback than I expected.</p>
<p>First of all, he said that the project that I sent was insufficient - I was expecting to hear that because I couldn't finish it 🤷‍♀️ I thought that I would still get some points for trying to come up with a solution even if I couldn't finish it completely, just like in college but as far as I experienced, things don't work that way with companies. They mostly care if you managed to complete it or not. Also, he pointed out some really good points to be improved upon. Let's go over each one of them.</p>
<h3 id="heading-improve-yourself-outside-of-work">Improve yourself outside of work.</h3>
<p>He said, "Improve yourself outside of work because the difference between good developers and great ones is the ones who improve themselves outside of the work, create personal projects, etc."
It is a very nice saying and I loved it. After that, I became more motivated to create my personal projects and I wrote blog posts about them.</p>
<h3 id="heading-keep-up-to-date-with-the-trending-libraries-and-technologies">Keep up-to-date with the trending libraries and technologies.</h3>
<p>I wasn't following the trends and what is new. I was hearing some stuff but I wasn't actually following and reading in-depth. I am better at following what's new now but I can't say I am 100% up to date with new technologies. I can still improve this point.</p>
<h3 id="heading-read-and-contribute-to-open-source-projects">Read and contribute to open-source projects.</h3>
<p>Just like this one, I received another piece of advice from someone "read others' code as much as you can and see what they are coding" I am now reading more of it, contributing to open-source with my blog posts and public repositories but haven't contributed to any third party library's repository yet but I think it's something and I am better than how I was.</p>
<h3 id="heading-read-the-documentation-and-create-personal-projects">Read the documentation and create personal projects.</h3>
<p>He said "Read the documentation and create personal projects with React-Native, React, Unit-Testing, JavaScript" Back when he gave that advice, I was a React Native Developer, however, I decided to make a change in my career path and chose to follow the path of iOS development with Swift. So, I am not following that piece of advice on those technologies but I am trying to read the Apple documentation and developing personal projects in Swift.</p>
<h3 id="heading-understand-why-a-piece-of-code-is-in-the-codebase">Understand why a piece of code is in the codebase.</h3>
<p>He said "Understand why a piece of code is in the codebase. Go deep into the logic and structure." This is still a point for me to improve on. I just focus on my task to do on a project. I don't investigate the codebase and understand why that code block is there, what's the purpose of that function etc. Also, unfortunately, when I'm stuck at some point I copy-paste the solution from StackOverflow but don't think about why that code block is the answer, just focus on solving it and don't think about "how". So, this is another point that I still should improve for myself.</p>
<p>To conclude, applying for companies is OK. Being rejected is OK. You learn some stuff and get experiences during these interviews. This was my unforgettable failed interview with valuable feedback and I am glad that someone told me these things. By writing this article, It was also a nice feeling that I am not the same person as I was. I have improved and I will continue to. I hope these pieces of advice help you in your career as well. Hope to see you in the next article, take care!</p>
]]></content:encoded></item><item><title><![CDATA[How to add SwiftUI to a UIKit project]]></title><description><![CDATA[The UIKit framework was introduced by Apple in 2008 along with iPhone OS2. More than 10 years later, in 2019, Apple introduced SwiftUI with the intent of saving developers time.
The SwiftUI framework supports declarative programming, meaning it requi...]]></description><link>https://iremkaraoglu.com/how-to-add-swiftui-to-a-uikit-project</link><guid isPermaLink="true">https://iremkaraoglu.com/how-to-add-swiftui-to-a-uikit-project</guid><category><![CDATA[Swift]]></category><category><![CDATA[SwiftUI]]></category><category><![CDATA[UIkit]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 15:59:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/p-xSl33Wxyc/upload/v1657727396717/s_dyo8XpO.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a target="_blank" href="https://developer.apple.com/documentation/uikit">UIKit</a> framework was introduced by Apple in 2008 along with iPhone OS2. More than 10 years later, in 2019, Apple introduced <a target="_blank" href="https://developer.apple.com/xcode/swiftui/">SwiftUI</a> with the intent of saving developers time.</p>
<p>The SwiftUI framework supports declarative programming, meaning it requires less code. In addition, it easily manages themes, offers a live preview, uses Canvas instead of Interface Builder, and is less prone to crashing.</p>
<p>So, SwiftUI vs. UIKit — is one better than the other? Well, despite its many advantages, companies have been slow to adopt the use of SwiftUI in their iOS apps. Some organizations are willing to try SwiftUI for a new project, but many are hesitant to migrate existing UIKit projects to this framework.</p>
<p>SwiftUI requires iOS 13 or later, so it’s not compatible with apps developed using an older iOS version. Also, transferring large apps to a different framework is time consuming and could hamper developer bandwidth.</p>
<p>This tutorial will demonstrate how to add a SwiftUI screen to a UIKit project. This SwiftUI UIKit integration solution can provide the experience of using SwiftUI without creating a new app from scratch. Adding SwiftUI to an existing UIKit project will also make it easier for us to migrate the app to SwiftUI in the future.</p>
<p><strong>Final project: UIKit app with SwiftUI screen</strong></p>
<p>Here’s the final version of the app that we’ll build in this tutorial:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/Sz0bDK-ghDs?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p>We’ll create a SwiftUI screen within a UIKit app, and then add functionality to allow navigation between the SwiftUI screen and the UIKit screen.</p>
<h2 id="heading-creating-the-ios-project-with-storyboard-interface">Creating the iOS project with Storyboard interface</h2>
<p>Let’s start by creating the UIKit project.</p>
<p>First, we’ll select <strong>App</strong> from the <strong>iOS</strong> tab:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718127514/WZSeF1wDJj.png" alt="App Selection" /></p>
<p>Then, we’ll select <strong>Storyboard</strong> from the <strong>Interface</strong> dropdown:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718128886/aXSO1CDki.png" alt="Storyboard Selection" /></p>
<p>For this tutorial, I‘ll remove Storyboard and will build the app’s UI programmatically. Here’s an article that you may find helpful for learning more about <a target="_blank" href="https://blog.logrocket.com/storyboard-vs-programmatically-ios-ui-design/">creating an iOS app’s UI with Storyboard vs. programmatically</a>.</p>
<p>Check this GitHub <a target="_blank" href="https://github.com/iremkaraoglu/iOS_SwiftUI_in_UIKit_Project/commit/531177cda292b591b81836fb33288b6d24d654f2">commit</a> to get the changes necessary to remove Storyboard from your sample project and specify the navigation controller as a root view controller.</p>
<h2 id="heading-creating-the-swiftui-screen">Creating the SwiftUI screen</h2>
<p>Now, let’s create a SwiftUI View file.</p>
<p>Create a new file in SwiftUI. Select <strong>iOS</strong> for the platform and <strong>SwiftUI View</strong> for the user interface:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718130719/Hy_XtHaLw.png" alt="SwiftUI View" /></p>
<p>Next, give the file a name, and click <strong>Create:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718132334/_oIvQ47iU.png" alt="Create Button" /></p>
<p>Now, you should see the default SwiftUI View file with text “Hello, World!”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718133932/PzfKzONcS.png" alt="App Preview With &quot;Hello World!&quot;" /></p>
<p>Next, let’s add a simple UI design consisting of some text and a button:</p>
<pre><code><span class="hljs-selector-tag">struct</span> <span class="hljs-selector-tag">SwiftUIView</span>: <span class="hljs-selector-tag">View</span> {
    <span class="hljs-selector-tag">var</span> <span class="hljs-selector-tag">body</span>: <span class="hljs-selector-tag">some</span> <span class="hljs-selector-tag">View</span> {
        <span class="hljs-selector-tag">VStack</span> {
            <span class="hljs-selector-tag">HStack</span> {
                <span class="hljs-selector-tag">Text</span>(<span class="hljs-string">"SwiftUI Screen"</span>)
                    <span class="hljs-selector-class">.bold</span>()
                    <span class="hljs-selector-class">.font</span>(.system(<span class="hljs-attribute">size</span>: <span class="hljs-number">21.0</span>))
            }
            <span class="hljs-selector-tag">Spacer</span>()
                <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: <span class="hljs-number">1</span>, <span class="hljs-attribute">height</span>: <span class="hljs-number">74</span>, <span class="hljs-attribute">alignment</span>: .bottom)
            <span class="hljs-selector-tag">VStack</span>(<span class="hljs-attribute">alignment</span>: .center){
                <span class="hljs-selector-tag">Button</span>(<span class="hljs-attribute">action</span>: {
                }) {
                    <span class="hljs-selector-tag">Text</span>(<span class="hljs-string">"Navigate to UIKit Screen"</span>)
                        <span class="hljs-selector-class">.font</span>(.system(<span class="hljs-attribute">size</span>: <span class="hljs-number">21.0</span>))
                        <span class="hljs-selector-class">.bold</span>()
                        <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: UIScreen.main.bounds.width, <span class="hljs-attribute">height</span>: <span class="hljs-number">10</span>, <span class="hljs-attribute">alignment</span>: .center)
                }
            }
            <span class="hljs-selector-tag">Spacer</span>()
                <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: <span class="hljs-number">2</span>, <span class="hljs-attribute">height</span>: <span class="hljs-number">105</span>, <span class="hljs-attribute">alignment</span>: .bottom)
        }<span class="hljs-selector-class">.navigationBarHidden</span>(true)
    }
}
</code></pre><p>After updating the SwiftUI screen, we can see the live preview on the canvas. Our new SwiftUI screen has a label, SwiftUI Screen, and a button to navigate to the UIKit screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718135395/6q8Dzq--9.png" alt="Updated SwiftUI Screen" /></p>
<h2 id="heading-creating-the-uikit-view">Creating the UIKit view</h2>
<p>Now, let’s work with the UIKit’s <code>ViewController</code> to create a basic user interface. It will include a label with text “UIKit screen” and a button to navigate to the SwiftUI screen.</p>
<pre><code><span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">viewDidLoad</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">super</span>.viewDidLoad()

        view.backgroundColor = .white

        <span class="hljs-keyword">let</span> label = <span class="hljs-type">UILabel</span>()
        label.text = <span class="hljs-string">"UIKit Screen"</span>
        label.textColor = .black
        label.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
        label.font = .boldSystemFont(ofSize: <span class="hljs-number">21</span>)
        view.addSubview(label)

        <span class="hljs-keyword">let</span> button = <span class="hljs-type">UIButton</span>()
        button.setTitleColor(.blue, <span class="hljs-keyword">for</span>: .normal)
        button.setTitle(<span class="hljs-string">"Navigate to SwiftUI Screen"</span>, <span class="hljs-keyword">for</span>: .normal)
        button.titleLabel?.textAlignment = .center
        button.translatesAutoresizingMaskIntoConstraints = <span class="hljs-literal">false</span>
        button.addTarget(<span class="hljs-keyword">self</span>, action: #selector(openSwiftUIScreen), <span class="hljs-keyword">for</span>: .touchUpInside)
        button.titleLabel?.font = .boldSystemFont(ofSize: <span class="hljs-number">21</span>)
        view.addSubview(button)

        <span class="hljs-type">NSLayoutConstraint</span>.activate(\[
            button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: <span class="hljs-number">64</span>)\])
    }
</code></pre><h2 id="heading-displaying-the-swiftui-screen">Displaying the SwiftUI screen</h2>
<p>We need a way to present our SwiftUI screen. Right now, our application opens with the UIKit screen but doesn’t navigate to the SwiftUI screen.</p>
<p>To set up the functionality to navigate between the UIKit screen and the SwiftUI screen, we’ll use the UIKit’s <code>UIHostingController</code> class. The <code>UIHostingController</code> is a UIKit view controller that manages a SwiftUI view hierarchy.</p>
<p>To create <code>UIHostingController</code>, ensure that you import SwiftUI at the top of the code module.</p>
<p>Now, let’s open the <code>ViewController.swift</code> file and create a function to navigate to the SwiftUI screen:</p>
<pre><code><span class="hljs-meta">@objc</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">openSwiftUIScreen</span><span class="hljs-params">()</span></span> {
        <span class="hljs-keyword">let</span> swiftUIViewController = <span class="hljs-type">UIHostingController</span>(rootView: <span class="hljs-type">SwiftUIView</span>())
        <span class="hljs-keyword">self</span>.navigationController?.pushViewController(swiftUIViewController, animated: <span class="hljs-literal">true</span>)
    }
</code></pre><p>Inside this function, we create a <code>UIHostingController</code> by passing our SwiftUI screen as a root view and also passing the main navigation controller to that. <code>UIHostingController</code> is a UIKit view controller and we push that view controller to our navigation controller.</p>
<p>Next, we need to add a target for our button to fire the <code>openSwiftUIScreen</code> function:</p>
<pre><code><span class="hljs-selector-tag">button</span><span class="hljs-selector-class">.addTarget</span>(self, <span class="hljs-attribute">action</span>: #selector(openSwiftUIScreen), <span class="hljs-attribute">for</span>: .touchUpInside)
</code></pre><p>Now, we can navigate from the UIKit screen like in the demo below. Notice that we’re not able to go back from the SwiftUI screen. This is because we didn’t give any action to our button.</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/DXTCvNzOP14?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p>To go back from the SwiftUI screen, we need to add a <code>UINavigationController</code> and pass our root navigation controller to the SwiftUI screen.</p>
<p>We pushed to the SwiftUI screen before using the <code>UIHostingController</code>. Now, we will use the <code>UINavigationController</code> to pop back to the UIKit screen.</p>
<pre><code><span class="hljs-selector-tag">struct</span> <span class="hljs-selector-tag">SwiftUIView</span>: <span class="hljs-selector-tag">View</span> {

    <span class="hljs-selector-tag">weak</span> <span class="hljs-selector-tag">var</span> <span class="hljs-selector-tag">navigationController</span>: <span class="hljs-selector-tag">UINavigationController</span>?

    <span class="hljs-selector-tag">var</span> <span class="hljs-selector-tag">body</span>: <span class="hljs-selector-tag">some</span> <span class="hljs-selector-tag">View</span> {
        <span class="hljs-selector-tag">VStack</span> {
            <span class="hljs-selector-tag">HStack</span> {
                <span class="hljs-selector-tag">Text</span>(<span class="hljs-string">"SwiftUI Screen"</span>)
                    <span class="hljs-selector-class">.bold</span>()
                    <span class="hljs-selector-class">.font</span>(.system(<span class="hljs-attribute">size</span>: <span class="hljs-number">21.0</span>))
            }
            <span class="hljs-selector-tag">Spacer</span>()
                <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: <span class="hljs-number">1</span>, <span class="hljs-attribute">height</span>: <span class="hljs-number">74</span>, <span class="hljs-attribute">alignment</span>: .bottom)
            <span class="hljs-selector-tag">VStack</span>(<span class="hljs-attribute">alignment</span>: .center){
                <span class="hljs-selector-tag">Button</span>(<span class="hljs-attribute">action</span>: {
                    <span class="hljs-selector-tag">navigationController</span>?<span class="hljs-selector-class">.popViewController</span>(<span class="hljs-attribute">animated</span>: true)
                }) {
                    <span class="hljs-selector-tag">Text</span>(<span class="hljs-string">"Navigate to UIKit Screen"</span>)
                        <span class="hljs-selector-class">.font</span>(.system(<span class="hljs-attribute">size</span>: <span class="hljs-number">21.0</span>))
                        <span class="hljs-selector-class">.bold</span>()
                        <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: UIScreen.main.bounds.width, <span class="hljs-attribute">height</span>: <span class="hljs-number">10</span>, <span class="hljs-attribute">alignment</span>: .center)
                }
            }
            <span class="hljs-selector-tag">Spacer</span>()
                <span class="hljs-selector-class">.frame</span>(<span class="hljs-attribute">width</span>: <span class="hljs-number">2</span>, <span class="hljs-attribute">height</span>: <span class="hljs-number">105</span>, <span class="hljs-attribute">alignment</span>: .bottom)
        }<span class="hljs-selector-class">.navigationBarHidden</span>(true)
    }
}
</code></pre><p>Next, let’s update our function in <code>ViewController</code>:</p>
<pre><code>@objc func openSwiftUIScreen() {
        let swiftUIViewController <span class="hljs-operator">=</span> UIHostingController(rootView: SwiftUIView(navigationController: <span class="hljs-built_in">self</span>.navigationController))
        <span class="hljs-built_in">self</span>.navigationController?.pushViewController(swiftUIViewController, animated: <span class="hljs-literal">true</span>)
    }
</code></pre><p>With this update, we’re able to navigate from the UIKit screen to the SwiftUI screen and then back to the UIKit screen.</p>
<p>Here’s the final version of our application:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/Sz0bDK-ghDs?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we demonstrated how to integrate SwiftUI into a UIKit project. The <a target="_blank" href="https://iosdevsurvey.com/2020/08-swiftui/">2021 iOS Developer Community Survey</a> indicated high levels of interest in SwiftUI. Given SwiftUI’s growing popularity among developers but slow adoption rate for organizations, it’s important to understand that it’s possible to use both SwiftUI and UIKit in a single application.</p>
<p>I hope you enjoyed this article. You can share your valuable feedback or questions in the comments section or via hi@iremkaraoglu.com. See you in the next article! Take care!</p>
<p>The post <a target="_blank" href="https://blog.logrocket.com/how-add-swiftui-uikit-project/">How to add SwiftUI to a UIKit project</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Easily handle JSON in Swift with SwiftyJSON]]></title><description><![CDATA[Handling data is a common task for frontend developers, and the data is very often in JSON format. SwiftyJSON is an open source third-party library that is useful for handling JSON data easily in Swift. As of this writing, the package has 21K+ stars ...]]></description><link>https://iremkaraoglu.com/easily-handle-json-in-swift-with-swiftyjson</link><guid isPermaLink="true">https://iremkaraoglu.com/easily-handle-json-in-swift-with-swiftyjson</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[SwiftyJSON]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 15:37:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/a2NRu2Wxa2o/upload/v1657726417599/xgHY4CaDT.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Handling data is a common task for frontend developers, and the data is very often in JSON format. <a target="_blank" href="https://github.com/SwiftyJSON/SwiftyJSON">SwiftyJSON</a> is an open source third-party library that is useful for handling JSON data easily in Swift. As of this writing, the package has 21K+ stars on GitHub and has been maintained since its initial release in 2014. It supports the latest versions of Swift, Xcode, and iOS. So far, it has met all my needs.</p>
<p>In this article, we’ll review how to handle JSON data easily in Swift with SwiftyJSON. We’ll use a demo project with a macOS command line interface to walk through the tutorial.</p>
<p>For the examples used in this article, we’ll use Swift v5, Xcode v13.2.1, and SwiftyJSON v5.0.1.</p>
<p>Let’s get started!</p>
<h2 id="heading-creating-a-macos-cli">Creating a macOS CLI</h2>
<p>Since a user interface is not important for this project, we’ll create and use a macOS command line tool. To create a CLI for macOS, open Xcode and click on <strong>Create a new Xcode project</strong>. Next, under macOS, select <strong>Command Line Tool</strong>, then click <strong>Next</strong>, and follow the remaining instructions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718140936/v-63xMYHC.png" alt="Command Line Tool" /></p>
<h2 id="heading-setting-up-the-demo-project">Setting up the demo project</h2>
<p>I like Pokémon, so I’ve decided to use it as the project’s topic. In this project, we’ll use <a target="_blank" href="https://pokeapi.co/">the RESTful Pokemon API</a>. We’ll request data for the character, Charmander, by fetching this JSON: <a target="_blank" href="https://pokeapi.co/api/v2/pokemon/charmander">https://pokeapi.co/api/v2/pokemon/charmander</a>.</p>
<p>This article will focus on handling JSON, so we’ll skip over the process of requesting the JSON data.</p>
<p>For this demo, I’ve used the macOS <a target="_blank" href="https://developer.apple.com/documentation/foundation/urlsession">URLSession</a> to handle the HTTP requests, but you may also use <a target="_blank" href="https://github.com/Alamofire/Alamofire">Alamofire</a> or <a target="_blank" href="https://github.com/Moya/moya.github.io">Moya</a>. In addition, you can always access the code in my <a target="_blank" href="https://github.com/iremkaraoglu/iOS-HandlingJSON-withSwiftyJSON">GitHub</a> <a target="_blank" href="https://github.com/iremkaraoglu/iOS-HandlingJSON-withSwiftyJSON">repository</a>. After we get the data, we’ll request some of Charmander’s attributes (for example, name, abilities, and type) and then we’ll display them in the terminal output.</p>
<p>The terminal output will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718142522/dpySt21CE.png" alt="Terminal Output" /></p>
<p>Let’s get started.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718143691/mHbNoBDgJf.jpeg" alt="Charmander Plush on Bench" /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@akin?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Akin Cakiner</a> on <a target="_blank" href="https://unsplash.com/s/photos/charmander?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash.</a></p>
<h2 id="heading-adding-swiftyjson-to-the-demo-project">Adding SwiftyJSON to the demo project</h2>
<p>To use a third-party library, we need to import that package in our project. Therefore, our first step is to add the SwiftyJSON package to our project; we’ll use the <a target="_blank" href="https://github.com/apple/swift-package-manager">Swift Package Manager</a>.</p>
<p>Here’s our path: Xcode &gt; ( Xcode project name) &gt; Targets &gt; (Xcode project name).</p>
<p>In the General tab, under the Frameworks and Libraries dropdown, we click on <strong>+</strong> and select <strong>Add package dependency</strong>. Then, we enter the package Git URL: <a target="_blank" href="https://github.com/SwiftyJSON/SwiftyJSON.git">https://github.com/SwiftyJSON/SwiftyJSON.git</a>.</p>
<p>After the package is successfully added, we’ll see SwiftyJSON listed under Framework, as well as under Package Dependencies in the Project Navigator:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718144955/DLEa23mq7.png" alt="SwiftyJSON Under Framework" /></p>
<h2 id="heading-using-swiftyjson-to-parse-json-in-swift">Using SwiftyJSON to parse JSON in Swift</h2>
<p>Now, we’re ready to write some code. To start, we’ll use a snippet from our JSON data:</p>
<pre><code><span class="hljs-string">"name"</span>: <span class="hljs-string">"charmander"</span>,
<span class="hljs-string">"order"</span>: <span class="hljs-number">5</span>,
<span class="hljs-string">"past\_types"</span>: \[\],
<span class="hljs-keyword">...</span>
</code></pre><p>We’ll create a JSON object that includes the <code>name</code> attribute of the data. Then, we’ll create a function to get the <code>name</code> attribute so that we can access it:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getName</span><span class="hljs-params">(data: Data)</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> json = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSON</span>(data: data) {
        <span class="hljs-keyword">let</span> name = json\[<span class="hljs-string">"name"</span>\].string ?? <span class="hljs-string">"N/A"</span>
        <span class="hljs-built_in">print</span>(<span class="hljs-string">"Name: \\(name)"</span>)
    }
}
</code></pre><p>When we call the <code>getName</code> function, we get the following output:</p>
<pre><code><span class="hljs-attribute">Name</span>: **charmander**

<span class="sql">Now, let’s work <span class="hljs-keyword">with</span> the <span class="hljs-keyword">nested</span> <span class="hljs-keyword">JSON</span> <span class="hljs-keyword">from</span> our Charmander <span class="hljs-keyword">HTTP</span> request:

<span class="hljs-string">"abilities"</span>: \[
    {
      <span class="hljs-string">"ability"</span>: {
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"blaze"</span>,
        <span class="hljs-string">"url"</span>: <span class="hljs-string">"&lt;https://pokeapi.co/api/v2/ability/66/&gt;"</span>
      },
      <span class="hljs-string">"is\_hidden"</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-string">"slot"</span>: <span class="hljs-number">1</span>
    },
    {
      <span class="hljs-string">"ability"</span>: {
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"solar-power"</span>,
        <span class="hljs-string">"url"</span>: <span class="hljs-string">"&lt;https://pokeapi.co/api/v2/ability/94/&gt;"</span>
      },
      <span class="hljs-string">"is\_hidden"</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-string">"slot"</span>: <span class="hljs-number">3</span>
    }
  \], 
{...}</span>
</code></pre><p>We’ll create a function to get the <code>abilities</code> attribute from the Charmander data. Previously, we created a JSON object, but now we have an array of objects. We’ll need to trace through the <code>abilities</code> array and get the <code>name</code> attribute of each <code>ability</code>.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getAbilities</span><span class="hljs-params">(data: Data)</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> json = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSON</span>(data: data) {
        <span class="hljs-keyword">for</span> (\<span class="hljs-number">_</span>, abilities) <span class="hljs-keyword">in</span> json\[<span class="hljs-string">"abilities"</span>\] {
            <span class="hljs-keyword">let</span> ability = abilities\\\[<span class="hljs-string">"ability"</span>\\\]\[<span class="hljs-string">"name"</span>\].string ?? <span class="hljs-string">"N/A"</span>
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"Ability: \\(ability)"</span>)
        }
    }
}
</code></pre><p>When we call the <code>getAbilities</code> function, we get the following output:</p>
<pre><code>Ability: <span class="hljs-operator">*</span><span class="hljs-operator">*</span>blaze<span class="hljs-operator">*</span><span class="hljs-operator">*</span>

Ability: <span class="hljs-operator">*</span><span class="hljs-operator">*</span>solar<span class="hljs-operator">-</span>power<span class="hljs-operator">*</span><span class="hljs-operator">*</span>
</code></pre><p>Similar to <code>abilities</code>, we also have the <code>types</code> attribute. Then, inside the object, we have a <code>type</code> object with a <code>name</code> attribute. We can see both attributes in the below JSON snippet:</p>
<pre><code><span class="hljs-string">"types"</span>: \[
    {
      <span class="hljs-string">"slot"</span>: <span class="hljs-number">1</span>,
      <span class="hljs-string">"type"</span>: {
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"fire"</span>,
        <span class="hljs-string">"url"</span>: <span class="hljs-string">"https://pokeapi.co/api/v2/type/10/"</span>
      }
    }
  \]
</code></pre><p>Now, we’ll trace through the <code>types</code> array and get the <code>name</code> attribute of each <code>type</code>.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">getType</span><span class="hljs-params">(data: Data)</span></span> {
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> json = <span class="hljs-keyword">try</span>? <span class="hljs-type">JSON</span>(data: data) {
        <span class="hljs-keyword">for</span> (\<span class="hljs-number">_</span>, types) <span class="hljs-keyword">in</span> json\[<span class="hljs-string">"types"</span>\] {
            <span class="hljs-keyword">let</span> type = types\\\[<span class="hljs-string">"type"</span>\\\]\[<span class="hljs-string">"name"</span>\].string ?? <span class="hljs-string">"N/A"</span>
            <span class="hljs-built_in">print</span>(<span class="hljs-string">"Type: \\(type)"</span>)
        }
    }
}
</code></pre><p>When we call the <code>getType</code> function, we get the following output:</p>
<pre><code>Type: <span class="hljs-operator">*</span><span class="hljs-operator">*</span>fire<span class="hljs-operator">*</span><span class="hljs-operator">*</span>
</code></pre><h2 id="heading-addressing-type-issues-in-swift">Addressing type issues in Swift</h2>
<p>In Swift, we have to use explicit typing. The benefit of this is that we are less likely to make mistakes. The downside is that it is not very flexible.</p>
<p>For example, when we fetch JSON data, we create the attributes by declaring their data type. If the data type changes from the server side, we’ll be unable to parse the JSON data and the app will crash. Fortunately, SwiftyJSON helps us address this issue.</p>
<p>Let’s look at an example.</p>
<p>In the below code snippet, we specify that the data type is a <code>string</code>. We could also specify that it must be an integer; the point here is that the code indicates it must be of the type we are specifying.</p>
<pre><code>let ability <span class="hljs-operator">=</span> abilities\\\[<span class="hljs-string">"ability"</span>\\\]\[<span class="hljs-string">"name"</span>\].string!
</code></pre><p>In this example, as long as the data type actually is a <code>string</code>, everything is fine. But if the data type changes, the value becomes nil and the app will crash.</p>
<p>Now, let’s look at the same example, but this time we’ll use a <code>nil</code>-coalescing operator to accomodate any possible changes in data type:</p>
<pre><code>let ability <span class="hljs-operator">=</span> abilities\\\[<span class="hljs-string">"ability"</span>\\\]\[<span class="hljs-string">"name"</span>\].string ?? <span class="hljs-string">"N/A"</span>
</code></pre><p>In the above snippet, we check to see if the data type is a <code>string</code>. If it is not a <code>string</code>, the value “N/A” is returned. The app does not crash. Of course, you are not limited to “N/A”, you may use any designation you like.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we reviewed how to handle JSON in Swift with SwiftyJSON and discussed how to handle type issues. We walked through the article examples using a demo with a macOS command line interface.</p>
<p>I hope you’ve enjoyed this article. Go to <a target="_blank" href="https://github.com/iremkaraoglu/iOS-HandlingJSON-withSwiftyJSON">GitHub</a> to check out the sample project that I made for this article. Feel free to reach out to me at hi@iremkaraoglu.com or in the below comment section. I appreciate your valuable feedback. Take care!</p>
<p>The post <a target="_blank" href="https://blog.logrocket.com/easily-handle-json-swift-swiftyjson/">Easily handle JSON in Swift with SwiftyJSON</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Storyboard vs. programmatically for iOS app UI design]]></title><description><![CDATA[With the UIKit framework, there are two options available for creating the UI for iOS apps: Storyboard and programmatically. Both methods offer several advantages.
When I first started learning to create user interfaces for iOS, I wasn’t sure how to ...]]></description><link>https://iremkaraoglu.com/storyboard-vs-programmatically-for-ios-app-ui-design</link><guid isPermaLink="true">https://iremkaraoglu.com/storyboard-vs-programmatically-for-ios-app-ui-design</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Mobile Development]]></category><category><![CDATA[storyboard]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 15:23:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/tze1kKj7Lgg/upload/v1657725756986/Im_bUZlgah.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>With the UIKit framework, there are two options available for creating the UI for iOS apps: Storyboard and programmatically. Both methods offer several advantages.</p>
<p>When I first started learning to create user interfaces for iOS, I wasn’t sure how to decide between using Storyboard and coding the UI programmatically. However, after much research and hands-on development experience, I’m ready to share what I’ve learned and also offer some insights and opinions.</p>
<p>In this article, we’ll compare the pros and cons of creating UI for iOS with Storyboard vs. programmatically. We’ll demonstrate coding the same UI using both methods, and we’ll also discuss which method is preferable for certain circumstances.</p>
<p>Let’s dive in!</p>
<h2 id="heading-designing-ios-ui-with-storyboard">Designing iOS UI with Storyboard</h2>
<p>Storyboard allows us to add UI elements to the screen by simply dragging and dropping. To create a project in UIKit with Storyboard, we select <strong>Storyboard</strong> in the Xcode project <strong>Interface</strong> dropdown:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718150075/TA3NtU1AX.png" alt="Storyboard Xcode Project" /></p>
<p>Using the Interface Builder, we add UI elements to the screen, as shown in the below video. We click on the <strong>+</strong> button, select an object, and then drag and drop it to the desired location on the screen.</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/G8F02mxfiyE?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<h3 id="heading-creating-a-sample-ui-with-storyboard">Creating a sample UI with Storyboard</h3>
<p>Let’s create a sample project called <code>Koala-Storyboard</code>. As shown in the below video, we’ll add a koala image and the text “Koala” in the Interface Builder:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/HyhC_9vUFd4?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p>Storyboard enables us to add objects to a UI in just seconds. We simply place the object in the desired location and it’s done. However, it’s important to understand that this method does not automatically result in a responsive design.</p>
<p>When we create a UI on a sample iOS device canvas and then build the app on a different device, the end result may have a slightly different appearance.</p>
<p>Here’s an example that illustrates this issue:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718151635/ex4gghatJ.png" alt="Storyboard Different UI" /></p>
<p>This UI was created on an iPhone 11 canvas (right image) but looks different when run on iPhone SE, 2nd generation (left image).</p>
<p>In order to create a UI that looks the same on all devices, we must add relationship constraints for the different UI elements and use the Interface Builder’s Auto Layout feature. Auto Layout automatically adjusts a UI’s layout to account for device screen size, as well as external changes like a user rotating a device or resizing a window.</p>
<p>First, we’ll add some constraints to have the same UI for different devices. We’ll resize the image and position it to the center of the screen:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/5NUdTz4E9iU?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p>Next, we’ll position the “I love koalas” text 64px below the image:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/7ZTiMya32Dg?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p>This process enables us to build the same UI for different devices such as iPhone 11, iPhone 8, and iPhone 13 Pro Max. Each device displays the image centered on the screen with text 64px below the image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718153241/3LNVPZNb5.png" alt="Storyboard UI Auto Layout" /></p>
<p>App UI built in Storyboard, using the Interface Builder’s Auto Layout feature.</p>
<p>Although Storyboard does not automatically generate a responsive design, it can be a very useful method for prototyping. To create a demo or prototype, we simply select the appropriate device canvas.</p>
<h3 id="heading-merging-conflicts-in-storyboard">Merging conflicts in Storyboard</h3>
<p>Merge conflicts are probably the most significant downside to Storyboard. Merge conflicts can occur easily, and because Storyboard is actually an XML file, it can be difficult to debug and resolve the conflict.</p>
<p>Let’s review a Storyboard merge conflict scenario:</p>
<p>Assume we have two developers: Developer A and Developer B. Both are working on a particular screen. Each developer has their own branches that are created from the main branch.</p>
<p>During development, the following sequence of events occurs:</p>
<ol>
<li>Developer A moves the <code>imageView</code> (in this case, the koala image) up by a certain number of pixels</li>
<li>Developer B adds a button and moves the <code>imageView</code> down by a certain number of pixels</li>
<li>Developer B’s branch is merged to the main branch</li>
</ol>
<p>After these events, Developer A’s branch is behind the main branch, and their branch’s codebase is outdated. Developer A tries to merge their branch with the main branch, but there is a merge conflict:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718154895/lrW5qL8wP.png" alt="Storyboard VS Code Merge Error Code" /></p>
<p>Merge conflict shown in VS Code.</p>
<p>We can see the conflict in the VS Code. The updated stream (shown in green) represents Developer B’s changes. The stashed changes (shown in blue) represent Developer A’s changes.</p>
<p>There are three options for attempting to resolve the conflict:</p>
<ol>
<li>Accept the most recent changes (Developer A’s changes) and lose the updated stream (Developer B’s changes)</li>
<li>Accept the updated stream (Developer B’s changes) only</li>
<li>Accept all changed lines, without losing a single change</li>
</ol>
<p>Accepting every change (option 3) may initially seem like the best option, but first, let’s take a closer look at the code.</p>
<p>One developer moved the <code>imageView</code> up, and the other moved it down. The file now consists of two <code>imageViews</code> (on lines 26 and 48). Since both <code>imageViews</code> have the same ID, we’re seeing an error when we open Xcode:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718156533/-GAwUNLkB.png" alt="Storyboard Xcode Error Message" /></p>
<p>Merge conflict error in Xcode.</p>
<p>Merge conflicts are not uncommon in development, and they happen fairly frequently in Xcode. Xcode adds some references and IDs to the XML file. So, as a UI becomes more elaborate, the XML file becomes more complex. Even just two developers working on the same UIKit Storyboard project can face a merge conflict that will take some time and attention to resolve.</p>
<h3 id="heading-pros-and-cons-of-using-storyboard-to-design-ui-for-ios">Pros and cons of using Storyboard to design UI for iOS</h3>
<p>Here’s a summary of Storyboard’s pros and cons:</p>
<h4 id="heading-pros">PROS</h4>
<p>Easy option for adding UI elements to the screen (drag and drop)</p>
<p>Easy option for prototype creation (static UI)</p>
<p>Provides a visual representation of all screens on Xcode</p>
<h4 id="heading-cons">CONS</h4>
<p>Difficult code review (XML file)</p>
<p>Requires constraints for auto layout (responsiveness)</p>
<p>Hard to resolve merge conflicts (XML file)</p>
<p>Difficult for more than one developer to work on the same screen</p>
<p>Code is not searchable</p>
<p>Performance (app load time) can be impacted if Storyboard is not well organized</p>
<p>Does not support animations (any animations must be added programmatically)</p>
<p>Difficult to see the properties of UI elements</p>
<h2 id="heading-designing-ios-ui-programmatically">Designing iOS UI programmatically</h2>
<p>Building UI programmatically means creating the user interface in code (Swift, to be exact), rather than using the Interface Builder.</p>
<p>To create a project in UIKit programmatically, we create a new Xcode project and initially select <strong>Storyboard</strong> as we did before. Xcode creates a storyboard by default and makes it the initial screen. We go to <strong>Project Navigator</strong> and remove any references to Storyboard. We also make some configuration changes to <code>Info.plist</code> and <code>AppDelegate.swift</code> to remove the Storyboard dependency. For a tutorial of these configuration changes, <a target="_blank" href="https://www.youtube.com/watch?v=WoXn1fUe1K4">follow along with this video</a>.</p>
<p>To build UI programmatically, we first create an instance of a UI element. Then, we code the position of the instance on the screen.</p>
<h3 id="heading-creating-a-sample-ui-programmatically">Creating a sample UI programmatically</h3>
<p>Let’s create a sample user interface programmatically that will match the <code>Koala-Storyboard</code>.</p>
<p>We’ll use the following Swift code snippet:</p>
<pre><code>let koalaView <span class="hljs-operator">=</span> UIImageView()
koalaView.image <span class="hljs-operator">=</span> UIImage(named: <span class="hljs-string">"koala"</span>)
koalaView.translatesAutoresizingMaskIntoConstraints <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>
<span class="hljs-keyword">view</span>.addSubview(koalaView)

NSLayoutConstraint.activate(\[
  koalaView.centerYAnchor.constraint(equalTo: <span class="hljs-keyword">view</span>.centerYAnchor),
  koalaView.centerXAnchor.constraint(equalTo: <span class="hljs-keyword">view</span>.centerXAnchor),
  koalaView.widthAnchor.constraint(equalToConstant: <span class="hljs-number">320</span>),
  koalaView.heightAnchor.constraint(equalToConstant: <span class="hljs-number">320</span>)
\])
</code></pre><p>First, we create an <code>UIImageView</code> called <code>koalaView</code>. We give it an image attribute, <code>UIImage</code>, and a file name, <code>koala</code>. We add this subview to the parent view.</p>
<p>Then, we use the <code>NSLayoutConstraint</code> class to position the UI element. We center the UI element in the screen by specifying that its <code>centerYAnchor</code> and <code>centerXAnchor</code> values should equal the parent’s (in this case, the screen’s) <code>centerYAnchor</code> and <code>centerXAnchor</code> values. Just as we did with Storyboard’s Interface Builder, we specify the image’s width and height to be 320px.</p>
<pre><code>let koalaText <span class="hljs-operator">=</span> UILabel()
koalaText.text <span class="hljs-operator">=</span> <span class="hljs-string">"I love koalas ❤️"</span>
koalaText.font <span class="hljs-operator">=</span> UIFont.systemFont(ofSize: <span class="hljs-number">42</span>)
koalaText.translatesAutoresizingMaskIntoConstraints <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>
<span class="hljs-keyword">view</span>.addSubview(koalaText)

NSLayoutConstraint.activate(\[
      koalaText.centerXAnchor.constraint(equalTo: <span class="hljs-keyword">view</span>.centerXAnchor),
      koalaText.topAnchor.constraint(equalTo: koalaView.bottomAnchor, <span class="hljs-keyword">constant</span>: <span class="hljs-number">64</span>)
\])
</code></pre><p>We create a <code>UILabel()</code> for the “I love koalas” text and specify a <code>UIFont</code> size to match that used in the Storyboard example. Next, we use the <code>centerXAnchor.constraint</code> to center-align the text horizontally (along the x-axis). We use the <code>topAnchor.constraint</code> to position the test 64px below the image’s <code>bottomAnchor</code>.</p>
<p>Here’s an example of the UI created programmatically:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718159408/Jq697R1sm.png" alt="iOS UI Built Programmatically" /></p>
<p>Demo of the app UI built programmatically.</p>
<p><em><strong>N.B.</strong>, Apple provides the<code>NSLayoutConstraint</code> class for constraining the relationship between UI elements; however, some third-party libraries provide the same functionality with greater ease. One of the most popular libraries is SnapKit. To learn more about SnapKit, check out its <a target="_blank" href="https://github.com/SnapKit/SnapKit">repository on GitHub</a>.</em></p>
<h3 id="heading-pros-and-cons-of-creating-ui-programmatically-for-ios">Pros and cons of creating UI programmatically for iOS</h3>
<p>Here’s a summary of the pros and cons of building UI programmatically:</p>
<h4 id="heading-pros">PROS</h4>
<p>All UI and screen control is in one place</p>
<p>Code may be searched and reused</p>
<p>Easy code refactoring for experienced developers since the developer is in control of the UI elements</p>
<p>Easier to resolve merge conflicts</p>
<p>Easy to see the properties of UI elements</p>
<p>Supports adding animations</p>
<h4 id="heading-cons">CONS</h4>
<p>Most developers find it more time consuming to write code vs. drag and drop</p>
<p>No visual representation of screens until the code is run</p>
<p>Potentially complex refactoring, in cases of old code or code that was written by another developer</p>
<p>Requires constraints for auto layout (responsiveness)</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>in this article, we evaluated the pros and cons of using Storyboard to create an iOS app user interface vs. building it programmatically. We showed that each method can be advantageous, depending on the scenario. Here are the repositories for the <a target="_blank" href="https://github.com/iremkaraoglu/iOS-Storyboard-Example">Storyboard example</a> and the <a target="_blank" href="https://github.com/iremkaraoglu/iOS-ProgrammaticallyUI-Example">programmatically example</a> used in this article.</p>
<p>I recommend getting comfortable using Storyboard as well as designing programmatically so that you can decide which method to use on a project-by-project basis.</p>
<p>If you have an urge to create a static UI and are a solo developer, Storyboard is probably the best option. Storyboard is quick, and without other developers working on the project, you won’t face merge conflicts.</p>
<p>I hope you enjoyed this article. If you have any feedback or would like to share knowledge on this topic, feel free to reach out to me in the comments below or directly at hi@iremkaraoglu.com.</p>
<p>The post <a target="_blank" href="https://blog.logrocket.com/storyboard-vs-programmatically-ios-ui-design/">Storyboard vs. programmatically for iOS app UI design</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Supporting accessibility in iOS applications]]></title><description><![CDATA[To develop the best product, we should be making a good user experience for everyone. People with disabilities should be considered in everything.
When it comes to software products, they need to be accessible. Disabilities should not be a barrier to...]]></description><link>https://iremkaraoglu.com/supporting-accessibility-in-ios-applications</link><guid isPermaLink="true">https://iremkaraoglu.com/supporting-accessibility-in-ios-applications</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[UIkit]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 15:12:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/A_H7TfmEyYo/upload/v1657724763626/7Ekg99SL-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To develop the best product, we should be making a good user experience for everyone. People with disabilities should be considered in everything.</p>
<p>When it comes to software products, they need to be accessible. Disabilities should not be a barrier to their usage. Products should be usable for everyone. By making your app more accessible, you can reach a larger audience and make it easier to use.</p>
<p>Operating systems do have accessibility features for their users, and mobile developers for iOS devices should consider getting benefits from these accessibility features. Today, I will be focusing on iOS app development for supporting accessibility.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718164201/qm8aOfQYL.jpeg" alt="&quot;I design experiences that make people's lives simple.&quot;" /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@benkolde">Ben Kolde</a> on Unsplash</p>
<p>In iOS devices, when you open <strong>Settings</strong>, you will see a title called <strong>Accessibility</strong>. As I mentioned before, accessibility is a general concept, so there are many options to help people use the applications in their best use case.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718165910/QJx7er_y1.png" alt="iOS Settings &gt; Accessibility Menu" /></p>
<p>What we can do to support accessibility in an iOS application are research the iOS capabilities and features, and how we can use these features in our apps. Today I will provide a few common examples to give you an idea.</p>
<h3 id="heading-an-accessibility-example-contrast">An accessibility example: Contrast</h3>
<p>As I mentioned previously, there are some responsibilities for designers. Before we start the technical stuff, I would like to give a basic tip for supporting accessibility.</p>
<p>If you are developing an app on your own, focus on color contrast. To make your app easy to read and see, the background and the text colors should contrast each other. It is beneficial for everyone but especially for people with low vision and reading disorders.</p>
<p>Let’s see the example below. The left one has more contrast than the right one. The label and the button text are more readable, right?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718168611/EaSXgvn2u.png" alt="Panda High Contract vs. Low Contrast Colors" /></p>
<p>This is an example of accessibility to bear in mind when creating your app, related to visual design.</p>
<h2 id="heading-accessibility-features-on-ios">Accessibility features on iOS</h2>
<p>Now, we can go over accessibility features for iOS. I created an example iOS application and we will walk through it in each step.</p>
<p>This app consists of two screens. The first screen has a label, image, and a button to navigate the second screen. The second one includes labels, an animation consisting of four images in a loop, and a slider. Let’s cover this app’s accessibility features.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718171282/V0B9t6QUV.gif" alt="iOS Accessibility Demo App" /></p>
<h3 id="heading-voiceover">VoiceOver</h3>
<p>I will mention VoiceOver a lot, so I need to talk about what it is first. VoiceOver is a screen reader on iOS and iPadOS devices. It reads the user interface of the device to help people with visual impairments, and it is also used by people who have motion sickness and when they are in a moving vehicle.</p>
<p>VoiceOver reads the screen as much as possible, but developers should also be sure it reads coherently. For instance, we have text on the screen and a star icon button to add the text to favorites. Probably, it will read the button as “star, button,” and developers can change the way it reads and give a label like “add to favorites, button.” It is better to check and give some attributes for VoiceOver by code to be more informative to users.</p>
<p>By coding with VoiceOver in mind, you can decide:</p>
<ul>
<li>which UI element is or is not to be read by VoiceOver</li>
<li>what the text will be when it is reading that element</li>
<li>what the value will be when it is reading that element (e.g., if the button is selected or not)</li>
<li>what can be a hint for that element to inform the user moreisAccessibilityElement: Bool</li>
</ul>
<p>This shows the value of whether the UI element is accessible or not. If you use a UIKit element, the value is <code>true</code> by default. If you create a custom UI element, you need to set this attribute to <code>true</code>.</p>
<p>accessibilityLabel: String?</p>
<p>This is a string that an assistive app — VoiceOver, in this case — reads for that UI element. VoiceOver reads the text of the <code>UILabel</code> or <code>UIButton</code> by default. However, you can still give the <code>accessibilityLabel</code> to be informative.</p>
<p>accessibilityValue: String?</p>
<p>The current value of the accessibility element is represented by a string. For instance, it can be a text value from a <code>UILabel</code>, a percentage from a <code>UISlider</code>, etc.</p>
<p>accessibilityHint: String?</p>
<p>You probably need to use this in some cases but not always. If you would like to give too much text to read in the <code>accessibilityLabel</code>, you may move some of them to the <code>accessibilityHint</code>. <code>accessibilityHint</code> gives the clue of what’s going to happen if they press that button or use some UI element.</p>
<p>Bear in mind that, generally, UIKit elements have default values to support accessibility. However, if you create a custom <code>UIView</code> subclass, you need to create an instance of <code>UIAccessibilityElement</code>. In this way, you will be able to use <code>UIAccessibility</code> properties.</p>
<p>To start my example, I didn’t need to code anything related to VoiceOver and ran my project with VoiceOver. Here is the demo:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/k149o79-LKU?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p><a target="_blank" href="https://blog.logrocket.com/wp-content/uploads/2021/12/ios-accessibility-voice-over-before.mov">VoiceOver: Before</a></p>
<p>I found out that it doesn’t see the image as an element and doesn’t read anything related to them. In addition to that, I also wanted to customize some values because VoiceOver was reading the default texts of the <code>UILabel</code>s.</p>
<p>⁕ I added an accessibility label to my <code>UILabel</code> and it shows the text as Welcome. However, VoiceOver reads it as “Example Accessibility Label” because I customized it.</p>
<pre><code>let pandaLabel <span class="hljs-operator">=</span> UILabel()
pandaLabel.text <span class="hljs-operator">=</span> <span class="hljs-string">"Welcome"</span>
pandaLabel.accessibilityLabel <span class="hljs-operator">=</span> <span class="hljs-string">"Example Accessibility Label"</span>
</code></pre><p>⁕ <code>pandaImageView</code> is what I called my image view, and I added <code>pandaImageView.isAccessibilityElement =</code> <code>true</code> to inform VoiceOver that it is accessible.</p>
<p>⁕ I added an <code>accessibilityLabel</code> to my image view and gave <code>pandaImageView.accessibilityLabel = "Panda"</code></p>
<p>⁕ I also added <code>accessibilityHint</code> to the next button at the bottom, to inform the user what that button performs when it is pressed.</p>
<pre><code>let nextButton <span class="hljs-operator">=</span> UIButton()
nextButton.setTitle(<span class="hljs-string">"Next"</span>, <span class="hljs-keyword">for</span>: .normal)
nextButton.accessibilityHint <span class="hljs-operator">=</span> <span class="hljs-string">"Navigates to the next screen"</span>
</code></pre><p>So, let’s see how it is changed:</p>
<iframe class="youtube-player" width="640" height="360" src="https://www.youtube.com/embed/_HE43fJuQ98?version=3&amp;rel=1&amp;showsearch=0&amp;showinfo=1&amp;iv_load_policy=1&amp;fs=1&amp;hl=en-US&amp;autohide=2&amp;wmode=transparent" style="border:0" sandbox="allow-scripts allow-same-origin allow-popups allow-presentation"></iframe>

<p><a target="_blank" href="https://blog.logrocket.com/wp-content/uploads/2021/12/ios-accessibility-voice-over-after.mov">VoiceOver: After</a></p>
<h3 id="heading-text-size">Text size</h3>
<p>While developing, we generally give the font-size value to meet with the design. However, it doesn’t let users change the font size according to their visual capabilities and preferences.</p>
<p>For this example, I first created a screen, including hardcoded font size.</p>
<pre><code>let pandaLabel <span class="hljs-operator">=</span> UILabel()
pandaLabel.font <span class="hljs-operator">=</span> .boldSystemFont(ofSize: <span class="hljs-number">24</span>)
</code></pre><p>As I mentioned before, in this case, font-size does not change according to accessibility settings.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718178237/80WcfZ2D2.gif" alt /></p>
<p>What we can do here is give a dynamic text size to the label to meet the user’s intentions.</p>
<p>N.B., sometimes a user’s choice can lead to inaccessible app UI. For instance, much bigger text sizes can cover the whole screen and displace a button.</p>
<p>Let’s see how we can give a dynamic text size to the label.</p>
<pre><code>let pandaLabel <span class="hljs-operator">=</span> UILabel()
pandaLabel.font <span class="hljs-operator">=</span> UIFont.preferredFont(forTextStyle: .body)
pandaLabel.adjustsFontForContentSizeCategory <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>
pandaLabel.numberOfLines <span class="hljs-operator">=</span> <span class="hljs-number">3</span>
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718185227/nUaoi8yqP.gif" alt="iOS Accessibility Change in Text Size" /></p>
<h3 id="heading-reduce-motion">Reduce motion</h3>
<p>Reduced motion is used for people who are sensitive to motion effects and screen movements. Reduced motion disables the animations in certain applications.</p>
<p>If we have any animation, switching on the <strong>Reduce motion</strong> feature probably won’t disable the animation in our app. What we can do here is remove the animation if the <strong>Reduce motion</strong> feature is enabled by using <code>isReduceMotionEnabled</code> property.</p>
<p>We can benefit from this feature using this code snippet.</p>
<pre><code><span class="hljs-keyword">if</span> (UIAccessibility.isReduceMotionEnabled) {
<span class="hljs-comment">// add what your app should do with reduced motion version</span>

} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// add what your app should do with motions are allowed</span>

}
</code></pre><p>In my example project, I created a <code>UIImageView</code>, an array including four images, and made a loop to show these images in that image view. In the beginning, when I enabled the <code>ReduceMotion</code> switch, it didn’t affect my application. So, I decided to show one image when it’s enabled like in the following.</p>
<pre><code><span class="hljs-keyword">if</span> (UIAccessibility.isReduceMotionEnabled) {
<span class="hljs-comment">// Settings &gt; Accessibility &gt; Motion &gt; Reduce Motion switch is turned on</span>
    pandaImageView.image <span class="hljs-operator">=</span> UIImage(named: <span class="hljs-string">"panda2"</span>)
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">// Settings &gt; Accessibility &gt; Motion &gt; Reduce Motion switch is turned off</span>
    let animationImages <span class="hljs-operator">=</span> \[UIImage(named: <span class="hljs-string">"panda.png"</span>)<span class="hljs-operator">!</span>, UIImage(named: <span class="hljs-string">"panda2.png"</span>)<span class="hljs-operator">!</span>, UIImage(named: <span class="hljs-string">"panda3.png"</span>)<span class="hljs-operator">!</span>, UIImage(named: <span class="hljs-string">"panda4.png"</span>)<span class="hljs-operator">!</span>\]
    pandaImageView.animationImages <span class="hljs-operator">=</span> animationImages
    pandaImageView.animationDuration <span class="hljs-operator">=</span> <span class="hljs-number">1.5</span>
    pandaImageView.startAnimating()
}
</code></pre><p>In the end, it turned into this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718190700/oxng0aEWf.gif" alt="iOS Accessibility Reduce Motion" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We are living in a digital era, so why don’t we make it accessible for everyone? If we want to create a better world for humans, we can start here.</p>
<p>Each major iOS version update brings new accessibility features. We can start by staying up to date on the capabilities of these features and how we can support them in our applications.</p>
<p>Today, I covered some tips on supporting accessibility in iOS applications. It is a broad concept, so I mentioned as many as possible. You can reach my <a target="_blank" href="https://github.com/iremkaraoglu/iOS-Accessibility-Example-UIKit">demo app here</a>.</p>
<p>If you would like to give any feedback, ask questions, or share something, feel free to reach out to me via hi@iremkaraoglu.com. For further information, I recommend you to check out the resources in the references section.</p>
<p>See you in the next article!</p>
<h3 id="heading-references">References</h3>
<ul>
<li><a target="_blank" href="https://developer.apple.com/accessibility/ios">https://developer.apple.com/accessibility/ios</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/uikit/accessibilityforuikit">https://developer.apple.com/documentation/uikit/accessibility_for_uikit</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/objectivec/nsobject/uiaccessibility">https://developer.apple.com/documentation/objectivec/nsobject/uiaccessibility</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/accessibility/supportingvoiceoverinyourapp">https://developer.apple.com/documentation/accessibility/supporting_voiceover_in_your_app</a></li>
<li><a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/accessibility/overview/text-size-and-weight/">https://developer.apple.com/design/human-interface-guidelines/accessibility/overview/text-size-and-weight/</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/uikit/uiaccessibility/1615133-isreducemotionenabled">https://developer.apple.com/documentation/uikit/uiaccessibility/1615133-isreducemotionenabled</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/uikit/uifont/scalingfontsautomatically">https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically</a></li>
</ul>
<p>The post <a target="_blank" href="https://blog.logrocket.com/supporting-accessibility-ios-applications/">Supporting accessibility in iOS applications</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Developing a 2D mobile game as a mobile app developer]]></title><description><![CDATA[After working on mobile application development for a few years, I started to develop 2D games. In this article, I would like to share with you my observations and compare two different concepts in the scope of mobile development. I will walk through...]]></description><link>https://iremkaraoglu.com/developing-a-2d-mobile-game-as-a-mobile-app-developer</link><guid isPermaLink="true">https://iremkaraoglu.com/developing-a-2d-mobile-game-as-a-mobile-app-developer</guid><category><![CDATA[Swift]]></category><category><![CDATA[iOS]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[SpriteKit]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 13:59:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/p0j-mE6mGo4/upload/v1657724320422/vQ4IIeWSoD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After working on mobile application development for a few years, I started to develop 2D games. In this article, I would like to share with you my observations and compare two different concepts in the scope of mobile development. I will walk through the differences one by one and add example code snippets from my example of a Swift, SpriteKit 2D game.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718199122/pE1ThF_tUB.gif" alt="PandaClicker Mobile Game" /></p>
<p>My game is called Panda Clicker, and the aim is to touch the Panda image in the center of the screen. In each touch, a small panda slides from the top of the screen, a sound plays, and the score increases. When the score becomes a number that is a multiplier of 10, the device vibrates, and the user sees a particle animation on the screen. <a target="_blank" href="https://github.com/iremkaraoglu/PandaClickerGame">You may reach the source code here.</a> I will cover it in this article in detail.</p>
<h3 id="heading-nodes-and-scenes">Nodes and scenes</h3>
<p>During this article, I will mention nodes and scenes. Let’s talk about what they are first.</p>
<p>In SpriteKit, nodes are organized hierarchically into node trees, similar to how views and subviews work. <a target="_blank" href="https://developer.apple.com/documentation/spritekit/sknode/getting_started_with_nodes">Apple’s developer docs put it this way</a>: “Most commonly, a node tree is defined with a scene node as the root node and other content nodes as descendants. The scene node runs an animation loop that processes actions on the nodes, simulates physics, and renders the contents of the node tree for display.”</p>
<p>With that in mind, we are ready to talk about the comparison between 2D games and mobile development!</p>
<p>While you are developing a game, you need to think more about the senses. What will be the player hear when they click that button? What will they feel while holding their phone? What visuals will they see? How long will that animation take? What will be the aim for the user? You will probably need to think differently than developing a mobile application. Let’s start! </p>
<h3 id="heading-randomness">Randomness</h3>
<p>You may have seen an example of a treasure hunt game. As a basic explanation, it is a game where a user attempts to find something that has been hidden.</p>
<p>I am adding an example from the Sims Mobile Treasure Hunt event. In this example GIF below, two spots have fifty ancient relics and one has thirty golden bunnies. Each time, the rewards in the area (and the spots with these awards) generate randomly, and there is one chance to select — or you need to spend some SimCash to get one more chance, but whatever.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718205007/rSgmJ8AXy.gif" alt="Sims Mobile Treasure Hunt example" /></p>
<p>If we could have the treasures in the same positions, the game wouldn’t be entertaining, right? If I knew the left one always contains golden bunnies, how would I get excited? It would be consistent, stable, and boring. We are looking for randomness here to have fun. It gives us uncertainty about where the treasure is. It gives a little bit of stress, but also joy when we succeed. Trying to find where would it be and listening to my instincts about the treasure position is the fun part of this game.</p>
<p>However, we wouldn’t like randomness in a bank application. Imagine you open your transfers page and your transfers are not ordered chronologically. No way! Every user would be complaining about it.</p>
<p>We are looking for consistency in the mobile applications to use them easily. Otherwise, users get confused about finding the section they need. But in a mobile game, randomness is one of the things that will help you to achieve fun!</p>
<p>I am adding an example code snippet below to give you an idea about randomness. It is from <a target="_blank" href="https://github.com/iremkaraoglu/PandaClickerGame">Panda Clicker,</a> which is my example project. The following code creates a node for the scene. I added an image I drew on Procreate and called it “panda.”</p>
<p>It gets the image and creates a node called “panda.” It gets a random x position between <code>0</code> and the screen width. Then, it positions the node in that random x position at the top of the screen. How they slide on the screen is the topic of the animations that we will cover later on:</p>
<pre><code>let screenSize: CGRect <span class="hljs-operator">=</span> UIScreen.main.bounds
let panda <span class="hljs-operator">=</span> SKSpriteNode(imageNamed: <span class="hljs-string">"panda"</span>)
let randomXPos <span class="hljs-operator">=</span> CGFloat.random(in: <span class="hljs-number">0</span>..&lt;screenSize.width)
panda.position <span class="hljs-operator">=</span> CGPoint(x: randomXPos, y: screenSize.height)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718207139/uhTNaHdZP.gif" alt="Randomness Example PandaClicker" /></p>
<h3 id="heading-calculations">Calculations</h3>
<p>While I am developing the user interface in a mobile application, I don’t need to calculate much. The paddings, height, and width are certain and I can reach the values on Figma. I never calculated a complex equation in developing UI.</p>
<p>However, developing a mobile game was different. As I stated before, there might be randomness in 2D games, and maybe in the specific part of a screen. You need to set the boundaries for that randomness.</p>
<p>Let’s say there will be images in those random positions. What happens when your image’s center is inside the boundaries but some parts overflow? You also need to consider your image size. How about the boundaries? They may differ depending on device; some devices have larger widths, some devices have larger heights. You need to consider the device size. You need to think about this in detail and calculate more!</p>
<p><a target="_blank" href="https://developer.apple.com/documentation/spritekit/getting_started_with_physics">Apple’s developer docs have this to say</a>: “Although you can control the exact position of every node in a scene, often you want these nodes to interact with each other, colliding with each other. You might also want to do things that are not handled by the action system, such as simulating gravity and other forces.”</p>
<p>For these purposes, you need to add a physics engine to your game. SpriteKit and Unity have this feature already. To hear more about the physics engine, you can check out this <a target="_blank" href="https://www.youtube.com/watch?v=-_IspRG548E&amp;feature=youtu.be">video on designing a physics engine</a>.</p>
<h3 id="heading-input-handling">Input handling</h3>
<p>In mobile app development, there is no need to handle inputs manually. However, in game development, inputs are the most important part of games. As developers, we are coding according to the input we take from a gamepad, touch, mousepad, keyboard, and so on to provide the best user experience.</p>
<p>In our case, this is a mobile game, therefore touch is important as an input. In application development, UI elements are giving the data of what the user touched on the screen. In game development, we are converting the screen position as a game camera and finding the touch position of the user.</p>
<h3 id="heading-animations">Animations</h3>
<p>In mobile applications such as a bank application or a chat application, you probably do not see animations as much as in 2D games. The user doesn’t have an interest in animation in a bank application; they would like to use a bank application in a secure, fast, and easy way! Good user experience is the key!</p>
<p>When it comes to 2D games, animations are what make the games fancier. Just think about match-three games like Candy Crush. Think about this game without any animations. The box just disappears when you clicked. The lack of feedback would make users disinterested. When developing games, animations are not a must, but they’re recommended if you want to attract users.</p>
<p>Just a basic example to show the difference with and without animation below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718208881/FNpj9FLN9.gif" alt="Animation Count" /> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718210591/jp77j-tjd.gif" alt="Normal Count" /></p>
<p>In the Randomness section, we saw the pandas sliding down the screen at a random x coordinate. Now it’s time to hear more about how they slide. In the below code, let’s recall how to add the node to the screen. Then just a statement provided slides it: that <code>moveTo()</code> function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718211995/PbKV36y-j.gif" alt="PandaClicker Randomness Example" /></p>
<pre><code><span class="hljs-comment">// recall creating a node and giving a random x position at the top of the screen </span>
let panda <span class="hljs-operator">=</span> SKSpriteNode(imageNamed: <span class="hljs-string">"panda"</span>)
let randomXPos <span class="hljs-operator">=</span> CGFloat.random(in: <span class="hljs-number">0</span>..&lt;screenWidth)
panda.position <span class="hljs-operator">=</span> CGPoint(x: randomXPos, y: screenHeight)

<span class="hljs-comment">// below codes moves the node to the -72 in the y coordinate, in the 0.80 seconds and removes the node from the scene. </span>
panda.run(.sequence(\[
      .moveTo(y: <span class="hljs-number">-72</span>, duration: <span class="hljs-number">0</span><span class="hljs-number">.80</span>),
      .removeFromParent()
      \]))
</code></pre><h3 id="heading-particles">Particles</h3>
<p>When we are considering animations, there can be elements that move on the screen, or an effect called particles. A particle system is a complex node that emits these so-called particles in the game scene. Particle effects are largely used in video games for various graphic touches — glitter, smoke, explosions, rain, snow, and so on.</p>
<p>In comparison to mobile app development, no one thinks about adding particles to the screen when you are just sending some money to someone else, but in a game, it needs to be exciting and engaging. Luckily, particles will help you to achieve that! Add special effects to your app, such as glittering or realistic fire with smoke, using particle effects.</p>
<p>If you are developing using SpriteKit, you may create and configure particle effects using Xcode’s SpriteKit Particle Editor, or in code. In PandaClicker, I created a SpriteKit Particle File and called it “MagicParticle.” I changed the values on the Xcode editor like the amount of the particles and the colors. Particles appear when the score is a multiplier of 10 and then disappear.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718214645/7cKqXkQVa.gif" alt="Particles Gamedev Example" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718216920/Xy4ZVz9Xo.gif" alt="PandaClicker particles" /></p>
<pre><code><span class="hljs-keyword">if</span> let myEmitter <span class="hljs-operator">=</span>  SKEmitterNode(fileNamed: <span class="hljs-string">"MagicParticle.sks"</span>) {
      myEmitter.position <span class="hljs-operator">=</span> CGPoint(x: screenWidth <span class="hljs-operator">/</span> <span class="hljs-number">2</span>, y: screenHeight <span class="hljs-operator">/</span> <span class="hljs-number">2</span>)
      addChild(myEmitter)
}
</code></pre><p>In the above code snippet, I created an emitter node and I positioned the node in the center of the screen. Then I added it as a child of the scene’s root node.</p>
<h3 id="heading-haptics">Haptics</h3>
<p>Until now, we have covered some visual elements. Let’s change the topic and talk about haptics. It is the use of technology that stimulates the senses of touch and motion. In other words, it is the science and technology of transmitting and understanding information through touch.</p>
<p>As <a target="_blank" href="https://macreports.com/iphone-system-haptics-what-they-are-enable-or-disable/">macReports puts it</a>, “Some iPhone models include haptic feedback (also called Haptics or System Haptics). This feature uses the Taptic Engine to provide haptic feedback, combined with an audible tone and/or visual feedback. Taptic Engine produces vibration and haptic feedback functions.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718219076/V_Rs1N_x8.png" alt="Apple Taptic Engine" /></p>
<p>Taptic Engine from <a target="_blank" href="https://macreports.com/iphone-system-haptics-what-they-are-enable-or-disable/">macReports</a></p>
<p>When we are addressing the player’s senses, it is a great option to provide something that the player will feel. Therefore, it is engaging to feel something through your phone when it’s quite exciting at that moment in the game!</p>
<p>In Panda Clicker, I have added the haptics when the user achieves a score that is a multiplier of 10. I am adding the haptics code below. I have selected the <code>medium</code> style, you may choose what you desire by trial and error. If your device doesn’t support this feature, but you would like to get an idea of how it works, <a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/haptics/">check out information on haptics here</a>. It shows you how they sound and feel:</p>
<pre><code>let generator <span class="hljs-operator">=</span> UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()
</code></pre><p><a target="_blank" href="https://blog.logrocket.com/wp-content/uploads/2021/10/haptic-sounds.mp4">Medium impact haptic sound</a></p>
<p>The above video shows how the medium impact haptic sounds. Also, bear in mind that this feature requires hardware, it is not possible to see if your haptics code runs as you desire on a simulator. You have to test it on a physical device that supports haptics.</p>
<h3 id="heading-sound">Sound</h3>
<p>We covered touch senses, but what about hearing? When you are developing a game, sounds are essential as well. You may put background music, or just add sound effects, or why not both? You need to consider the harmony between the game and the sounds. If you are working with a design team, they will probably give you the sound files, but if you are an indie developer working alone, you need to think about your own.</p>
<p>I found a royalty-free sound to add to Panda Clicker and named it <code>panda_tap.mp3</code>. When the player touches the big panda on the screen, the following code runs and the panda_tap sound plays:</p>
<pre><code>SKAction.playSoundFileNamed(<span class="hljs-string">"panda\_tap.mp3"</span>, waitForCompletion: <span class="hljs-literal">true</span>)
</code></pre><p>We walked through randomness before, and when it comes to sounds we may randomize them as well! We may have several sounds for the win case of the game to make it more exciting!</p>
<p>An example code snippet is below. It is not from Panda Clicker, but I am adding it as an example of randomness in sounds. In this code, we have four sound files in an array that gets a random element in that array and assigns it to a <code>randomWinSound</code> variable. Then, <code>SKAction</code> plays the <code>randomWinSound</code>:</p>
<pre><code><span class="hljs-keyword">var</span> randomWinSound <span class="hljs-operator">=</span> \[<span class="hljs-string">"AudioAssets/perfect.mp3"</span>,
                      <span class="hljs-string">"AudioAssets/awesome.mp3"</span>,
                      <span class="hljs-string">"AudioAssets/well\_done.mp3"</span>,
                      <span class="hljs-string">"AudioAssets/congrats.mp3"</span>\].randomElement()<span class="hljs-operator">!</span>
SKAction.playSoundFileNamed(randomWinSound, waitForCompletion: <span class="hljs-literal">true</span>)
</code></pre><h3 id="heading-winlose-conditions">Win/lose conditions</h3>
<p>In mobile applications, there is no win or lose. However, when we are developing a mobile game, it is better to have winning or losing for anything to make users play with a purpose!</p>
<p>If you start developing, you should consider: what will be the player’s purpose? What will be the obstacles to achieving that or what would make them fail? You need to think from the player’s perspective and how will they engage with the game.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These are all of my observations until now. I hope it gives you an idea about the comparison between mobile app development and mobile game development. Your experiences may differ, but I wanted to share my journey and point of view. You may check out my example 2D game called <a target="_blank" href="https://github.com/iremkaraoglu/PandaClickerGame">Panda Clicker here</a>.<br />You may reach me via hi@iremkaraoglu.com for any feedback or questions.<br />See you in the next article! </p>
<h3 id="heading-references">References</h3>
<p><a target="_blank" href="https://www.ultraleap.com/company/news/blog/what-is-haptics/">https://www.ultraleap.com/company/news/blog/what-is-haptics/</a><br /><a target="_blank" href="https://developer.apple.com/documentation/uikit/animationandhaptics">https://developer.apple.com/documentation/uikit/animation_and_haptics</a><br /><a target="_blank" href="https://www.androidcentral.com/haptic-feedback-most-important-smartphone-feature-no-one-talks-about">https://www.androidcentral.com/haptic-feedback-most-important-smartphone-feature-no-one-talks-about</a><br /><a target="_blank" href="https://developer.apple.com/documentation/spritekit/sknode/gettingstartedwith_nodes">https://developer.apple.com/documentation/spritekit/sknode/getting_started_with_nodes</a><br /><a target="_blank" href="https://macreports.com/iphone-system-haptics-what-they-are-enable-or-disable/">https://macreports.com/iphone-system-haptics-what-they-are-enable-or-disable/</a></p>
<p>The post <a target="_blank" href="https://blog.logrocket.com/developing-2d-mobile-game-mobile-app-developer/">Developing a 2D mobile game as a mobile app developer</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Managing app permissions in React Native]]></title><description><![CDATA[When you are developing a mobile application with advanced features, you will most likely need to get permission from the user.
Applications should not be able to directly access the user’s camera, microphone, location, and so on in order to protect ...]]></description><link>https://iremkaraoglu.com/managing-app-permissions-in-react-native</link><guid isPermaLink="true">https://iremkaraoglu.com/managing-app-permissions-in-react-native</guid><category><![CDATA[React Native]]></category><category><![CDATA[permissions]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 13:29:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/cqFKhqv6Ong/upload/v1657718938278/VHc9HefNr.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you are developing a mobile application with advanced features, you will most likely need to get permission from the user.</p>
<p>Applications should not be able to directly access the user’s camera, microphone, location, and so on in order to protect the user. We need to respect user privacy by seeking permission to capture and store photos, audio, and video.</p>
<p>Let’s check on Facebook to see an example of camera permission. You are familiar with these alerts, right?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718228037/YWEv_ynH-t.png" alt="FB Camera Access Permission" /></p>
<p>To be able to present your application fully, your users have to give permission. But what if the user denies it? As you may guess, you can’t provide that feature. Therefore, permissions are essential.</p>
<p>What if we are developing a photo editing application? The solution is simple: we need to get their permission to access their data. In this article, we are going to dive into permissions and how we can get permissions in React Native by using zoontek’s <a target="_blank" href="https://github.com/zoontek/react-native-permissions">react-native-permissions library</a>.</p>
<p>Unfortunately, React Native doesn’t support getting permissions. Luckily, there is a popular third-party library we can use: Mathieu Acthernoene’s react-native-permissions library.</p>
<p>Let’s assume we want to ask for camera permission. The steps are easy to do.</p>
<p>To start, make sure you add this library to the project:</p>
<pre><code>$ npm install <span class="hljs-operator">-</span><span class="hljs-operator">-</span>save react<span class="hljs-operator">-</span>native<span class="hljs-operator">-</span>permissions
<span class="hljs-operator">-</span><span class="hljs-operator">-</span>or<span class="hljs-operator">-</span><span class="hljs-operator">-</span>
$ yarn add react<span class="hljs-operator">-</span>native<span class="hljs-operator">-</span>permissions
</code></pre><p>Then, be sure you import the library by writing at the top of your file where you’ll handle these permissions:</p>
<pre><code><span class="hljs-keyword">import</span> \<span class="hljs-operator">*</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">permissions</span> <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'react-native-permissions'</span>;
<span class="hljs-comment">// you may also import just the functions or constants that you will use from this library</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">request</span>, <span class="hljs-title">PERMISSIONS</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'react-native-permissions'</span>;
</code></pre><h3 id="heading-react-native-permissions-for-ios-devices">react-native-permissions for iOS devices</h3>
<ul>
<li>Make sure you add all wanted permissions to your app’s <code>Podfile</code> and run this command:</li>
</ul>
<pre><code><span class="hljs-attribute">pod</span> install
</code></pre><p>CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. The <code>Podfile</code> is a specification that describes the dependencies of the targets of one or more Xcode projects. Running <code>pod install</code> helps you to install the dependencies. You can <a target="_blank" href="https://cocoapods.org">check out CocoaPods here to read more</a>.</p>
<p>→ In our case, we will add</p>
<pre><code>pod <span class="hljs-string">'Permission-Camera'</span>, <span class="hljs-symbol">:path</span> =&gt; <span class="hljs-string">"<span class="hljs-subst">#{permissions\_path}</span>/Camera"</span>
</code></pre><p>to <code>Podfile</code> and run <code>pod install</code>.</p>
<ul>
<li>Update the <code>Info.plist</code> with wanted permissions usage descriptions. You may achieve this in two ways; choose which suits you.</li>
</ul>
<h4 id="heading-option-1-xcode">Option 1: Xcode</h4>
<ul>
<li>Open the Info section</li>
<li>Add a new line</li>
<li>Select which permission you would like from the options as a key</li>
<li>Add value to that key</li>
</ul>
<p>→ In our case, we will select <strong>Privacy – Camera Usage Description.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718231999/oOaXAVf9k.png" alt="Xcode Privacy Camera Usage" /></p>
<h4 id="heading-option-2-text-editor">Option 2: Text Editor</h4>
<ul>
<li>Open <code>Info.plist</code> file</li>
<li>Copy key and string values from the following and paste that file</li>
<li>Update the string value according to your need:</li>
</ul>
<pre><code><span class="hljs-operator">&lt;</span>?xml version<span class="hljs-operator">=</span><span class="hljs-string">"1.0"</span> encoding<span class="hljs-operator">=</span><span class="hljs-string">"UTF-8"</span>?<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span>DOCTYPE plist PUBLIC <span class="hljs-string">"-//Apple//DTD PLIST 1.0//EN"</span> <span class="hljs-string">"http://www.apple.com/DTDs/PropertyList-1.0.dtd"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>plist version<span class="hljs-operator">=</span><span class="hljs-string">"1.0"</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span>dict<span class="hljs-operator">&gt;</span>     
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> 🚨 Keep only the permissions used in your app 🚨 <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSAppleMusicUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSBluetoothAlwaysUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSBluetoothPeripheralUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSCalendarsUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSCameraUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSContactsUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSFaceIDUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSLocationAlwaysAndWhenInUseUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSLocationAlwaysUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSLocationTemporaryUsageDescriptionDictionary<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>dict<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>YOUR<span class="hljs-operator">-</span>PURPOSE<span class="hljs-operator">-</span>KEY<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
        <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dict<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSLocationWhenInUseUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSMicrophoneUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSMotionUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSPhotoLibraryUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSPhotoLibraryAddUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSRemindersUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSSpeechRecognitionUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSSiriUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSUserTrackingUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> … <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>dict<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>plist<span class="hljs-operator">&gt;</span>
</code></pre><p>→ In our case, it is as follows:</p>
<pre><code><span class="hljs-operator">&lt;</span>key<span class="hljs-operator">&gt;</span>NSCameraUsageDescription<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>key<span class="hljs-operator">&gt;</span>
    <span class="hljs-operator">&lt;</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>YOUR TEXT<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span><span class="hljs-keyword">string</span><span class="hljs-operator">&gt;</span>
</code></pre><p>The value section in the first option and the <code>&lt;string&gt;</code> section in the second option correspond to the text inside the alert message.</p>
<p>Let’s recall the Facebook camera permission alert. The description part is the text you give as the value here:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718235122/SSq2odbFX.jpeg" alt="FB Camera Permission Text" /></p>
<p>→ In our case, I just gave “Camera” to the value, and here it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718236786/0xXaIyDUh.png" alt="RN Permission Text Body" /></p>
<h3 id="heading-react-native-permissions-for-android">react-native-permissions for Android</h3>
<ul>
<li>Add all wanted permissions to your app’s <code>android/app/src/main/AndroidManifest.xml</code> file:</li>
</ul>
<pre><code><span class="hljs-operator">&lt;</span>manifest xmlns:android<span class="hljs-operator">=</span><span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
      package<span class="hljs-operator">=</span><span class="hljs-string">"com.myawesomeapp"</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> 🚨 Keep only the permissions used in your app 🚨 <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ACCEPT\_HANDOVER"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ACCESS\_BACKGROUND\_LOCATION"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ACCESS\_COARSE\_LOCATION"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ACCESS\_FINE\_LOCATION"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ACTIVITY\_RECOGNITION"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.ANSWER\_PHONE\_CALLS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.BODY\_SENSORS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.CALL\_PHONE"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.CAMERA"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.GET\_ACCOUNTS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.PROCESS\_OUTGOING\_CALLS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_CALENDAR"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_CALL\_LOG"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_CONTACTS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_EXTERNAL\_STORAGE"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_PHONE\_NUMBERS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_PHONE\_STATE"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.READ\_SMS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.RECEIVE\_MMS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.RECEIVE\_SMS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.RECEIVE\_WAP\_PUSH"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.RECORD\_AUDIO"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.SEND\_SMS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.USE\_SIP"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.WRITE\_CALENDAR"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.WRITE\_CALL\_LOG"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.WRITE\_CONTACTS"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"android.permission.WRITE\_EXTERNAL\_STORAGE"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>
      <span class="hljs-operator">&lt;</span>uses<span class="hljs-operator">-</span>permission android:name<span class="hljs-operator">=</span><span class="hljs-string">"com.android.voicemail.permission.ADD\_VOICEMAIL"</span> <span class="hljs-operator">/</span><span class="hljs-operator">&gt;</span>

      <span class="hljs-operator">&lt;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> … <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">&gt;</span>

<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>manifest<span class="hljs-operator">&gt;</span>
</code></pre><p>→ In our case, we need to add only camera permission to the <code>AndroidManifest.xml</code> file:</p>
 

<h3 id="heading-requesting-the-permission-return-types">Requesting the permission: return types</h3>
<pre><code>request(Platform.OS <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-string">'ios'</span> ? PERMISSIONS.IOS.CAMERA : PERMISSIONS.ANDROID.CAMERA).then((result) <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> {
        setPermissionResult(result)
        console.log(result)
      });
</code></pre><p>The return types and the meanings are here:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718238517/oycS8f2qe.png" alt="Permission Return Types and Meanings" /></p>
<p>The flow differs by the operating system. Here, there is the flow chart for permissions for iOS and Android, which is taken from the documentation of this library.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718240158/9IwaH7kcm.png" alt="iOS Permission Flow" /><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718241844/t0SIPy3nJ.png" alt="Android Permission Flow" /></p>
<h3 id="heading-the-final-product">The final product</h3>
<p>Voila! You are ready to run your code! Basically, that’s it!</p>
<p>You may still encounter a few problems, like maybe your device doesn’t support that feature or the version is not valid. My advice: the first place where you check for the solution should be the documentation of the library.</p>
<p>While writing this post, I built an example React Native application that includes camera and microphone permissions. It shows the result of the permission and the explanation of the result.</p>
<p>You may play with it, see the result types, and observe when that result is returned. You may first approve it, then change the permission in Settings, open the application, and see what happens. Work with it to understand better!</p>
<p>You may also use the sample for testing while you are coding for specific occasions. Other than playing with the sample, you can check out the source code, and if you are having trouble with anything, you can compare it with mine!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=Ktny9_Tc5l4">https://www.youtube.com/watch?v=Ktny9_Tc5l4</a></div>
<p>When I was about to finish my example project, I found out zoontek also made an example app for this just like mine but including every permission! You can <a target="_blank" href="https://github.com/zoontek/react-native-permissions/tree/master/example">check out zoontek’s example application here.</a></p>
<p>Key points for configuring permissions</p>
<h4 id="heading-permission-appearance">Permission appearance</h4>
<p>Bear in mind that if you answer a permission request, it won’t ask for that permission again. If you want it to appear again, delete and install the app.</p>
<p>If you only want to change the result, you may change it on the settings of your device.</p>
<p>In iOS, the user must explicitly grant permission for each app to access the camera and microphone. Before your app can use the capture system for the first time, the operating system shows an alert asking the user to grant your app access to the camera. They remember the user’s response to this alert, so it doesn’t reappear each time you access a user’s camera.</p>
<p>The user can change permission settings for your app in <strong>Settings</strong> &gt; <strong>Privacy</strong> in iOS, or<br /><strong>Settings</strong> &gt; <strong>Apps</strong> &gt; <strong>“Your App Name”</strong> &gt; <strong>Permissions</strong> in Android.</p>
<h4 id="heading-dangerous-permissions">Dangerous permissions</h4>
<p>Previously in Android development, every permission had to be added in the <code>AndroidManifest.xml</code> file. They were called Install-Time Permissions, and they were requested at the installation time at the Google Play Store.</p>
<p>Starting from Android 6.0 (API 23), the dangerous permissions, in other words run-time permissions, concept came up and these permissions became necessary to ask in runtime rather than install-time. Runtime permissions are the alert dialog boxes that come up when the app is running.</p>
<p>Let’s examine Instagram for permissions. When we check Instagram on Google Play Store, we see a bunch of permissions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718244836/otKt23hxX.png" alt="Instagram Permissions" /></p>
<p>User’s camera, contacts, location, microphones, phones, and storage are their sensitive information. Therefore, they are dangerous permissions. So, in the Android 6.0 and later versions, users see run-time permissions when they are using the app; here, it’s Instagram.</p>
<p>When a user is trying to post a photo or a video, the run-time permission dialog comes up on the screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718246354/iYrP7MXKf.png" alt="Instagram Permissions Request" /></p>
<p>Similarly, when a user attempts to take a photo or a video on Instagram, these permissions come up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657718247767/IAafCMjs2.png" alt="Instagram Runtime Permissions" /></p>
<h4 id="heading-android-11-permission-updates">Android 11 permission updates</h4>
<p>In the Android ecosystem, there have been changes that come with Android 11:</p>
<ul>
<li>If your application requests permission related to camera, microphone, or location, the permission dialog includes the “Only this time” option. If it is selected, your app is granted permission for one time. It is called “one-time permission.” The second time the app is opened, the permission dialog comes up again</li>
<li>If your application hasn’t been used for a few months, the system automatically resets the sensitive runtime permissions that the user had granted for the app</li>
</ul>
<p>To learn more, <a target="_blank" href="https://developer.android.com/about/versions/11/privacy/permissions">go check out Android 11’s updates</a>.</p>
<h4 id="heading-ios-145-app-tracking-transparency">iOS 14.5: App Tracking Transparency</h4>
<p>For iOS 14.5, iPadOS 14.5, and tvOS 14.5 and newer, developers are required to ask users for their permission to track them across apps and websites owned by other companies. One of the best features of this library is that it is up-to-date. You may add an <a target="_blank" href="https://developer.apple.com/documentation/apptrackingtransparency">AppTrackingTransparency</a> (ATT) prompt and request by using react-native-permissions. Remember, only iOS devices version 14.5 or newer are able to request this.</p>
<h5 id="heading-when-to-ask-permissions-for-the-best-user-experience">When to ask permissions for the best user experience 🤗</h5>
<p>Asking for permissions in the onboarding of the application or asking them at the specific time that you need is still a user experience debate. There is not an answer; there are opinions.</p>
<p>What I would suggest is asking when you need it. As a user, seeing all the permissions in the onboarding scares me, and most of the time I don’t give the full permissions. As I said before, this is open to debate. Choose what suits you.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have covered the concept of permissions and how we can get them in React Native by using react-native-permissions. I gave you the key points you may need in your permission journeys, such as the Android 11 and iOS 14.5 changes. You can <a target="_blank" href="https://github.com/iremkaraoglu/ReactNative-Permissions-Example">find my example project in this GitHub repository</a>.</p>
<p>I hope you have enjoyed this article and your users give the full permissions to get benefit from your application features! If you have any feedback, feel free to reach out. Until next time, take care! </p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://developer.android.com/guide/topics/permissions/overview">Android permissions docs</a></li>
<li><a target="_blank" href="https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_ios">iOS permissions docs</a></li>
</ul>
<p>The post <a target="_blank" href="https://blog.logrocket.com/react-native-permissions/">Managing app permissions in React Native</a> appeared first on <a target="_blank" href="https://blog.logrocket.com">LogRocket Blog</a>.</p>
]]></content:encoded></item><item><title><![CDATA[UI Testing in React Native with Detox]]></title><description><![CDATA[Today, I would like to talk about UI tests, which is one of the things that I am responsible for years in the company that I work at. Let’s start with what is UI testing.
UI testing is basically what designers, testers and the frontend developers do ...]]></description><link>https://iremkaraoglu.com/ui-testing-in-react-native-with-detox-fa28ef310830</link><guid isPermaLink="true">https://iremkaraoglu.com/ui-testing-in-react-native-with-detox-fa28ef310830</guid><category><![CDATA[React Native]]></category><category><![CDATA[Detox]]></category><category><![CDATA[Testing]]></category><category><![CDATA[E2E]]></category><category><![CDATA[ui testing]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 13:07:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657717482881/n8X4kkwTb.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, I would like to talk about UI tests, which is one of the things that I am responsible for years in the company that I work at. Let’s start with <strong>what is UI testing.</strong></p>
<p><strong>UI testing</strong> is basically what designers, testers and the frontend developers do maybe without even noticing it. When we are testing a screen, we check the components: The button is located in the right place, the content is correct, the button navigates the user to the X screen, and so on. We were all doing it and it was namely UI (User Interface) Testing. It can be done manually or <a target="_blank" href="https://www.perfecto.io/products/testcraft">automated with a testing tool</a>. Regardless of the method used, the goal is to ensure that all the UI elements meet the requested specifications.</p>
<p>The more features your application has, the harder it is to test manually. Automated tests help to ensure that your application performs correctly before you publish it while retaining your feature and bug-fix velocity.</p>
<p>In <a target="_blank" href="https://otsimo.com/en/">Otsimo</a>, we develop our products in React Native and one day we faced with a major bug that costs a lot for our company. Then, we realized that we should do something to prevent this situation to happen again. Also, we add features each day so we need to be sure that we are not breaking anything and continue developing with confidence. So, we ended up with the solution which is building End to End testing.</p>
<p>When it comes to the comparison of tests, Integration Testing has the highest maintenance cost, has the most dependencies, and slowest in execution speed but gives the highest confidence with respect to Unit and Component Testing. According to our reasons, it was fair enough for us to do Integration Testing, so we dived into UI Testing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657715154517/f6Bxp_tkdG.png" alt /></p>
<p>Table for comparison of tests</p>
<p>To learn more about the test types you can check <a target="_blank" href="https://reactnative.dev/docs/testing-overview">React Native’s Testing documentation</a>.</p>
<h4 id="heading-detox">Detox</h4>
<p><a target="_blank" href="https://github.com/wix/Detox">Detox</a> is an end-to-end testing framework which is developed by <a target="_blank" href="http://wix.com">Wix</a>. This means it runs your app on an actual device/simulator and interacts with it just like a real user would. This type of testing can give a lot of confidence in your app and help automate a manual QA process. To learn more about how detox works, you may want to check <a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/Introduction.HowDetoxWorks.md">here</a>.</p>
<p>Detox was the best fit for us because it is built from the ground up to support React Native projects as well as pure native ones. It is built for gray box end-to-end testing for iOS and then started to support Android as well. It offers more capabilities for iOS rather than Android and since we are not fond of Android default emulator, our tests only run on iOS.</p>
<h4 id="heading-testathon">Testathon</h4>
<p>In our company, we spared two days just for testing in the developers team. We called it <strong>Testathon.</strong> We wanted to have UI Tests and have the artifacts (logs and video recordings from the tests) to be stored. Therefore, we created a new backend service to store artifacts that runs on Raspberry PI in the office near our real UI testing device.</p>
<p>We separated into two groups, one group listed down the test scenarios and wrote tests, the other one worked on backend service to store the build artifacts to our Raspberry PI in the office. I am not going to dive into this part because this is not relevant to the topic I would like to cover but as a brief, I may say, we also added these tests to our CI/CD process. When one of the tests fails, It doesn’t pass the CI and the fail message comes with our internal Slack bot. Gitlab does not have any feature like having these logs and videos to show, we needed to build this. We store each one for 90 days. These all are built using <a target="_blank" href="https://golang.org">Go</a>. Let’s go back to the first group’s part which is about the test itself.</p>
<h4 id="heading-creating-ui-test-scenarios">Creating UI Test Scenarios</h4>
<p><strong>It’s better to focus on what is essential for your application</strong>. For example, if registering is mandatory in your application, you should better be checking if sign up and login screens and their functions work as intended!</p>
<p>While doing that, you have to code the tests as if you are testing manually. What do I mean by that? When you are manually testing, you check the screen like if the title and the content are correct. Then, check the the button if it is located correctly and you press a button. Next, you wait for an action like navigating to a new screen. You understand you have navigated correctly because you saw a new title and the content are changed. Same way, you should code your UI test. You should write the commands like what you normally do when you are testing it manually.</p>
<p>For example:<br />1. Check if there are “Sign Up” and “Sign In” buttons on the screen.<br />2. Press the “Sign In” button and wait for a screen to have e-mail input field.<br />3. Type correct email address and password and expect to see the Home screen<br />…</p>
<p>As a company, we need to be sure that our users or potential users should successfully sign up/sign in, they should be able to purchase a premium membership and successfully open the screens in the application without any crash. We started with these essential tests. Before diving into the code, let’s see my frequently used stuff which is taken from the API documentation, and see an example to make it clear.</p>
<h4 id="heading-the-devicehttpsgithubcomwixdetoxblobmasterdocsapirefdeviceobjectapimd-object">The <a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.DeviceObjectAPI.md">Device</a> Object</h4>
<p><code>device</code> is globally available in every test file, it enables control over the current attached device (currently only simulators are supported).</p>
<ul>
<li><code>device.installApp()</code>By default, <code>installApp()</code> with no params will install the app file defined in the current <code>configuration</code>.</li>
<li><code>device.uninstallApp()</code>By default, <code>uninstallApp()</code> with no params will uninstall the app defined in the current <code>configuration</code>.</li>
<li><code>device.launchApp()</code>Launch the app defined in the current <code>configuration</code>.</li>
<li><code>device.terminateApp()</code>By default, <code>terminateApp()</code> with no params will terminate the app file defined in the current <code>configuration</code>.</li>
<li><code>device.openURL(url)</code>Mock opening the app from URL.</li>
<li><code>device.enableSynchronization()</code>Enable (restore) synchronization (idle/busy monitoring) with the app — namely, resume waiting for the app to go idle before moving forward in the test execution. Enabled by default.</li>
<li><code>device.disableSynchronization()</code>Temporarily disable synchronization (idle/busy monitoring) with the app - namely, stop waiting for the app to go idle before moving forward in the test execution (rather, resort to applying unrecommended <code>sleep()</code>'s in your test code...).</li>
<li><code>device.setURLBlacklist([urls])</code> Exclude syncrhonization with respect to network activity (i.e. don’t wait for network to go idle before moving forward in the test execution) according to specific endpoints, denoted as URL reg-exp’s.</li>
</ul>
<h4 id="heading-matchershttpsgithubcomwixdetoxblobmasterdocsapirefmatchersmd"><a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md">MATCHERS</a></h4>
<p>Detox uses <a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md">matchers</a> to match UI elements in your app. The ones that I use so often are below.</p>
<ul>
<li><code>by.id()</code><br />Match elements with the specified accessibility identifier. In React Native, this corresponds to the value in the <code>[testID](https://reactnative.dev/docs/view.html#testid)</code> prop.<br /> — <code>testID</code>Used to locate a view in end-to-end tests.</li>
<li><code>by.label()</code>Match elements with the specified accessibility label (iOS) or content description (Android). In React Native, this corresponds to the value in the <code>[accessibilityLabel](https://facebook.github.io/react-native/docs/view.html#accessibilitylabel)</code> prop.</li>
<li><code>by.text()</code>Match elements with the specified text.</li>
</ul>
<h4 id="heading-actionshttpsgithubcomwixdetoxblobmasterdocsapirefactionsonelementmd"><a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.ActionsOnElement.md">ACTIONS</a></h4>
<p>Detox uses <a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.ActionsOnElement.md">actions</a> to simulate user interaction with those elements. My frequently used ones are below.</p>
<ul>
<li><code>.tap()</code> Simulates a tap on the element at the specified point, or at element’s activation point if no point is specified.</li>
<li><code>.typeText()</code>Simulates typing of the specified text into the element, using the system’s builtin keyboard and typing behavior.</li>
<li><code>.clearText()</code>Simulates clearing the text of the element, using the system’s builtin keyboard and typing behavior.</li>
<li><code>.tapReturnKey()</code>Simulates tapping on the return key into the element, using the system’s builtin keyboard and typing behavior.</li>
</ul>
<p>[<strong>wix/Detox</strong><br /><em>Detox uses matchers to match UI elements in your app. Use actions to simulate use interaction with elements and…</em>github.com](https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md "https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md")<a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.Matchers.md"></a></p>
<h4 id="heading-expectationshttpsgithubcomwixdetoxblobmasterdocsapirefexpectmd"><a target="_blank" href="https://github.com/wix/Detox/blob/master/docs/APIRef.Expect.md">EXPECTATIONS</a></h4>
<p>Detox uses expectations to verify those elements are in the expected state.</p>
<ul>
<li><code>.toBeVisible()</code>Expects the element to be visible on screen.</li>
<li><code>.toExist()</code>Expects the element to exist within the app’s current UI hierarchy.</li>
</ul>
<p>Bear in mind:<br />If we are checking the element’s visibility, we are expecting that the element is on the screen (not scrolled or something) and has at least <strong>75% opacity</strong>. Alternatively, you can expect the element <code>.toExist()</code>, but that might result with an element that a user can't interact with. <code>.toExist()</code>checks for the current UI hierarchy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657715155930/Fcobwtc8T.jpeg" alt /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@cookiethepom?utm_source=medium&amp;utm_medium=referral">Cookie the Pom</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<h4 id="heading-example">👩🏻‍💻 EXAMPLE</h4>
<blockquote>
<p><strong>Talk is cheap, show me the code.</strong></p>
</blockquote>
<p>Here is the coding part 🐝</p>
<p>I created a <a target="_blank" href="https://github.com/iremkaraoglu/ReactNative-Detox-Example"><strong>repository</strong></a> to show you an example. Now, I will summarize it here with simpler code.</p>
<p>I created two screens and they have the following UI elements inside the render methods. I added <strong>testID</strong> attribute to the elements to reach during tests.</p>
<p>Then, I added the <strong>detox</strong> library and made the configurations.</p>
<p>Now, time to write the first test !</p>
<ul>
<li>First, we should see the sign up and sign in buttons on the screen. Expect the elements’ visibility by their id (which are the testID’s we recently gave)</li>
<li>Secondly, sign in button should be clicked and it should navigate to a new screen. Its ID is “emailField” and it should be visible.</li>
<li>Thirdly, emailField and passwordField should be filled by the values “irem@test.com” and “123456” respectively. Then the “My Courses” text should be visible on the screen. (This time, I checked by text not by id — this is a separate screen and it just has a text component, so I didn’t place it here)</li>
</ul>
<h4 id="heading-demo">DEMO 🎉🎉🎉</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657715160433/JGKv6RpVL.gif" alt /></p>
<h4 id="heading-hint-1">Hint — 1💡</h4>
<p>It is more practical to check the elements by ID because the machine finds the elements by id more easily and also it avoids the ambiguity. For example, there might be “Done” button twice in a screen, one on the page and one may occur in a popup. If we expect the element by text as “Done”, it won’t be able to decide about which one we are aiming for.</p>
<h4 id="heading-hint-2">Hint — 2💡</h4>
<p>If there are multiple elements on the screen (most probably this will be the case) if one of them’s visibility gives you the confidence that you are on the right screen, you do not have to check for every element. However, if there are essential ones, it’s better to check them too.</p>
<p>While you are running your UI test, make sure that you opened Simulator by XCode to see how the tests run on a simulator. Therefore you may easily see where it got stuck; in a popup or a screen that you might have forgotten for instance. Other than that, it gives me joy to see someone is clicking on the buttons and testing the app :)</p>
<h4 id="heading-hint-3-common-mistake">Hint — 3: Common Mistake 💡</h4>
<p>You may see console warn messages appear during the UI tests just like in the gif above. When there is a warn message and it comes across to the element you expect it to be visible or will have an action with it, it ends up with failure because warn messages block the button’s visibility and the actions. You may avoid having console warn messages and learn here how to achieve that:</p>
<p>[<strong>How do you hide the warnings in React Native iOS simulator?</strong><br /><em>I found that even when I disabled specific warnings (yellow-box messages) using the above mentioned methods, the…</em>stackoverflow.com](https://stackoverflow.com/questions/35309385/how-do-you-hide-the-warnings-in-react-native-ios-simulator "https://stackoverflow.com/questions/35309385/how-do-you-hide-the-warnings-in-react-native-ios-simulator")<a target="_blank" href="https://stackoverflow.com/questions/35309385/how-do-you-hide-the-warnings-in-react-native-ios-simulator"></a></p>
<h4 id="heading-useful-video-resources">Useful Video Resources</h4>
<p>I personally love reading the Detox documentation because it gives me all the information I need. However, if you would like to search for more resources here is a list of my favorite others.</p>
<ul>
<li><a target="_blank" href="https://youtu.be/_neMz2_6u20">Real World e2e Testing with Detox by Vojtech Novak</a> :<br />It is a presentation in React Native EU 2019 Conference. As a visual learner, I like to see someone explains a technology with a presentation. This video was my first resource before diving into the Detox! After getting to know the concepts, using the documentation became easier!</li>
<li><a target="_blank" href="https://youtu.be/4rU0IGEt6OQ">Detox: Tackling the flakiness of mobile automation by Viktorija Sujetatie</a><br />It is again a presentation and it’s by Mobile QA Engineer of Wix. She revises React Native, mentions why they need to implement their own framework for E2E testing and explains Detox.</li>
</ul>
<p>Please like this article if you liked the content, it helps me to get motivated and create more 🌟</p>
]]></content:encoded></item><item><title><![CDATA[Building Design System in React Native 🎨]]></title><description><![CDATA[If you are running a company a Design System will probably let you create screens quickly and as intended! But..what is a Design System?
A design system is a system that all your components are already planned to use in the screens to be compatible. ...]]></description><link>https://iremkaraoglu.com/building-design-system-in-react-native</link><guid isPermaLink="true">https://iremkaraoglu.com/building-design-system-in-react-native</guid><category><![CDATA[React Native]]></category><category><![CDATA[Design]]></category><category><![CDATA[Design Systems]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 12:40:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657653719939/tBo6u19JI.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are running a company a Design System will probably let you create screens quickly and as intended! But..what is a Design System?</p>
<p>A design system is a system that all your components are already planned to use in the screens to be compatible. So the designers decide on what kind of buttons there will be in the application, which colors will be used, and so on. So, when a screen is updated or a new screen is coming up, designers focus on making it compatible and use the same kind of components or improve them without changing them much. After all, the design process becomes faster than before and the development as well. 🏃‍♀</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657649233652/bMHo1r7GW.png" alt="1*yhD8KsccGl0DTKSU-i0Zaw.png" /></p>
<p>Building a design system requires teamwork. Now, I’m going to mention what we have done in Otsimo as the development team and how we cooperate with the design team.</p>
<p>The design team discussed what kind of buttons will we have, which size, font, colors, and so on. After all, we started to build the components and also made a specific React Native application to see what the design components are. It gives us the benefit of seeing how an upcoming component is compatible with our system, how do they look, and inform us about the design system components. Nowadays, we are updating our products with the new design of the screens using design system components! 🧙🏻‍♀️
If all of these sound complicated, don’t worry it will be clear. Let’s start!</p>
<h3 id="heading-typography">Typography</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657649290496/FraILFxs_.png" alt="1*2WqFdiaLy8D4yBLt7U0wMw.png" /></p>
<p>Text variants were decided and as developers, we created our Text component which takes the variant as a prop and we only use these variants to maintain our design system.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="38e6a2702be4831cc2ac9b173349620e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/38e6a2702be4831cc2ac9b173349620e" class="embed-card">https://gist.github.com/iremkaraoglu/38e6a2702be4831cc2ac9b173349620e</a></div><p>The code snippet shows how we would style a text in a way that probably most of you all know. What we have done is, having stylings and just giving the styling name as a props, and voila! Let’s see how it works.</p>
<p>We called our text component as OtsimoText. It works similarly with the Text component, the only difference is it has the variant props.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="46e242624b6b3aadc3b352aee71d66f2"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/46e242624b6b3aadc3b352aee71d66f2" class="embed-card">https://gist.github.com/iremkaraoglu/46e242624b6b3aadc3b352aee71d66f2</a></div><p>Two of the variants are listed below. So, the styling changes according to that variant and it makes our job easier.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="60fb1408040e1856ddd28d2597c817d4"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/60fb1408040e1856ddd28d2597c817d4" class="embed-card">https://gist.github.com/iremkaraoglu/60fb1408040e1856ddd28d2597c817d4</a></div><h3 id="heading-colors">Colors</h3>
<p>Designers set the color palette that our application will have and as the development team, we created a file to add these colors as constants and named them. We don’t use any other HEX or RGB code, we stay in that color palette.</p>
<p>Some colors are listed below.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="47ff29ef7ae6e1c77094da3d94d50b2e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/47ff29ef7ae6e1c77094da3d94d50b2e" class="embed-card">https://gist.github.com/iremkaraoglu/47ff29ef7ae6e1c77094da3d94d50b2e</a></div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657652858894/eKSwY6Dje.jpeg" alt="1*NWwhvL9JOmNu73jyFxSTNg.jpeg" /></p>
<p>Writing style={{ color: colors.yellow.dark1 }} instead of style={{ color: “rgb(245,198, 0, 1.0)” }} is more practical and also prevents typos.</p>
<h3 id="heading-buttons">Buttons</h3>
<p>Designers designed what kind of buttons we will have and they divided these into three.</p>
<ul>
<li>Filled Button</li>
<li>Text Button</li>
<li>Iconic Button
So, we created separate components for each of them. They have the Pressable component inside.</li>
</ul>
<p>Example of our button variants:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716482152/FU4rCxStL.png" alt="1*qFyDV1k9lBpiWnrdh5ySUg-2.png" /></p>
<h3 id="heading-theme-support">👩🏻‍🎨 Theme Support</h3>
<p>Until here, all were somehow easy if you are already a React Native Developer. Let’s dive into deep and build a theme! But why do we need that? We have several mobile applications and each one has different color palettes. We care about reusing the components and we don’t want to give hardcoded color values, therefore, we build theme support and each application gets the color from its theme. For example, one application may have a dark background, one may have light and we get the color value from its theme according to which application is it. After we built this, it became essential for us. Let’s see how it works in detail.</p>
<p>If you have a theme with background, primary, and secondary colors and you change one of the colors in your theme, the change will apply to every place where the color is used in the application.</p>
<p>Assume that your primary color in your application is dark blue. You use this dark blue all of your buttons in your project. You access this color not by this dark blue’s hex or RGB numbers, you access it by your theme like color:theme.primary.</p>
<p>When you change your opinion about this primary color and you decide to make it dark green, you don’t need to change every single button’s color, you just need to change the primary color’s value and here we go! It’ll be changed dynamically!</p>
<p>So, let’s see some code! 💻</p>
<p>We used React Context which is designed to share data for a tree of React components.
We created a Hook to access easily to the theme values.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="49b4eef4cfb771398d112700d5cb0f7f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/49b4eef4cfb771398d112700d5cb0f7f" class="embed-card">https://gist.github.com/iremkaraoglu/49b4eef4cfb771398d112700d5cb0f7f</a></div><p>Usage</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="ae93d55d8086a4a7268f846175b3680a"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/ae93d55d8086a4a7268f846175b3680a" class="embed-card">https://gist.github.com/iremkaraoglu/ae93d55d8086a4a7268f846175b3680a</a></div><p>How we use this theme support in our design system application is shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716527870/IlsmONes3.png" alt="1*AgML0npuIG9aoCeYiozC6A-2.png" /></p>
<p>This shows the process of changing the primary color from blue to yellow in the theme, and the buttons that use primary color changes to yellow immediately. Why don’t we play and mix it more?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716800034/Gi_9YdDpy.png" alt="1*Z8o9bPbUBUAHuUWPortjPg-2.png" /></p>
<p>Changing primary, secondary, background, and textPrimary colors result with this grey backgrounded screen. We use these theme colors especially in the buttons, see how they changed:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716829664/hS_7-MkbB.png" alt="1*opegTFi4Np_dLA5mCZd7uw-2.png" /></p>
<h3 id="heading-svg-icons-into-font">SVG Icons into Font! 👀</h3>
<p>First, we created a separate repository for this purpose. We used fantasticon which is an icon font generation tool. It generates TTF, TypeScript, and JSON files. When we need new icons we add them to that repository. We run the command to convert SVG icons and then update our development repository with the new output files. Fantasticon’s documentation is so good, so I won’t go over it. I want to mention what we have gained after this conversion.</p>
<p>Earlier, we were putting icons as Image and it was making our application size larger. Styling was also taking the time.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="d41344c53a43b8690e224e123acd6a58"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/d41344c53a43b8690e224e123acd6a58" class="embed-card">https://gist.github.com/iremkaraoglu/d41344c53a43b8690e224e123acd6a58</a></div><p>Then, we came up with converting SVG Icons to the font. We can access them by using the Icon component.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="a228283bc38f8fe3a7d3382871436ca1"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/a228283bc38f8fe3a7d3382871436ca1" class="embed-card">https://gist.github.com/iremkaraoglu/a228283bc38f8fe3a7d3382871436ca1</a></div><p>✓ Takes less space on disk than png images.
✓ Fewer lines of code.
✓ Can be scalable to any size.</p>
<p>To see our icons list and how do they look according to the size, we created a page on our design system application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716915716/43lpqKRf9.png" alt="1*RYOY_9w8pwPiesupqw4oug-2.png" /></p>
<h3 id="heading-accessibility">Accessibility!</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657716908712/2xflt1kX7.png" alt="1*GGpOLbESJTqbYXxhkn5VgA.png" /></p>
<p>Accessibility is a part of our design system. During the building process of the design system, we also paid attention to how we can make our components and application accessible.</p>
<p>It is a long story so for further details, you can read an article about how to support accessibility in React Native from <a target="_blank" href="https://iremkaraoglu.medium.com/support-accessibility-in-mobile-applications-e9e8c0a181e7">here</a>. ⬅️</p>
<p>“With design system, we have minimized to use of time, maximized to speak same design language with design crew. Not just for that, but also design system has been an icebreaker to set up fast and healthy collaboration with the dev-team.” — Mehmet Çam, Head of Design at Otsimo</p>
<p>Hope you enjoyed this article!</p>
<p>If you’d like to see more articles, please subscribe to my newsletter 📨 Thank you for being here and for your support. 💙</p>
]]></content:encoded></item><item><title><![CDATA[Accessibility Support in React Native Applications]]></title><description><![CDATA[Here in Otsimo, we are developing applications for the kids who have learning disorders or with autism spectrum disorder. We care about the equality in education and support the special children’s needs. Our apps are designed to be used by parents an...]]></description><link>https://iremkaraoglu.com/accessibility-support-in-react-native-applications</link><guid isPermaLink="true">https://iremkaraoglu.com/accessibility-support-in-react-native-applications</guid><category><![CDATA[React Native]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[Mobile Development]]></category><dc:creator><![CDATA[Irem Karaoglu]]></dc:creator><pubDate>Wed, 13 Jul 2022 11:01:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657708772100/lHz5qu0jU.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here in <a target="_blank" href="https://www.otsimo.com/en">Otsimo</a>, we are developing applications for the kids who have learning disorders or with autism spectrum disorder. We care about the equality in education and support the special children’s needs. Our apps are designed to be used by parents and their lovely children. What about our visually impaired users? How can they easily use our app? Can blind people use mobile applications? What about writing code? Can they write a code even they cannot see? Let’s talk about it first.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657707172417/DKoyAdV1u.png" alt="1*Ovh3J1LDY92pRxifiokEWw.png" /></p>
<p><strong>Tuukka Ojala</strong> is a blind developer who listens the code line by line by screen reader. He speaks in detail about how he uses his computer and writes code in <a target="_blank" href="https://www.vincit.fi/fi/software-development-450-words-per-minute/">his blog post</a>. He is one of the best examples that visually impaired people do exist, they have jobs just like us and use technological devices as well. They are able to use these devices, thanks to the accessibility features of softwares.</p>
<p>What can we do for visually impaired people not only as humans but also as developers? We can make the apps suitable for their needs. We can add accessibility features to help their usage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657707209579/9VQRZkQin.png" alt="1*RvSQk2fTQ3UI6qhlbe00zg.png" /></p>
<p>We generally think like only people who have blindness use screen readers, but it is only 64% of users of screen readers. People who have low vision are 39% and there are also cognitive, deafness, motor and other ilnesses who use screen readers.</p>
<p>To support accessibility in a mobile application project, emphaty is the key to understand. I am going to mention <strong>how to make a mobile application more accessible for people who use screen readers</strong> on a React Native project especially for iOS devices.</p>
<p>My development started as testing it on iOS Settings. It reads the text of a button and then says “button” to let the user know it’s pressable. If you have already implemented at least a page of your mobile application, you can check out what are the necessities. Probably VoiceOver won’t understand that it is a button and won’t say “button” after reading the text of your button. So you need to make it accessible first (by default, all touchable elements are accessible) and declare accessibility role as button. If these don’t make sense, don’t worry. Keep reading, everything will be clear.</p>
<h2 id="heading-lets-start">Let’s start</h2>
<p>To ensure that VoiceOver can access your component, type 
<strong>accessible={true}</strong> in your component.</p>
<p>Whenever you have a control, add all of the accessibility information you can. At a minimum, implement the following properties</p>
<ul>
<li>accessibilityRole (button, text, link, etc.)</li>
<li>accessibilityLabel (when the operating system can’t derive a useful read out on what this control does)</li>
<li>accessibilityHint (when the label alone won’t tell the user what’s going to happen when they click it)</li>
</ul>
<h3 id="heading-accessibilityrole">AccessibilityRole</h3>
<p>To inform the user that it’s a button, add 
<strong>accessibilityRole=“button”</strong> to your component in the same way.</p>
<p>Some accessibility roles you may probably use often are listed below. There are bunch of other roles so you can check it out for more to find out which suits your needs.</p>
<p><strong>alert</strong>: Used when an element contains important text to be presented to the user.</p>
<p><strong>button</strong>: Used when the element should be treated as a button.</p>
<p><strong>header</strong>: Used when an element acts as a header for a content section (e.g. the title of a navigation bar).</p>
<p><strong>image</strong>: Used when the element should be treated as an image. For example, it can be combined with button or link.</p>
<p><strong>switch</strong>: Used to represent a switch which can be turned on and off.</p>
<p><strong>text</strong>: Used when the element should be treated as static text that cannot be changed.</p>
<h3 id="heading-accessibilitystate">AccessibilityState</h3>
<p>You can inform the user by adding <strong>accessibilityState={{ disabled: true }}</strong> if the button is disabled so the user can’t press that one. VoiceOver reads it as “dimmed” when it’s disabled. You can also use <strong>accessibilityState={{selected: true}}</strong> if you want it to be read as “selected”.</p>
<p>Let’s see some code to make it clear. Following code renders a Pressable component with a “This is an example” text on it and Accessibility VoiceOver reads it as “This is an example dimmed button” on iOS.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="c57364e09498a228dcc17cb79934e070"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/iremkaraoglu/c57364e09498a228dcc17cb79934e070" class="embed-card">https://gist.github.com/iremkaraoglu/c57364e09498a228dcc17cb79934e070</a></div><p>AccessibilityState takes an object which is not limited with the disabled key. You may also add selected, checked and so on.</p>
<p><strong>Selected</strong> is mostly used in the components that include buttons and users are able to select only one. Therefore, VoiceOver informs the user about which is “selected”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657707920060/rXuhXWUO1.png" alt="1*EqpErTA1BCDSI3z8suPIOw.png" /></p>
<p>In the above example, “While iPhone is Locked” is selected so these two rows are read as “Always” and then “Selected While iPhone is Locked”.</p>
<p>When it comes to “checked”, you may use it on your switch buttons just like iOS’ airplane mode on — off. Also, make sure that you are writing <strong>accessibilityRole=“switch”</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657708005784/lNjb2I3vI.png" alt="1*yyC4yeFbi_hLTFPy2ll7lg.png" /></p>
<p>Above example is read as “Do not disturb <strong>on</strong> double tap to toggle setting, scheduled <strong>off</strong> double tap to toggle setting” by VoiceOver.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657708028898/gUewPr_e8.png" alt="1*e3255Xu2xS0Gq6L26hnrqg.png" /></p>
<h3 id="heading-accessibilityhint">AccessibilityHint</h3>
<p>An accessibility hint helps users to understand what will happen when they perform an action on the accessibility element when the result from the accessibility label is not clear. Such as telling the user that back button’s action as “Navigates to the previous screen”.</p>
<p>Bear in mind that if the user has hints enabled in the device’s VoiceOver settings, VoiceOver reads the hint after reading the label. When it comes to Android, TalkBack (Android’s screen reader) will read the hint after the label as well but hints cannot be turned off on Android.</p>
<h2 id="heading-did-you-know-that-voiceover-uses-machine-learning">Did you know that VoiceOver uses Machine Learning ?</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657708051906/ON9eOj_ApV.jpeg" alt="1*wBolfiakc2ClJM_gn6RpOA.jpeg" /></p>
<p>You may think like it just reads and we give the roles, states, labels to make it read. Where is Machine Learning in this?</p>
<p>As a personal experience, while using our application, I realized it reads my iconic button (which has a + sign on it) as “Add” but we didn’t provide any accessibility information to it. I thought probably it just reads the icon’s name but icons are just unicode numbers and voice over doesn’t know it’s name.</p>
<p>While investigating this with our CTO, we tested it by opening the gallery and it started to read the photographs like “image, a baby crawling on the floor”. Then we found <strong>“VoiceOver Recognition”</strong> feature which uses on-device machine learning models. According to Apple, It improves accessibility of an app that have no accessibility information such as identifying the state of buttons or toggles.</p>
<p>As a user, you can switch recognition features <strong>ON</strong> under the <strong>VoiceOver Recognition</strong> title. If <strong>Image Descriptions</strong> is on, VoiceOver speaks descriptions of images in apps and on the web. If <strong>Text Recognition</strong> is on, VoiceOver speaks descriptions of text found in images. When it comes to <strong>Screen Recognition</strong>, it automatically make apps more accessible by recognizing items on the screen and especially this one is what makes your mobile application more accessible. For instance, it identifies the state of buttons or toggles, and by grouping related items together.</p>
<p>So, especially for icons and images, if you don’t want VoiceOver to read your visual component according to Machine Learning result, just give it an <strong>AccessibilityLabel</strong> to specify what you would like to be read. Otherwise, if your screen recognition turned on iOS users may experience some readings not matching what you have intended.</p>
<h2 id="heading-recommendation">Recommendation</h2>
<p>I recommend two movies (<a target="_blank" href="https://www.imdb.com/title/tt2980516/">Theory of Everything</a> and <a target="_blank" href="https://www.imdb.com/title/tt4632316/?ref_=fn_al_tt_1">Gleason</a>) to help you understand how accessibility features are beneficial for people. As you may know, Stephen Hawking is one of the well known people about experiencing Voice Technologies. Helping them and making their lives easier is our responsibility.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article was only for supporting screen readers in mobile applications. As Otsimo development team, our work about accessibility is still going on. Now, we are searching for taking input just by head or eye movements and how we can add these features to our products.</p>
<p>I hope this article was beneficial for you and will help you to support accessibility in your products. If you are not developing anything at least having awareness is important too.</p>
<p>Thank you for reading, if you like this article and want to hear more please like this article. If you want to be notified about my next article, you can subscribe to my newsletter.</p>
<p>This article is originally posted <a target="_blank" href="https://www.iremkaraoglu.medium.com">on my medium blog</a>. See you in the next article! 🦋</p>
]]></content:encoded></item></channel></rss>