<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Evan Deaubl</title>
    <description>The latest articles on Forem by Evan Deaubl (@evandeaubl).</description>
    <link>https://forem.com/evandeaubl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F112473%2F3de3b5ce-7af4-47fa-b414-d9a7de76e5fb.jpg</url>
      <title>Forem: Evan Deaubl</title>
      <link>https://forem.com/evandeaubl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/evandeaubl"/>
    <language>en</language>
    <item>
      <title>Adding manual app badges to your app: step by step</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 26 Apr 2019 13:00:08 +0000</pubDate>
      <link>https://forem.com/evandeaubl/adding-manual-app-badges-to-your-app-step-by-step-2d6b</link>
      <guid>https://forem.com/evandeaubl/adding-manual-app-badges-to-your-app-step-by-step-2d6b</guid>
      <description>&lt;p&gt;It’s really common for apps that support notifications to use them to update the application badge to display numbers of unread messages, undone tasks, etc. &lt;strong&gt;But what if you don’t need or want the added complexity of supporting push notifications, or even local notifications, but want to alert the user via an app badge?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apple’s documentation on this particular way of using app badges is not the best. Badges are combined with the UserNotifications framework, but if you want to set the badge yourself outside of a notification, that is part of UIKit. And the documentation are missing important points like: do you need to check that you’re authorized to show badges to set the badge manually? Will it error out? Crash? Result in strange app behavior?&lt;/p&gt;

&lt;p&gt;Manual app badges turn out to be really easy, but the docs don’t make it seem that way. Let’s demystify them right now.&lt;/p&gt;




&lt;p&gt;First of all, as I alluded to above, badges are part of the notification functionality of iOS. This means that before you do anything with notifications, you need to get authorization from the user.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.badge]) 
   { (granted, error) in
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you want to do something if the user rejects the authorization, then you can include code that handles that case in the block. More than likely, if a user rejects app badge authorization, your app will not experience any problems, as we will touch on a little later, so I generally don’t do anything to handle the condition (but you must pass a block, because it isn’t optional…).&lt;/p&gt;

&lt;p&gt;Apple recommends you do this authorization process when the app is first launched. I’ve seen some apps that delay that to an initial onboarding process, so they can better explain to the user why they need notification access. Either way, you should do this step early in the app lifecycle.&lt;/p&gt;

&lt;p&gt;Once you have that authorization, it’s time to set a badge. While other notification functionality is more complicated, setting the badge count is really easy, though not obvious. Setting the badge count manually is a property of your &lt;code&gt;UIApplication&lt;/code&gt; object, but that isn’t indicated anywhere in Apple’s notifications documentation, only in the UIKit documentation.&lt;/p&gt;

&lt;p&gt;Once you know that, it’s really, really easy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;UIApplication.shared.applicationIconBadgeNumber = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will result in your app displaying a badge with the number 1 on it, like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mssJyspF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Settings-Update-app-iOS-7.jpg" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-247" src="https://res.cloudinary.com/practicaldev/image/fetch/s--mssJyspF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Settings-Update-app-iOS-7.jpg" width="254" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;applicationIconBadgeNumber&lt;/code&gt; to 0 will clear the badge. (This also has the side effect of clearing any notifications your app has produced, because badges are normally coupled with notifications, but for this example, we are just implementing manual badges, so nothing to worry about here).&lt;/p&gt;

&lt;p&gt;Now, you may have noticed that there was no checking around setting the badge number whether badges were authorized by the user. That is perfectly okay. iOS will simply ignore any request to set a badge if a user has not authorized a badge for your app, or revokes that authorization later on. You may want to check if you want to do something else instead of an app badge using &lt;code&gt;UNUserNotificationCenter.getNotificationSettings(completionHandler:)&lt;/code&gt;. For app badges, you’ll almost always want to do nothing if you haven’t been authorized, so no checking required.&lt;/p&gt;

&lt;p&gt;A simple couple of lines of code, and you have support for app badges, the simplest way to notify your user that there’s something to do in your app!&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/blank-page-getting-started-new-app-development/"&gt;a workflow to get unstuck building a new app&lt;/a&gt; is already waiting for you. &lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/manual-app-badge-tutorial/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>uikit</category>
      <category>notifications</category>
    </item>
    <item>
      <title>Making your circular views circular in Interface Builder</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Thu, 18 Apr 2019 13:17:33 +0000</pubDate>
      <link>https://forem.com/evandeaubl/making-your-circular-views-circular-in-interface-builder-4l5b</link>
      <guid>https://forem.com/evandeaubl/making-your-circular-views-circular-in-interface-builder-4l5b</guid>
      <description>&lt;p&gt;A really common thing to do in iOS interfaces is make interface elements either circular or into a squircle (squircular?). This is a common thing to do when displaying user avatars, for example.&lt;/p&gt;

&lt;p&gt;If you’re building your interface in a storyboard, though, you’ll find one big problem when you add the code to make your view circular: &lt;strong&gt;Your storyboard doesn’t look like your app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ajy5UZIE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.08.21.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-237" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ajy5UZIE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.08.21.png" width="386" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ugly.&lt;/strong&gt; This just won’t do.&lt;/p&gt;

&lt;p&gt;Luckily, there is a really simple way to make your storyboard controls match your app controls.&lt;/p&gt;




&lt;p&gt;First step, we’ll start with the code that implements the circular view in the app itself. Setting the &lt;code&gt;cornerRadius&lt;/code&gt; in &lt;code&gt;layoutSubviews()&lt;/code&gt; is important because the frame of the view will change as a result of the layout process, and the corner radius size needs to be half of the frame size to make it circular.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class CircleView: UIView {

    // ...

    override func layoutSubviews() {
        super.layoutSubviews()
        if (frame.width != frame.height) {
            NSLog("Ended up with a non-square frame -- so it may not be a circle");
        }
        layer.cornerRadius = frame.width / 2
        layer.masksToBounds = true
    }

    // ...

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Second, when you add your view to your storyboard or XIB, set an Aspect Ratio constraint to make it 1:1 by setting the frame size with equal width and height, and then adding the constraint. This will enforce the square frame (as long as Auto Layout doesn’t break that constraint for some other reason).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KTZwp7kK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.06.32.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-239" src="https://res.cloudinary.com/practicaldev/image/fetch/s--KTZwp7kK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.06.32.png" width="532" height="2006"&gt;&lt;/a&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fv74S1e_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.05.18.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-236" src="https://res.cloudinary.com/practicaldev/image/fetch/s--fv74S1e_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.05.18.png" width="548" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, to tackle the square view problem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q4dIfOns--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.08.21-1.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-235" src="https://res.cloudinary.com/practicaldev/image/fetch/s--q4dIfOns--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-08-at-19.08.21-1.png" width="386" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need one more bit: add &lt;code&gt;@IBDesignable&lt;/code&gt; to your UIView declaration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@IBDesignable class CircleView: UIView {
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And voilà:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HCdlyeXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/DraggedImage.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-238" src="https://res.cloudinary.com/practicaldev/image/fetch/s--HCdlyeXh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/DraggedImage.png" width="386" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While we talked about this specifically for making your circular view should up correctly in Interface Builder, this works anytime you create fully custom views, or Interface Builder’s visualization of a view doesn’t reflect everything you have implemented in code.&lt;/p&gt;

&lt;p&gt;It works because &lt;code&gt;@IBDesignable&lt;/code&gt; is telling Interface Builder is that it should call into the compiled version of your view to do the drawing and layout. With that simple annotation, Interface Builder used the custom &lt;code&gt;layoutSubviews()&lt;/code&gt;, which applied the appropriate circular layer mask, which Interface Builder than displayed.&lt;/p&gt;

&lt;p&gt;Use it to make your storyboards look that much closer to your real app’s interface.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/manual-app-badge-tutorial/"&gt;adding manual app badges to your app&lt;/a&gt; is already waiting for you. &lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/circular-view-interface-builder-ibdesignable/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>interfacebuilder</category>
      <category>xcode</category>
      <category>uikit</category>
    </item>
    <item>
      <title>You can go home again — Using unwind segues to navigate back to previous screens</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Mon, 15 Apr 2019 14:04:06 +0000</pubDate>
      <link>https://forem.com/evandeaubl/you-can-go-home-again-using-unwind-segues-to-navigate-back-to-previous-screens-1e9b</link>
      <guid>https://forem.com/evandeaubl/you-can-go-home-again-using-unwind-segues-to-navigate-back-to-previous-screens-1e9b</guid>
      <description>&lt;p&gt;If you are doing all of your app navigation in storyboards, one of the advantages you have surely discovered is that it’s a great way to specify all of the navigation for your app with minimal code. You may run into this catch, though: specifying a segue for forward navigation is straightforward, but what if you want to specify a segue to dismiss a screen? The most common example of this would be to dismiss a view controller presented modally using a Done button.&lt;/p&gt;

&lt;p&gt;If you search for this on the web, you get all sorts of proposals:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Make a regular segue
&lt;ul&gt;
    &lt;li&gt;This solution is clearly wrong, because you want to remove view controllers from the stack when you dismiss, not add to them&lt;/li&gt;
&lt;/ul&gt;




&lt;/li&gt;

    &lt;li&gt;Dismiss the controller yourself in code

&lt;ul&gt;
    &lt;li&gt;We’re using storyboards to get our navigation out of code, this defeats our purpose&lt;/li&gt;
&lt;/ul&gt;




&lt;/li&gt;

    &lt;li&gt;Write a custom segue to dismiss your view controller

&lt;ul&gt;
    &lt;li&gt;This is closer, but is inflexible and makes reuse of your view controllers more difficult as we’ll touch on later&lt;/li&gt;
&lt;/ul&gt;




&lt;/li&gt;

&lt;/ul&gt;
&lt;br&gt;&lt;br&gt;
The correct solution for flexible navigation backwards in your storyboards is what is called an &lt;em&gt;unwind segue&lt;/em&gt;. The functionality is a little more hidden in Interface Builder than the regular segue — let’s talk about how they work, and how to find and use them in Interface Builder.




&lt;p&gt;Unwind segues work a little bit differently from standard segues, because they need to. Regular segues are normally setup from a control in one view controller to another view controller. Tap the control, trigger the segue, jump to another view controller.&lt;/p&gt;

&lt;p&gt;Unwind segues go to a previous screen in your view hierarchy, which means &lt;strong&gt;you don’t know the destination of an unwind segue upfront.&lt;/strong&gt; Now most of the time, that isn’t true, because you only have one pathway back. But if you are reusing a view controller in your storyboard — perhaps it is one of your standard modal screens — you cannot hardcode a view controller for it to dismiss back to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ciujuFMy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-03-at-10.44.30.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-219" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ciujuFMy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-03-at-10.44.30.png" width="1414" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The storyboard example above illustrates this problem. Unwind segues are built to handle that multiple destination problem in a clever way. Let’s talk about how to define them first, and then we’ll talk about that clever mechanism that iOS uses when the unwind segue is triggered to find the correct view controller to navigate back to.&lt;/p&gt;

&lt;h2&gt;1. Create method to receive unwind segue&lt;/h2&gt;

&lt;p&gt;Another way unwind segues are different is that you don’t receive them using the usual &lt;code&gt;prepare(for segue: UIStoryboardSegue, sender: Any?)&lt;/code&gt; method, because this segue is inverted: it will be processed by the destination view controller, rather than the source. Instead, you define an &lt;code&gt;@IBAction&lt;/code&gt; function on the view controller you are unwinding back to.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@IBAction func modalDismissed(segue: UIStoryboardSegue) {
  // You can use segue.source to retrieve the VC
  // being dismissed to collect any data which needs
  // to be processed
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will define this method for each view controller which you may want to dismiss back to using this unwind segue. For example, multiple different screens which are sharing the same reusable modal view controller. I’ll address how iOS determines which screen to jump back to later in the article.&lt;/p&gt;

&lt;p&gt;Going back to the example storyboard above, both screens will be displaying that view controller, and you will need to unwind back to the correct tab when Done is clicked, so you would add a copy of the above method with the same name to both the First and Second Scene view controllers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; The method signature is very important! It must be an &lt;code&gt;@IBAction&lt;/code&gt;, and it must take a single &lt;code&gt;UIStoryboardSegue&lt;/code&gt; argument, labeled with &lt;code&gt;segue&lt;/code&gt;. Any variance from that, and your method will not be recognized as an unwind segue target by Interface Builder, and therefore will not show up in the next step when you try to link it to your control.&lt;/p&gt;

&lt;h2&gt;2. Connect segue in Interface Builder to dismissing control&lt;/h2&gt;

&lt;p&gt;Once you have that method defined in at least one of your view controllers, you need to connect the control that will be responsible for dismissing the view controller via triggering the unwind segue.&lt;/p&gt;

&lt;p&gt;The easiest way to accomplish this is to select the Exit node in your modal view controller, go to the Connections inspector, and under Presenting Segues, connect the appropriate method to the appropriate control.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wPPc32di--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-03-at-10.53.47.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-220" src="https://res.cloudinary.com/practicaldev/image/fetch/s--wPPc32di--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/04/Screen-Shot-2019-04-03-at-10.53.47.png" width="961" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also Control-drag from the dismissing control’s action outlet to the Exit node of one of the view controllers which implements the unwind segue method. It has the advantage that it makes sure that your segue will unwind correctly (at least for that case), but the first technique is much easier in terms of doing in Interface Builder.&lt;/p&gt;

&lt;p&gt;Whichever technique you use, this only needs to be done once, even if multiple screens may be the target of that unwind segue. Why that is is the subject of the next section.&lt;/p&gt;

&lt;h2&gt;How the unwind segue works at runtime&lt;/h2&gt;

&lt;p&gt;How the unwind is performed when your control is tapped is how the unwind segue navigates you back to the correct screen. When an unwind segue is requested, iOS walks back through the stack of screens you have presented, looking for a view controller with a method matching the signature configured on your dismissing control. The first one it finds becomes the target of the unwind: the VC’s method is called to process the unwind, and the view controller stack is popped back to that view controller. If no matching method is found, the unwind segue is aborted; if your dismissing control doesn’t do anything, look for a missing or incorrectly named method.&lt;/p&gt;

&lt;p&gt;For example, if you have a &lt;code&gt;UITabViewController&lt;/code&gt; with two tabs, and both of them want to display the same modal dialog. When you define your unwind segue method on both screens, when your user dismisses the modal dialog, it will return to the correct screen, because that is the first screen it will find on the view controller stack which implements the appropriate method.&lt;/p&gt;

&lt;p&gt;Going back to the example storyboard one more time, if you trace back what would happen when you tap the Done button, it would pop back through the view controller stack to the Navigation Controller. That doesn’t implement the appropriate method, so it would pop back to either First Scene or Second Scene, depending on which one the button was tapped from. Because the method is implemented for both, it finds it has an unwind target, calls the method, and then dismisses all the view controllers back to the target view controller.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/circular-view-interface-builder-ibdesignable/"&gt;making your circular components actually look circular in Interface Builder&lt;/a&gt; is already waiting for you. &lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/unwind-segues-storyboard/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>uikit</category>
      <category>storyboards</category>
      <category>interfacebuilder</category>
    </item>
    <item>
      <title>Slow, laggy Xcode? Maybe it’s not (just) Xcode…</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Mon, 08 Apr 2019 14:17:12 +0000</pubDate>
      <link>https://forem.com/evandeaubl/slow-laggy-xcode-maybe-it-s-not-just-xcode-3kdn</link>
      <guid>https://forem.com/evandeaubl/slow-laggy-xcode-maybe-it-s-not-just-xcode-3kdn</guid>
      <description>&lt;p&gt;When you’re developing for iOS, there is pretty much no other game in town other than Xcode. And if you’ve needed to use it for any period of time, you know: &lt;strong&gt;it’s a memory hog&lt;/strong&gt;. Not just Xcode, but the iOS simulator, Interface Builder, debugger… You can easily use several GB of memory with just the iOS development tools alone. If you have 8GB of RAM (or 4GB… 😱), it’s enough to bring Xcode to its knees, and your blood pressure to a boil. When your code completion starts lagging to the point you can’t type… 🤬&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s 2019. Shouldn’t your machine be thinking faster than you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But your problem may be more than just Xcode. You may want to look at what else is running on your machine to see if you need to put it on a RAM diet.&lt;/p&gt;




&lt;p&gt;Today, we live in the world of enormous browsers and Electron apps. Browsers are turning into full-fledged operating systems in their own right — and use enough memory to match. And because Electron apps each run their own instance of a web browser (Chrome) to present their app functionality, you could have multiple browser runtimes running on your machine at the same time, each taking 1-2GB of memory a piece. To run a web page. The desktop Slack app is the most cited example of this.&lt;/p&gt;

&lt;p&gt;Run a few of these, and all of a sudden, it isn’t Xcode being the only memory hog. And that doesn’t include the several GB of RAM devoted to the operating system itself.&lt;/p&gt;

&lt;p&gt;Once you’ve filled your memory, everything runs slow, because the operating system needs to decide what to keep in memory. And swap things in and out to your disk to keep the illusion that everything is in memory. Even with our souped-up SSDs, disks are slow.&lt;/p&gt;

&lt;p&gt;Executive summary: Computers are great at multitasking, until they aren’t.&lt;/p&gt;

&lt;p&gt;So if your Xcode is lagging, take a look at what you have open on your machine using Activity Monitor. Use the Memory tab and sort the Memory column to see your major abusers.&lt;/p&gt;

&lt;p&gt;If you have other memory hogs, here are some things you can do:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;If you are using an app to access a web-based service, consider using your web browser. You probably can’t kill your web browser anyway, so you may as well share the overhead.&lt;/li&gt;
    &lt;li&gt;If you have an app that you don’t need open for iOS development, temporarily shut it down to reclaim that memory.&lt;/li&gt;
    &lt;li&gt;Browsers are a pretty opinionated decision, but if you do not have a strong preference, consider switching to a lighter choice. Or perhaps, use that lighterweight browser just during coding sessions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully once Marzipan is fully available, we’ll live in a world of Mac-ified iOS apps that run using much less memory than their Electron counterparts. Until then, practice some memory hygiene to improve your Xcode performance.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/unwind-segues-storyboard/"&gt;using unwind segues to do backwards navigation in storyboards&lt;/a&gt; is already waiting for you. &lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/slow-laggy-xcode-memory/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>xcode</category>
    </item>
    <item>
      <title>Keep your debug toolkit handy but hidden using conditional compilation</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 08 Mar 2019 14:20:44 +0000</pubDate>
      <link>https://forem.com/evandeaubl/keep-your-debug-toolkit-handy-but-hidden-using-conditional-compilation-2309</link>
      <guid>https://forem.com/evandeaubl/keep-your-debug-toolkit-handy-but-hidden-using-conditional-compilation-2309</guid>
      <description>&lt;p&gt;When you’ve been working on an app for a while, especially as it gets large, you often start to include snippets of code in the app that have been useful for debugging your app in the past. Such debugging code may be as simple as log statements, to as complex as adding full screens to your interface, activated by controls that you add to your interface for debugging only.&lt;/p&gt;

&lt;p&gt;Such tools become an integral part of your debugging environment; you don’t want to throw them out. &lt;strong&gt;But do you really want to ship those in your app?&lt;/strong&gt; It makes your app bigger and slower. You could comment them out before you release, but after a marathon debug session, do you trust that you’ll comment out again &lt;strong&gt;all&lt;/strong&gt; of the debugging tools you enabled?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can I keep my debugging addons, but ensure they aren’t in the version I deploy to the App Store?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a way: you can use a feature of Swift called conditional compilation to enable debugging code on your debug build. If you still have Objective-C code, you’re still in luck: a similar feature called preprocessor macros can provide the same functionality.&lt;/p&gt;




&lt;p&gt;We’ll start with the happy path. If you’ve created your project with a recent version of Xcode (at least 9.3, so within the past year or so), you’re already set, and you can skip down to the part where we talk about the code itself (or you can go through it to verify your settings are there).&lt;/p&gt;

&lt;p&gt;If you have an older project, you’ll need to add a couple of build settings for the following code to work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9owJZUP0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-19.03.57.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-195" src="https://res.cloudinary.com/practicaldev/image/fetch/s--9owJZUP0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-19.03.57.png" width="2292" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your project, switch to the Build Settings tab, show All build settings, and select Levels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZvjsDkZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-18.52.35.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-196" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZvjsDkZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-18.52.35.png" width="1726" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find Active Compilation Conditions, and add &lt;code&gt;DEBUG&lt;/code&gt; under the project setting, as above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HCrePGHQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-18.53.12.png" class="article-body-image-wrapper"&gt;&lt;img class="alignnone size-full wp-image-194" src="https://res.cloudinary.com/practicaldev/image/fetch/s--HCrePGHQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.appsdissected.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-28-at-18.53.12.png" width="1726" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have Objective-C code as well, find Preprocessor Macros and add &lt;code&gt;DEBUG=1&lt;/code&gt; to the project setting.&lt;/p&gt;

&lt;p&gt;Once you have those set, you’re ready to hide your debug code.&lt;/p&gt;

&lt;p&gt;Even though the two features have different names, compilation conditions and preprocessor macros, the code to wrap your debug code with is exactly the same, and it’s really easy:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#if DEBUG
   // My debug code is here
#endif
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you do your builds for the simulator and your development devices, all of your debug code will be enabled, ready for you to use. When you build an archive for App Store release or TestFlight, DEBUG will not be defined, and all of that code will disappear, ensuring your app stays fast and lean.&lt;/p&gt;

&lt;p&gt;You can keep all your debugging addons AND keep them to yourself.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/slow-laggy-xcode-memory/"&gt;your Xcode lag not being (entirely) Xcode's fault&lt;/a&gt; is already waiting for you.&lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/hide-debug-code-conditional-compilation/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>objc</category>
    </item>
    <item>
      <title>I’ve done the courses, tutorials, videos. Where do I go from here to get hired?</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Mon, 04 Mar 2019 14:14:59 +0000</pubDate>
      <link>https://forem.com/evandeaubl/ive-done-the-courses-tutorials-videos-where-do-i-go-from-here-to-get-hired-2kcp</link>
      <guid>https://forem.com/evandeaubl/ive-done-the-courses-tutorials-videos-where-do-i-go-from-here-to-get-hired-2kcp</guid>
      <description>&lt;p&gt;You’ve been learning iOS development for months now. You been taking courses, like the &lt;a href="https://itunes.apple.com/us/course/developing-ios-11-apps-with-swift/id1309275316"&gt;Stanford iOS development course&lt;/a&gt;, or maybe something from Udemy. You’ve watched YouTube channels like &lt;a href="https://www.youtube.com/channel/UCuP2vJ6kRutQBfRmdcI92mA"&gt;Let’s Build That App&lt;/a&gt;. You’ve checked out random tutorials on the web from Medium, or you’ve bought some books from &lt;a href="https://www.raywenderlich.com"&gt;Ray Wenderlich&lt;/a&gt; (or even sprung for the full video subscription).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And still you’re frustrated… It doesn’t feel like I’m progressing anymore.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At some point, you realize that all of these resources only take you so far, and that you need something more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the next step between learning, and getting hired?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are several paths from there, but one easy way you can make yourself stand out is to make a “clone app:” an app that replicates the functionality of an existing, well-known app. Let’s talk about the many benefits of doing that.&lt;/p&gt;




&lt;h2&gt;You don’t need your own inspiration&lt;/h2&gt;

&lt;p&gt;Some people at this stage of their development have an idea for an app they want to build. But what if you’re part of the other group that doesn’t? &lt;strong&gt;Building a clone app doesn’t require any bursts of inspiration. Just take your favorite app, and start.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;Something to show to potential employers&lt;/h2&gt;

&lt;p&gt;The more you can show off your abilities to a potential employer, the better you will look. You can talk about your experience and training at an interview, but if you have an app ready to show off, either at your interview or just a Testflight email away, you’re a step ahead of the rest of the pack.&lt;/p&gt;

&lt;h2&gt;You can take it a piece at a time&lt;/h2&gt;

&lt;p&gt;Many of the most popular apps are written by teams of people working full-time. &lt;strong&gt;You don’t need to rewrite the entire app!&lt;/strong&gt; It’s easy for you to break off a piece at a time: a piece of the app structure, a screen, a particular interaction, an animation, etc., and do just that for the moment. &lt;strong&gt;Pick the things you want to build, want to learn.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The opposite applies as well. If you want to work on a screen that is several levels deep in the app, but aren’t ready to work on the screens to get there, skip them for the moment. If you absolutely can’t skip them, fake them just as much as you need to to get to the part you want to work on. Consider using an Xcode playground: you can focus on just what you’re building, and move it into your app codebase when the structure around it is built. &lt;strong&gt;Don’t let the work you don’t want to do (right now) stop you from doing the work you want to do.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can build it up piece by piece. Employers are not going to be expecting you to rewrite the entire Instagram app, but they will be impressed by the parts you have rebuilt.&lt;/p&gt;

&lt;h2&gt;Ability to work with a large codebase&lt;/h2&gt;

&lt;p&gt;When you’ve worked on your courses, exercises, and videos, you have been working on skills and concepts &lt;strong&gt;in isolation&lt;/strong&gt;. Even if you’ve been developing an entire app, they have usually been to illustrate a small number of concepts together, not the complexity of an entire app.&lt;/p&gt;

&lt;p&gt;When you work on a clone app, you begin to see how hard it is to work on a full app codebase:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Working with a large of number of UI storyboards, classes, etc.&lt;/li&gt;
    &lt;li&gt;Knowing where to find things in that codebase&lt;/li&gt;
    &lt;li&gt;Understanding how things in one, seemingly disconnecting part of the codebase, can radically change something in another part&lt;/li&gt;
    &lt;li&gt;Using features that may have not been important for your class apps, but are very important for polished released apps (like publishing your apps…)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many app companies are working on large codebases like this; having experience working this way gives you a head start.&lt;/p&gt;

&lt;h2&gt;Learning more than just iOS development&lt;/h2&gt;

&lt;p&gt;Existing apps almost always have some sort of cloud data storage. Cloning an app is a way to get experience with how to build the backend itself, and integrate it with iOS. If you’re an iOS developer that also has a basic understanding of at least one way of building a backend for an app (Firebase, Realm, REST APIs) and integrating that into an iOS app, you will look much more attractive as a developer than one who has dealt with frontend only.&lt;/p&gt;

&lt;h2&gt;Working through your own problems&lt;/h2&gt;

&lt;p&gt;The tutorials and courses you’ve been working on have been a more guided experience: taking you through sets of exercises that slowly build on a particular concept. At most, you may have had assignments where you had to build something, but it was still probably centered on a particular concept, and because it was a course, the answers you needed were still close at hand.&lt;/p&gt;

&lt;p&gt;When you build your clone app, you will encounter the same problems the original developers had writing the original app, and often the answer will not be as easy as something from your courses and tutorials. This is what makes building a clone app a way to “level up” your skills:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;You learn how to take apart an existing app, breaking it into small pieces you can implement.&lt;/li&gt;
    &lt;li&gt;You experience a wide variety of problems, and you learn the skills of researching, finding, and building solutions on your own.&lt;/li&gt;
    &lt;li&gt;It’s much more like the “real world” experience of building an app to publish to the App Store.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The beauty of this method is that it works no matter how far along you are in your career. Need some experience in new iOS APIs and see an app using them well? See a new trick you want to keep? Clone that app! Learn by seeing, then by doing.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/hide-debug-code-conditional-compilation/"&gt;saving your debug code in your app without shipping it as part of your release&lt;/a&gt; is already waiting for you.&lt;/p&gt;

&lt;p&gt;Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox&lt;/a&gt;, plus newsletter-only tips and deeper dives on website articles and discounts on future product launches.&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/clone-app-learning-getting-hired/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>How Do You Get the Data From Your Custom UITableViewCells?</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 22 Feb 2019 14:36:52 +0000</pubDate>
      <link>https://forem.com/evandeaubl/how-do-you-get-the-data-from-your-custom-uitableviewcells-3fbb</link>
      <guid>https://forem.com/evandeaubl/how-do-you-get-the-data-from-your-custom-uitableviewcells-3fbb</guid>
      <description>&lt;p&gt;You don’t need to progress very far into iOS development before you need to deal with tables. This means: UITableView, and probably your own custom UITableViewCells. A common pattern is to have editable controls in those cells, so that the user can change data from the table itself. Now you’re faced with a problem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you transfer that data back to your UIViewController so the app can use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You know how to do this with standard controls, like UITextFields, UIButtons, etc. But you have a UITableView with a bunch of UITableViewCells. They don’t really behave the same way:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;They’re dynamically constructed by your UITableView&lt;/li&gt;
    &lt;li&gt;There are a variable number of them (usually)&lt;/li&gt;
    &lt;li&gt;Getting access to them from the UITableView is not easy&lt;/li&gt;
    &lt;li&gt;You don’t treat them the same way as “normal” UIViews, such as hooking them up using outlets in Interface Builder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But tear all this away, and &lt;strong&gt;your UITableViewCells are not special snowflakes&lt;/strong&gt;, they are UIViews just like any other. You should treat them exactly that way. Then the answer becomes simple: you do the same thing that Apple does in their UIViews when their controls need to send state back. Use delegates. Here’s how.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.appsdissected.com%2Fwp-content%2Fuploads%2F2019%2F02%2FScreen-Shot-2019-02-11-at-12.17.56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.appsdissected.com%2Fwp-content%2Fuploads%2F2019%2F02%2FScreen-Shot-2019-02-11-at-12.17.56.png" alt="Multiple choice app mockup"&gt;&lt;/a&gt;To set the stage, let’s say you’re writing a multiple choice testing app, where you have a UITableView containing UITableViewCells, each containing 3 buttons to indicate the answers a user could tap. You need to receive that information in order to be able to determine whether the answers are right once the user is complete.&lt;/p&gt;

&lt;p&gt;TK Insert quick screenshot from playground?&lt;/p&gt;

&lt;p&gt;First, define your delegate protocol. How you define it is a matter of personal preference. In this case, we probably don’t need the delegate to understand how the UI for the AnswerCellView is structured, so let’s just send indexes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;protocol AnswerCellViewDelegate {
    func answerCellTapped(answerCellIndex: Int, answerSelected: Int)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now add your delegate to your custom UITableViewCell class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AnswerCellView: UITableViewCell {
    // ...

    weak var delegate: AnswerCellViewDelegate?

    // ...
}

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Make sure you define your delegate variable as weak. Often, the delegate that gets passed in is owned by an outer UIView or the UIViewController. If you don’t define the delegate as weak in the UITableViewCell, you could cause a retain cycle and a memory leak.&lt;/p&gt;

&lt;p&gt;Next, you will need to translate the button taps into calls through the delegate to communicate the state changes (in the case of UIButons, you would have registered these methods using UIButton.addTarget when you built the AnswerViewCell, or hooked them up to outlets if your cell UI is in a XIB):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AnswerViewCell: UITableViewCell {
    // ...

    func button1Tapped() {
        // index is a field set up on construction
        delegate?.answerCellTapped(index, 1)
    }

    func button2Tapped() {
        // index is a field set up on construction
        delegate?.answerCellTapped(index, 2)
    }

    func button3Tapped() {
        // index is a field set up on construction
        delegate?.answerCellTapped(index, 3)
    }

    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this example, we’ll have the UITableView serve as the delegate and collect the information from the individual AnswerViewCells:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class AnswerCellTableView: UITableViewDataSource, AnswerCellViewDelegate {
    // ...
    
    func answerCellClicked(answerCell: AnswerCellView, answer: UIButton) {
        // do the work to keep track of which buttons have been clicked
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&amp;gt; UITableViewCell {
        var answerCell: AnswerCellView
        // construct your AnswerCellView, setting the delegate property on your cell to self
        // ...
        answerCell.delegate = self
        // ...
    }
    
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You could also have your main UIViewController or a view model object implement the delegate, depending on your app’s architecture.&lt;/p&gt;

&lt;p&gt;When you need to collect that information from the AnswerCellTableView, you can either provide an accessor method that the UIViewController can use to get the selected answers, or if you need to receive updates in real-time (such as to commit to an external data store), make your UIViewController the delegate, or if you want to keep proper code separation, repeat the delegate pattern and have the UIViewController give the AnswerCellTableView a delegate object. &lt;a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down" rel="noopener noreferrer"&gt;It’s delegates all the way down!&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/clone-app-learning-getting-hired/" rel="noopener noreferrer"&gt;the advantages of building a clone app to getting hired as an iOS developer&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/" rel="noopener noreferrer"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/uitableviewcell-data-delegates/" rel="noopener noreferrer"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>uikit</category>
      <category>uitableview</category>
      <category>uitableviewcell</category>
    </item>
    <item>
      <title>Porting to Swift? Do it Gradually Using Extensions: Part 1</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 25 Jan 2019 14:16:17 +0000</pubDate>
      <link>https://forem.com/evandeaubl/porting-to-swift-do-it-gradually-using-extensions-part-1-188h</link>
      <guid>https://forem.com/evandeaubl/porting-to-swift-do-it-gradually-using-extensions-part-1-188h</guid>
      <description>&lt;p&gt;Despite the fact that Swift has been available to iOS developers for over 4 years now, it’s likely that many long-lived apps still have Objective-C code in them. To keep things up to date, and to take advantage of the more modern Swift language, you will need to port those at least some of those classes to Swift.&lt;/p&gt;

&lt;p&gt;You are instantly drawn to your small, simple classes, and you think, “Sure, those won’t be a problem at all. I could knock these out in a couple hours a piece.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But then you open up one of your large classes. And you freeze.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You know which one. Every codebase has (at least) one. It is one of the core classes of the app: hundreds (or thousands…) of lines of code, many dependencies on other classes in your codebase. It’s a core part of the app; porting this class and testing that the porting doesn’t completely break everything else could takes weeks. &lt;strong&gt;Nobody has time for “weeks” anymore.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So you surrender, and &lt;strong&gt;those big, hairy Objective-C classes stay big, hairy Objective-C.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It saves unnecessary rework to only refactor code that you are actually changing for another reason. But if you’re only changing one method, you don’t want to port the rest of the class you aren’t touching, because it means extra coding work, extra testing work, extra review work...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a way to port Swift like this, method by method, property by property?&lt;/strong&gt; There is, by writing Swift extensions for your Objective-C classes.&lt;/p&gt;




&lt;p&gt;Extensions allow you to create a separate block of code that extends an existing class definition with additional methods. You can use this feature to gradually port your Objective-C code over to Swift with minimal disruption. The following process comes straight from a porting effort I am doing for one of my own apps, a bowling score tracker called 12 Strikes.&lt;/p&gt;

&lt;p&gt;First, if this is the first time you are porting a particular class, you’ll need to create a new Swift file for that class’s extension, the standard way you would create a new Swift file in Xcode. Afterwards, if your Swift code will need to reference UIKit, add &lt;code&gt;import UIKit&lt;/code&gt; to the top.&lt;/p&gt;

&lt;p&gt;Once you have your &lt;code&gt;.swift&lt;/code&gt; file, add the empty extension definition:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;extension BowlingGame {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should already have a &lt;code&gt;Your Project-Bridging-Header.h&lt;/code&gt;, either from the previous step earlier, or from earlier porting efforts. If not, follow &lt;a href="https://stackoverflow.com/questions/31097484/creating-a-bridging-header"&gt;these instructions&lt;/a&gt; to create one manually. Once you have one, add the matching Objective-C &lt;code&gt;.h&lt;/code&gt; file for the class you’re porting, so that Swift can reference anything from the base Objective-C class:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#import "BowlingGame.h"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you can get down to porting your method. First, comment out the Objective-C method: both the code definition in the &lt;code&gt;.m&lt;/code&gt; file and the declaration in the &lt;code&gt;.h&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;At this point, take a breath and let Xcode rebuild your project. Did your compile succeed without errors? If so, this is a strong indicator that you don’t need to port this code, you just need to delete it. &lt;strong&gt;Don’t port it if you’re not using it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you did get compile errors as you should have, now rewrite your method inside your Swift extension. Be sure to apply the &lt;code&gt;@objc&lt;/code&gt; modifier to the method definition so that the method is accessible from Objective-C:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@objc public static func scoreFrame(firstRoll: String, secondRoll: String) -&amp;gt; Int
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you have unit tests for this method, you &lt;em&gt;could&lt;/em&gt; rewrite those as well, but I recommend against it. You’re trying to rewrite as little as possible at one time. If you do feel the urge to rewrite the tests as well, rewrite them &lt;strong&gt;after&lt;/strong&gt; you have ported the method to Swift and made sure the Swift method passes all of the Objective-C tests. Objective-C tests will be able to test your ported Swift method.&lt;/p&gt;

&lt;p&gt;Finally, if you have Objective-C methods that are dependent on the ported Swift method, then you will also need to add an &lt;code&gt;#import&lt;/code&gt; to import Swift declarations into any &lt;code&gt;.m&lt;/code&gt; or &lt;code&gt;.h&lt;/code&gt; files that reference it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#import "Your_Project-Swift.h"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Once you have ported the method, you can run the app as a sanity check that you ported the code correctly (especially if you didn’t have unit tests…), and once you’re satisfied, remove the commented out Objective-C version.&lt;/p&gt;

&lt;p&gt;Done! From there, it’s simply repeat until the entire class is ported. Although probably not right away. Remember, only port code that you’re changing!&lt;/p&gt;

&lt;p&gt;Now the fine print:&lt;/p&gt;

&lt;p&gt;Many classes will port this easily, but there are some special cases which require some special techniques in order to port from Objective-C to Swift in a method-by-method manner: using advanced Swift data structures, and UIKit. I will cover those in parts 2 and 3 of this series at &lt;a href="https://www.appsdissected.com"&gt;Apps Dissected&lt;/a&gt;. &lt;a href="https://www.appsdissected.com/newsletter/"&gt;Sign up for the newsletter to be notified when those parts come out.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Did you like this tip? &lt;a href="https://www.appsdissected.com/port-objective-c-swift-extensions-2/"&gt;Part 2 of this series on incremental Swift porting&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/port-objective-c-swift-extensions/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>objc</category>
      <category>porting</category>
    </item>
    <item>
      <title>Everybody wants React Native. Should I still learn native iOS?</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 18 Jan 2019 14:12:12 +0000</pubDate>
      <link>https://forem.com/evandeaubl/everybody-wants-react-native-should-i-still-learn-native-ios-4n02</link>
      <guid>https://forem.com/evandeaubl/everybody-wants-react-native-should-i-still-learn-native-ios-4n02</guid>
      <description>&lt;p&gt;The market for mobile developers is larger than ever. There’s a good chance that the reason you started learning iOS development in the first place was to get a full-time job building apps.&lt;/p&gt;

&lt;p&gt;If that is your motivation, you may have looked at job boards and already had feelings of regret about your decision when you see a major requirement many companies ask for:&lt;/p&gt;

&lt;p&gt;React Native.&lt;/p&gt;

&lt;p&gt;Even if you really like native iOS development, you wonder whether you would be more marketable as a candidate by learning React Native instead. “I mean, after all, React Native is still mobile development, and I can claim both iOS and Android development, plus knowledge of JavaScript. That’s good, right?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;”I can give up the platform I love for the platform that gets me paid, right?”&lt;/strong&gt; [cue tiny piece of soul dying inside]&lt;/p&gt;

&lt;p&gt;I’m here to say, you shouldn’t need to. There is more than enough interest in native iOS development that — even if you don’t learn React Native at all — you will have no problem finding a job.&lt;/p&gt;




&lt;p&gt;There are many iOS development shops who are much more interested in preserving the “native feel” of iOS and Android in their apps. Plus, there are high-profile apps, such as AirBnB, that once used React Native, and then decided that native apps were a better choice.&lt;/p&gt;

&lt;p&gt;Long story short: there are still a number of reasons to choose native over React Native. As long as those reasons still exist — and I don’t see many of them going away — there will be demand for native iOS developers.&lt;/p&gt;

&lt;p&gt;One big reason I’ve seen repeat itself is this: cross-platform frameworks come and go. I was head of development for a company where we initially built our mobile apps using a similar cross-platform framework called Titanium. We eventually moved to native apps for both platforms because we wanted to add many features that were very difficult for Titanium to support. Eventually, the interest in Titanium from the industry at large went the same way.&lt;/p&gt;

&lt;p&gt;React Native has built up quite a following, but there is never a guarantee that a third-party dependency will stay up to date with the underlying platform, or stay suitable for your requirements. That is a very compelling reason for a company to stick with native development.&lt;/p&gt;

&lt;p&gt;But maybe you don’t think JavaScript is that bad, and decide to pick up React Native anyway. Knowing native iOS development will still make you more valuable than the average React Native developer:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Many React Native apps are hybrid: either an iOS core with some screens in React Native, or a React Native core with native iOS code extensions. Knowing iOS makes you much more capable of bridging the gap between the two platforms.&lt;/li&gt;
    &lt;li&gt;If things in React Native don’t work quite as expected, you can fall back to your iOS knowledge to help you understand what may be going wrong and how to debug it.&lt;/li&gt;
    &lt;li&gt;If you have knowledge of iOS already, learning React Native will be easier, because you will already be familiar with the concepts at the native level.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;iOS development will be around as long as iOS is around, and iOS doesn’t appear to be going anywhere anytime soon. If you love native iOS development, it’s still a great time to pursue it as a career.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/port-objective-c-swift-extensions/"&gt;porting your Objective-C code to Swift more incrementally using extensions&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/react-native-learn-native-ios/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>react</category>
      <category>reactnative</category>
      <category>career</category>
    </item>
    <item>
      <title>Faster UI Code Reviews Using Screenshot and Video Diffs</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Fri, 28 Dec 2018 15:46:39 +0000</pubDate>
      <link>https://forem.com/evandeaubl/faster-ui-code-reviews-using-screenshot-and-video-diffs-5177</link>
      <guid>https://forem.com/evandeaubl/faster-ui-code-reviews-using-screenshot-and-video-diffs-5177</guid>
      <description>&lt;p&gt;Code review is an integral part of multiple developers working on the same project, whether you are on a team of developers, or contributing changes to public open source projects. In either case, the reviewer needs to be comfortable with your changes before they will merge them.&lt;/p&gt;

&lt;p&gt;This leads to one law of code review: &lt;strong&gt;The clearer it is to the reviewer what changes you made, the faster the reviewer can review and merge your changes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, this gets complicated when you’re developing iOS UI. Whether your team has chosen Storyboards, programmatic UIs, or a combination of the two, reading either Storyboard XML or code diffs is really hard to visualize for anything beyond trivial changes. Worse, if you have a combination of storyboards and code — which is often the case — you can’t necessarily trust that the storyboards before and after even look like what the app does.&lt;/p&gt;

&lt;p&gt;To make the intent of your changes clear, you need another way to show that diff. For larger UI changes, representing those diffs as either screenshots or video is key in making those changes as clear as possible.&lt;/p&gt;




&lt;p&gt;If it is easy enough to get your point across with a before and after screenshot of the UI, then it’s easy to do either through the Simulator or on device.&lt;/p&gt;

&lt;p&gt;Simulator: Press Command-S to take a screenshot.&lt;/p&gt;

&lt;p&gt;On device: Press the sleep button, followed quickly by the home button (or volume up on devices with no home button).&lt;/p&gt;

&lt;p&gt;If you have a multi-step process, or need to show something dynamic, video is the way to go. Quicktime Player can record a video of your interaction with an app either through the Simulator or on device.&lt;/p&gt;

&lt;p&gt;Simulator:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Open Quicktime Player, and select File -&amp;gt; New Screen Recording&lt;/li&gt;
    &lt;li&gt;Drag a box around the simulator screen and then click Start Recording.&lt;/li&gt;
    &lt;li&gt;When done, click the Stop icon in the menu bar, Stop button on the Touch Bar, or press Command-Control-Esc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On device:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;Connect your device to a Mac via lightning cable.&lt;/li&gt;
    &lt;li&gt;Open Quicktime Player, and select File -&amp;gt; New Movie Recording&lt;/li&gt;
    &lt;li&gt;Click the arrow to the right of the record button, and select your device as the Camera and Microphone.&lt;/li&gt;
    &lt;li&gt;Click the record button.&lt;/li&gt;
    &lt;li&gt;When done, click the Stop button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You have a .mov file now, but none of the popular git services or bug trackers accept video attachments. They will however accept animated .gifs, so the last step before upload is to convert your screen capture. Luckily there is a quick open source tool to do that.&lt;/p&gt;

&lt;p&gt;Download &lt;a href="https://github.com/mortenjust/droptogif"&gt;Drop to GIF&lt;/a&gt;, install, and open. It is a simple drag-and-drop interface, although you may want to click the gear to configure settings to make the file smaller. I generally choose to uncheck Match original and set the FPS to 10. The quality slider doesn’t have a huge impact on size, and keeping fidelity in these images is reasonably important, so I generally leave quality at maximum.&lt;/p&gt;

&lt;p&gt;Once you have your .gif, you can easily drag and drop into your Pull Request, if you’re using GitHub, Gitlab, etc., or upload into your bug tracking tool of choice. It’s a little bit of extra work upfront, but pays off by making your code reviews faster for the reviewer — and faster and more successful for you.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/react-native-learn-native-ios/"&gt;whether you should learn native iOS development in a world of React Native jobs&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/faster-ui-code-reviews-screenshot-video-diffs/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>codereview</category>
      <category>userinterface</category>
    </item>
    <item>
      <title>When is a Bool not a Bool?</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Mon, 17 Dec 2018 15:19:04 +0000</pubDate>
      <link>https://forem.com/evandeaubl/when-is-a-bool-not-a-bool-2e53</link>
      <guid>https://forem.com/evandeaubl/when-is-a-bool-not-a-bool-2e53</guid>
      <description>&lt;p&gt;This is a silly question — or rather, it &lt;strong&gt;should&lt;/strong&gt; be a silly question — but it’s going to bite you sometimes when you integrate Objective-C and Swift code together (&lt;strong&gt;&lt;em&gt;cough&lt;/em&gt;&lt;/strong&gt; UIKit).&lt;/p&gt;

&lt;p&gt;You will try to use what you think is a &lt;code&gt;Bool&lt;/code&gt; from an Objective-C API, and suddenly you’re getting this compile error:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Cannot convert value of type ‘ObjCBool’ to expected argument type ‘Bool’
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This &lt;strong&gt;is&lt;/strong&gt; a Boolean value; why can’t I use this @($^ thing as a &lt;code&gt;Bool&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Normally the standard types play nice between Objective-C and Swift. But &lt;code&gt;Bool&lt;/code&gt;s are an unusual case that require a non-obvious solution.&lt;/p&gt;

&lt;p&gt;Objective-C uses &lt;code&gt;BOOL&lt;/code&gt; as the type for Boolean values. In earlier versions of Swift, this was properly bridged to a &lt;code&gt;Bool&lt;/code&gt;. In Swift 3, this changed to a value of type &lt;code&gt;ObjCBool&lt;/code&gt;. When you’re used to the standard types being automatically bridged nicely, it’s jarring when suddenly you have what you think is a &lt;code&gt;Bool&lt;/code&gt;, but it can’t be used like a &lt;code&gt;Bool&lt;/code&gt; anywhere. You get the aforementioned error. It also cannot be cast to a &lt;code&gt;Bool&lt;/code&gt;; that results in a compile-time error as well.&lt;/p&gt;

&lt;p&gt;It turns out that there is a property on &lt;code&gt;ObjCBool&lt;/code&gt; instances called &lt;code&gt;boolValue&lt;/code&gt;, which is responsible for producing a Swift &lt;code&gt;Bool&lt;/code&gt; from the &lt;code&gt;ObjCBool&lt;/code&gt;. So, in the example I was having a problem with, accessing a BOOL property on an Objective-C object:&lt;/p&gt;

&lt;pre class=""&gt;&lt;code&gt;let val = objcObject.aBool // This is of type ObjCBool
let boolVal = objcObject.aBool.boolValue // This is actually a Bool
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’s aggravating when Swift itself isn’t very Swift-like, isn’t it?&lt;/p&gt;

&lt;p&gt;If you need to go the other direction, that is thankfully more obvious:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;let objectiveCBool = ObjCBool(swiftBoolVal)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Maybe one of these days we will be able to put Objective-C behind us all together. Until then, little workarounds like this are going to be part of the game.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/faster-ui-code-reviews-screenshot-video-diffs/"&gt;speeding up iOS UI code reviews by including screenshot or video diffs&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/bool-objcbool-swift/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>objc</category>
    </item>
    <item>
      <title>Force unwrapping is not just “not Swift-like.” It’s wrong.</title>
      <dc:creator>Evan Deaubl</dc:creator>
      <pubDate>Mon, 10 Dec 2018 14:22:47 +0000</pubDate>
      <link>https://forem.com/evandeaubl/force-unwrapping-is-not-just-not-swift-like-its-wrong-gcm</link>
      <guid>https://forem.com/evandeaubl/force-unwrapping-is-not-just-not-swift-like-its-wrong-gcm</guid>
      <description>&lt;p&gt;Swift comes with a number of features that help developers write correct bug-free programs: optionals, safe casting, and built-in error handling. But for every one of these, there is an escape hatch: &lt;code&gt;!&lt;/code&gt;, the force unwrapping operator.&lt;/p&gt;

&lt;p&gt;You may know another developer or team member who plays a little fast and loose with force unwrapping. Or you don’t feel like doing the additional boilerplate to unwrap an optional, so you do it when “nobody’s looking.”&lt;/p&gt;

&lt;p&gt;You may not have a good argument for why safe unwrapping is good and force unwrapping is bad, other than that the Swift documentation says so, or “that’s how it’s done.”&lt;/p&gt;

&lt;p&gt;The reason behind safe unwrapping comes from a long history of languages that didn’t provide strong safeties such as these. This often resulted in trying to interpret random memory locations as objects, resulting in crashes at best, hard to debug app behavior at worst. Not using all of Swift’s safety mechanisms at your disposal is not just not Swift-like, it is bad programming.&lt;/p&gt;




&lt;p&gt;Swift does a lot to make safe unwrapping easy to use, but sometimes the draw to use &lt;code&gt;!&lt;/code&gt; is very attractive. Just drop it in your code and you can ignore a bunch of nil checking or error catching or type casting you would normally need to. That is the wrong way to think about it; &lt;strong&gt;you shouldn’t think of &lt;code&gt;!&lt;/code&gt; as a way out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;!&lt;/code&gt; is saying that you know better than your compiler; that you can reason through all the paths and uses of your code, not just now, but every possible use in the future, and decide that your force unwrapping is safe. &lt;strong&gt;NEWS FLASH:&lt;/strong&gt; Compilers reason about code; interpreting code to produce executable output is their sole reason for existing. They will do a better job than you will at keeping you safe.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;!&lt;/code&gt; operator is a good choice of character — okay, maybe 🚨 would have been better, or 🔥 — because &lt;strong&gt;you should be alarmed&lt;/strong&gt; anywhere you see it in your code. Everywhere you see the &lt;code&gt;!&lt;/code&gt; operator, either defining an implicitly unwrapped property, after an Optional, &lt;code&gt;as!&lt;/code&gt;, or &lt;code&gt;try!&lt;/code&gt;, you shouldn’t think “this is going to be fine, so I’m force unwrapping.” You should think, “This is a place where I have specified that my code can crash.” When you frame it in those terms, you will feel much more motivated to code in ways that avoid that situation in the first place.&lt;/p&gt;

&lt;p&gt;You might be saying right now, “But I need to interface with Objective-C NSDictionarys or NSArrays, and I know they contain all Strings, or all Integers, so I want to just force unwrap it and move on.” You can — and should — still use safe unwrapping and casting on NSDictionarys and NSArrays.&lt;/p&gt;

&lt;p&gt;Consider this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var foo: NSArray = NSArray(arrayLiteral: 5, 6, 7)

if let bar = foo as? [Int] {
  print(bar.reduce(0, +))
}

if let bar2 = foo as? [String] {
  print(bar2)
}
// Will not print
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The safe cast checks all of the elements immediately, so the first &lt;code&gt;if let&lt;/code&gt; prints the sum of the elements of the NSArray, while the second &lt;code&gt;if let&lt;/code&gt; falls through because the elements are not Ints. Do this as soon as you can after receiving an NSArray, NSDictionary, or other loose Objective-C type, then your Swift code will work with the stricter Swift types exclusively.&lt;/p&gt;

&lt;p&gt;If you have a force unwrapping, casting, or &lt;code&gt;try!&lt;/code&gt; in your code, there is almost always some way you can restructure your code to make it safe. Get rid of your &lt;code&gt;!&lt;/code&gt;s; your future self will thank you for it.&lt;/p&gt;




&lt;p&gt;Did you like this tip? The next tip on &lt;a href="https://www.appsdissected.com/bool-objcbool-swift/"&gt;a compile-time error you may run into using Objective-C BOOLs in Swift&lt;/a&gt; is already waiting for you. Or &lt;a href="https://www.appsdissected.com/newsletter/"&gt;sign up to get every tip straight to your inbox.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post originally published at &lt;a href="https://www.appsdissected.com/force-unwrapping-not-swift-like-wrong/"&gt;Apps Dissected.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
    </item>
  </channel>
</rss>
