<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>iOS Development on Ivan: Thinking</title>
    <link>https://ivanthinking.net/tags/ios-development/</link>
    <description>Recent content in iOS Development on Ivan: Thinking</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://ivanthinking.net/tags/ios-development/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Technology is not enough</title>
      <link>https://ivanthinking.net/2026/04/20/technology-is-not-enough/</link>
      <pubDate>Mon, 20 Apr 2026 16:47:31 -0700</pubDate>
      <guid>https://ivanthinking.net/2026/04/20/technology-is-not-enough/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://daringfireball.net/2023/02/making_our_hearts_sing&#34;&gt;Daring Fireball&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Either you know that software can be art, and often should be, or you think what I’m talking about here is akin to astrology. One thing I learned long ago is that people who prioritize &lt;a href=&#34;https://ivanthinking.net/tags/design/&#34;&gt;design&lt;/a&gt;, UI, and UX in the software they prefer can empathize with and understand the choices made by people who prioritize other factors (e.g. raw feature count, or the ability to tinker with their software at the system level, or software being free-of-charge). But it doesn’t work the other way: most people who prioritize other things can’t fathom why anyone cares deeply about design/UI/UX &lt;em&gt;because they don’t perceive it&lt;/em&gt;. Thus they chalk up iOS and native Mac-app enthusiasm to being hypnotized by marketing.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Moving along on Ready Time relaunch</title>
      <link>https://ivanthinking.net/2026/04/15/moving-along-on-ready-time-relaunch/</link>
      <pubDate>Wed, 15 Apr 2026 22:33:19 -0700</pubDate>
      <guid>https://ivanthinking.net/2026/04/15/moving-along-on-ready-time-relaunch/</guid>
      <description>&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.reddit.com/r/SideProject/comments/1sml19i/relaunched_my_app_backward_planner_for_people_who/&#34;&gt;Posted on r/SideProject&lt;/a&gt;. Had a little hiccup since my original post was filtered by reddit&amp;rsquo;s spam filter (boo!), but re-submitted a day later with fewer links in the post. I&amp;rsquo;d also been dormant on reddit for a while, so it may have smelled like spam with the initial post.&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Found out there&amp;rsquo;s an &lt;a href=&#34;https://www.readyby.app&#34;&gt;app by the name of ReadyBy&lt;/a&gt; with the same concept. After checking it out, it reinforces that I think my change from subscription to one-time premium upgrade makes sense (ReadyBy is a subscription model).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Published &lt;a href=&#34;https://ivanthinking.net/2026/04/14/3am-bring-the-car-seat/&#34;&gt;blog post&lt;/a&gt; about how Ready Time saved the day when wife went into labor. This has been a long time coming. Finally buckled down to write this thing out.&lt;/li&gt;&#xA;&lt;li&gt;Submitted to &lt;a href=&#34;https://indieappcatalog.com&#34;&gt;Indie App Catalog&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Shared with some friends who&amp;rsquo;ve been giving me some feedback on the app.&lt;/li&gt;&#xA;&lt;li&gt;Been warming up my profile on &lt;a href=&#34;https://www.indiehackers.com&#34;&gt;Indie Hackers&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>It&#39;s like gonna have like this tab</title>
      <link>https://ivanthinking.net/2026/04/14/its-like-gonna-have-like-this-tab/</link>
      <pubDate>Tue, 14 Apr 2026 11:30:37 -0700</pubDate>
      <guid>https://ivanthinking.net/2026/04/14/its-like-gonna-have-like-this-tab/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.swiftjectivec.com/kids-and-vibe-coding-ios-apps/&#34;&gt;Kids and Vibe Coding&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;It’s easy for &lt;em&gt;us&lt;/em&gt; to spot the issues. However, the bit that’s surprised me, though, is that they are…aware of it? Even as a 9 year old. Is this a potential byproduct of growing up in the digital age? They know it doesn’t feel right, and they can’t really say why yet, they just know it feels off.&lt;/p&gt;&#xA;&lt;p&gt;That’s hardly surprising, as &lt;a href=&#34;https://ivanthinking.net/tags/design/&#34;&gt;design&lt;/a&gt; and user experience are things that take years and years to develop.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ready Time</title>
      <link>https://ivanthinking.net/2026/04/07/ready-time/</link>
      <pubDate>Tue, 07 Apr 2026 16:32:03 -0700</pubDate>
      <guid>https://ivanthinking.net/2026/04/07/ready-time/</guid>
      <description>&lt;p&gt;We&amp;rsquo;re always underestimating how long things take:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;mornings with a kid&lt;/li&gt;&#xA;&lt;li&gt;catching a flight&lt;/li&gt;&#xA;&lt;li&gt;getting out the door for dinner&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It always feels like there&amp;rsquo;s enough time until suddenly there isn&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://getreadytime.com&#34;&gt;Ready Time&lt;/a&gt; works backward from your deadline. You add your steps: shower, pack lunch, get the kid&#xA;dressed, drive. Then you set when you need to be done. It calculates when to start each step and sends you a&#xA;notification when it&amp;rsquo;s time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Getting Ready for Ready Time</title>
      <link>https://ivanthinking.net/2026/03/30/getting-ready-for-ready-time/</link>
      <pubDate>Mon, 30 Mar 2026 20:53:39 -0700</pubDate>
      <guid>https://ivanthinking.net/2026/03/30/getting-ready-for-ready-time/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://getreadytime.com&#34;&gt;Ready Time&lt;/a&gt; is the rebranded name for &lt;a href=&#34;https://ivanthinking.net/category/little-countdown/&#34;&gt;Little Countdown&lt;/a&gt;. Domain: check. Website: &lt;a href=&#34;https://getreadytime.com&#34;&gt;check&lt;/a&gt;. App update: almost.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Time Lock, New Premium Feature</title>
      <link>https://ivanthinking.net/2026/01/14/time-lock-new-premium-feature/</link>
      <pubDate>Wed, 14 Jan 2026 06:11:12 +0000</pubDate>
      <guid>https://ivanthinking.net/2026/01/14/time-lock-new-premium-feature/</guid>
      <description>&lt;p&gt;Sometimes you need a task to happen at a specific time. Maybe you need to leave for the airport at exactly 3:00 PM, or you have a hard deadline to be at a meeting at 10:00 AM. Little Countdown normally schedules all your tasks backward from your deadline, but that doesn&amp;rsquo;t work when one task needs to happen at a fixed time.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Time Lock&lt;/strong&gt; lets you set a fixed start time for any Task in your Countdown. When you lock a task to a specific time, Little Countdown schedules the rest of your timeline around it:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Development login credentials in Xcode</title>
      <link>https://ivanthinking.net/2023/04/24/development-login-credentials-in-xcode/</link>
      <pubDate>Mon, 24 Apr 2023 12:08:51 -0400</pubDate>
      <guid>https://ivanthinking.net/2023/04/24/development-login-credentials-in-xcode/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://www.danijelavrzan.com/posts/2023/04/login-xcode-breakpoint/&#34;&gt;Danijela Vrzan&lt;/a&gt; posted&#xA;a very cool solution to streamlining entering login credentials in Xcode and the iOS Simulator&#xA;using breakpoints. I&amp;rsquo;ll admit that I probably haven&amp;rsquo;t fully unlocked the&#xA;full potential of Xcode breakpoints in my development workflow.&lt;/p&gt;&#xA;&lt;p&gt;If you&amp;rsquo;re an app developer, no doubt you&amp;rsquo;ve run into the case where you&amp;rsquo;re tediously&#xA;typing in your auth username and passwords every time you rebuild/relaunch&#xA;the Simulator. It gets old pretty quickly when you&amp;rsquo;re trying to quickly&#xA;make updates or fix a bug in your app.&lt;/p&gt;</description>
    </item>
    <item>
      <title>iOS Developer Resources</title>
      <link>https://ivanthinking.net/2022/10/04/ios-developer-resources/</link>
      <pubDate>Tue, 04 Oct 2022 23:58:18 -0400</pubDate>
      <guid>https://ivanthinking.net/2022/10/04/ios-developer-resources/</guid>
      <description>&lt;h2 id=&#34;developer-news-and-community&#34;&gt;&#xA;  Developer News and Community&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#developer-news-and-community&#34;&gt;&#xA;    &lt;i class=&#34;fa fa-link&#34; aria-hidden=&#34;true&#34;&gt;&lt;/i&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;If I could give any advice to all new iOS developers, it&amp;rsquo;s that they should&#xA;keep up with the ever-changing iOS ecosystem. Apple pushes out a new&#xA;version of iOS every year, so it&amp;rsquo;s important (and exciting!) to keep up&#xA;with the latest going on in the world of iOS Developmenet. I like to keep&#xA;my ears on the ground with these resources.&lt;/p&gt;</description>
    </item>
    <item>
      <title>SwiftUI: Link phone numbers, emails, URLs in Text without Markdown</title>
      <link>https://ivanthinking.net/2022/09/20/swiftui-link-phone-numbers-emails-urls-in-text-without-markdown/</link>
      <pubDate>Tue, 20 Sep 2022 17:54:51 -0400</pubDate>
      <guid>https://ivanthinking.net/2022/09/20/swiftui-link-phone-numbers-emails-urls-in-text-without-markdown/</guid>
      <description>&lt;p&gt;SwiftUI provides an easy way to link URLs and emails inside of a &lt;code&gt;Text&lt;/code&gt; view&#xA;using &lt;code&gt;AttributedString&lt;/code&gt;&amp;rsquo;s markdown initializer:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; text = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Jenny&amp;#39;s at 867-5309.&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; Email her at jenny@tutone.net.&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; Find out more: https://en.wikipedia.org/wiki/867-5309/Jenny&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;VStack {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Text(&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;! AttributedString(markdown: text))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, this has a few shortcomings:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;the phone number isn&amp;rsquo;t linked/tappable&lt;/li&gt;&#xA;&lt;li&gt;we may not want all the markdown rendering: bullets (&lt;code&gt;*&lt;/code&gt;) and brackets (&lt;code&gt;[]&lt;/code&gt;) in the text may end up rendering with unexpected results&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;We can use &lt;code&gt;NSDataDetector&lt;/code&gt; instead to help us construct our own&#xA;&lt;code&gt;AttributedString&lt;/code&gt; that can detect phone numbers and also prevent the user&#xA;from accidentally injecting markdown:&lt;/p&gt;</description>
    </item>
    <item>
      <title>CoreData: All that is left to us is honor</title>
      <link>https://ivanthinking.net/2022/06/07/coredata-all-that-is-left-to-us-is-honor/</link>
      <pubDate>Tue, 07 Jun 2022 17:08:51 -0700</pubDate>
      <guid>https://ivanthinking.net/2022/06/07/coredata-all-that-is-left-to-us-is-honor/</guid>
      <description>&lt;p&gt;&#xA;&#xA;  &lt;img class=&#34;page-img&#34; src=&#34;https://ivanthinking.net/images/coredata-all-that-is-left-honor.png&#34; alt=&#34;NSMAnagedObjectContext__MultiThreading_Violation_AllThatIsLeftToUsIsHonor__&#34;  /&gt;&#xA;&#xA;&#xA;&lt;em&gt;My life for Aiur&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;how-to-do&#34;&gt;&#xA;  How to do?&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#how-to-do&#34;&gt;&#xA;    &lt;i class=&#34;fa fa-link&#34; aria-hidden=&#34;true&#34;&gt;&lt;/i&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Add &lt;code&gt;-com.apple.CoreData.ConcurrencyDebug 1&lt;/code&gt; to your Xcode &lt;a href=&#34;https://www.donnywals.com/using-launch-arguments-for-easier-core-data-debugging/&#34;&gt;launch arguments&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Execute some &lt;a href=&#34;https://medium.com/bpxl-craft/some-lessons-learned-on-core-data-5f095ecb1882&#34;&gt;non-thread safe CoreData code&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Crash, but at least you&amp;rsquo;ll still have your dignity.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;see-also&#34;&gt;&#xA;  See also&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#see-also&#34;&gt;&#xA;    &lt;i class=&#34;fa fa-link&#34; aria-hidden=&#34;true&#34;&gt;&lt;/i&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://davedelong.com/blog/2018/05/09/the-laws-of-core-data/&#34;&gt;The Laws of Core Data&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/33575664/xcode-multithreading-violationall-that-is-left-to-us-is-honor-cocoa&#34;&gt;Stack Overflow&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>iPhone Upgrade Program vs Buying, Trade In</title>
      <link>https://ivanthinking.net/2020/12/05/iphone-upgrade-program-vs-buying-trade-in/</link>
      <pubDate>Sat, 05 Dec 2020 17:22:26 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/12/05/iphone-upgrade-program-vs-buying-trade-in/</guid>
      <description>&lt;p&gt;Every year, when Apple makes its big announcement about the new iPhone being the most amazing device ever, you&amp;rsquo;re wondering whether you should upgrade or not. You consider whether the new features are worth it or whether you want a better camera or a better battery life.&lt;/p&gt;&#xA;&lt;p&gt;Maybe your iPhone&amp;rsquo;s becoming gruelingly slow because you&amp;rsquo;re 3 years behind. Or maybe you can tell that your battery life is incrementally dying away with each night&amp;rsquo;s recharge.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Swift: Immutable Struct Singleton Initialization</title>
      <link>https://ivanthinking.net/2020/05/29/swift-immutable-struct-singleton-initialization/</link>
      <pubDate>Fri, 29 May 2020 11:10:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/05/29/swift-immutable-struct-singleton-initialization/</guid>
      <description>&lt;p&gt;How can you initialize a &lt;code&gt;struct&lt;/code&gt; singleton that has dependencies? You likely chose to use a &lt;code&gt;struct&lt;/code&gt; because you&amp;rsquo;re trying to reduce state and keep things immutable in your code. You&amp;rsquo;re also likely wanting to use the singleton pattern for a shared service or model in your project.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;m a fan of keeping things immutable if possible, and I &lt;a href=&#34;https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes&#34;&gt;default&lt;/a&gt; to &lt;code&gt;struct&lt;/code&gt;s and &lt;code&gt;let&lt;/code&gt;s before using &lt;code&gt;class&lt;/code&gt;es, or &lt;code&gt;var&lt;/code&gt;s.&lt;/p&gt;&#xA;&lt;p&gt;One place I&amp;rsquo;ll use this pattern is when making services that depend on an external API like so:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Fastlane: Downloading AppStore Metadata</title>
      <link>https://ivanthinking.net/2020/05/28/fastlane-downloading-appstore-metadata/</link>
      <pubDate>Thu, 28 May 2020 10:38:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/05/28/fastlane-downloading-appstore-metadata/</guid>
      <description>&lt;p&gt;Just like we use &lt;code&gt;git&lt;/code&gt; to be able to audit changes to our code over time, doing so with our app&amp;rsquo;s AppStore metadata lets us keep an eye on changes made to our AppStore page as well.&lt;/p&gt;&#xA;&lt;p&gt;The first step in getting more control of our metadata is by having it live in our project&amp;rsquo;s repository. Keeping a copy of our metadata in &lt;code&gt;git&lt;/code&gt; lets us keep track of changes to our app&amp;rsquo;s description, keywords, and even screenshots over time.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Swift: Converting String to Date</title>
      <link>https://ivanthinking.net/2020/05/20/swift-converting-string-to-date/</link>
      <pubDate>Wed, 20 May 2020 12:20:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/05/20/swift-converting-string-to-date/</guid>
      <description>&lt;p&gt;When consuming an API response, we&amp;rsquo;ll often see an &lt;a href=&#34;https://en.wikipedia.org/wiki/ISO_8601&#34;&gt;ISO 8601 formatted date&lt;/a&gt; &lt;code&gt;String&lt;/code&gt; like this:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2020-04-20T16:20:42+02:00&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a &lt;code&gt;String&lt;/code&gt;, it&amp;rsquo;s not really useful for us, as it&amp;rsquo;s not really something you want to show your users.&#xA;We may want to be able to extract just the hour, calculate the time interval between this date and others, or just format it in a way that&amp;rsquo;s more meaningful for the user.&#xA;To do that, we can convert the &lt;code&gt;String&lt;/code&gt; to a &lt;code&gt;Date&lt;/code&gt; object.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Horizontal Stack Content Hugging</title>
      <link>https://ivanthinking.net/2020/05/19/horizontal-stack-content-hugging/</link>
      <pubDate>Tue, 19 May 2020 11:14:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/05/19/horizontal-stack-content-hugging/</guid>
      <description>&lt;p&gt;In your iOS app, you&amp;rsquo;ve got a &lt;a href=&#34;https://developer.apple.com/documentation/uikit/uistackview&#34;&gt;Horizontal Stack&lt;/a&gt; with subviews layed out like so:&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;  &lt;img class=&#34;page-img&#34; src=&#34;https://ivanthinking.net/images/software-dev/hstack-hugging01.png&#34; alt=&#34;Horizontal Stack: default content hugging&#34;  /&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;viewDidLoad&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt;.viewDidLoad()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; loveLabel = UILabel()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loveLabel.text = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;LOVE&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    loveLabel.backgroundColor = .systemRed&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; kissesLabel = UILabel()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    kissesLabel.text = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Kisses&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    kissesLabel.backgroundColor = .systemYellow&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; xoxoLabel = UILabel()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    xoxoLabel.text = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;XOXO&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    xoxoLabel.backgroundColor = .systemBlue&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; stack = UIStackView(arrangedSubviews: [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        loveLabel,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        kissesLabel,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        xoxoLabel,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stack.translatesAutoresizingMaskIntoConstraints = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stack.axis = .horizontal&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stack.spacing = &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    view.addSubview(stack)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLayoutConstraint.activate([&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stack.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        view.rightAnchor.constraint(equalToSystemSpacingAfter: stack.rightAnchor, multiplier: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;hmm-a-bit-too-much-love&#34;&gt;&#xA;  Hmm, a bit too much LOVE&#xA;  &lt;a class=&#34;heading-link&#34; href=&#34;#hmm-a-bit-too-much-love&#34;&gt;&#xA;    &lt;i class=&#34;fa fa-link&#34; aria-hidden=&#34;true&#34;&gt;&lt;/i&gt;&#xA;  &lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;But what if you really want is to see less of that &lt;code&gt;LOVE&lt;/code&gt; and more of those &lt;code&gt;Kisses&lt;/code&gt;?&lt;/p&gt;</description>
    </item>
    <item>
      <title>Adding an Instructional Overlay for first time users to your app in iOS</title>
      <link>https://ivanthinking.net/2020/05/16/adding-an-instructional-overlay-for-first-time-users-to-your-app-in-ios/</link>
      <pubDate>Sat, 16 May 2020 13:04:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2020/05/16/adding-an-instructional-overlay-for-first-time-users-to-your-app-in-ios/</guid>
      <description>&lt;p&gt;Sometimes called &lt;em&gt;Coachmarks&lt;/em&gt;, a &lt;em&gt;Wizard&lt;/em&gt;, or an &lt;em&gt;Onboarding Flow&lt;/em&gt;, this common UX pattern is used to guide first time users to an app on its features in your UI.&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;  &lt;img class=&#34;page-img&#34; src=&#34;https://ivanthinking.net/images/software-dev/coach-marks01.png&#34; alt=&#34;Instructional Overlay&#34;  /&gt;&#xA;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;Here’s a quick and simple way to implement this pattern:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;buildButton&lt;/span&gt;(with title: String) -&amp;gt; UIButton {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; button = UIButton(type: .system)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    button.backgroundColor = .systemOrange&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    button.setTitle(title, &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt;: .normal)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; button&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;viewDidLoad&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt;.viewDidLoad()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; buttonText = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Put me in coach!&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; button = buildButton(with: buttonText)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    button.translatesAutoresizingMaskIntoConstraints = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; overlay = UIView(frame: .zero)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    overlay.translatesAutoresizingMaskIntoConstraints = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    overlay.backgroundColor = UIColor.black.withAlphaComponent(&lt;span style=&#34;color:#ae81ff&#34;&gt;0.5&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; coachButton = buildButton(with: buttonText)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coachButton.translatesAutoresizingMaskIntoConstraints = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coachButton.isUserInteractionEnabled = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; coachLabel = UILabel(frame: .zero)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coachLabel.translatesAutoresizingMaskIntoConstraints = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coachLabel.textColor = .white&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coachLabel.text = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Get player in the game&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    view.addSubview(button)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    view.addSubview(overlay)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    view.addSubview(coachButton)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    view.addSubview(coachLabel)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLayoutConstraint.activate([&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        button.centerXAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.centerXAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        button.centerYAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.centerYAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        coachButton.centerXAnchor.constraint(equalTo: button.centerXAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        coachButton.centerYAnchor.constraint(equalTo: button.centerYAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        coachLabel.centerXAnchor.constraint(equalTo: coachButton.centerXAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        coachLabel.centerYAnchor.constraint(equalTo: coachButton.bottomAnchor, constant: &lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        overlay.topAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.topAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        overlay.bottomAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.bottomAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        overlay.leftAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.leftAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        overlay.rightAnchor.constraint(equalTo: &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.view.rightAnchor),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ])&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The idea here is that you have a duplicate button on top of a semi-transparent overlay. We use Auto Layout to constrain &lt;code&gt;coachButton&lt;/code&gt; to the real &lt;code&gt;button&lt;/code&gt;, and we also disable  &lt;code&gt;isUserInteractionEnabled&lt;/code&gt; since we don’t actually want the user to be able to select it in this flow.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Bitrise: Mobile CI Service</title>
      <link>https://ivanthinking.net/2019/06/06/bitrise-mobile-ci-service/</link>
      <pubDate>Thu, 06 Jun 2019 19:53:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2019/06/06/bitrise-mobile-ci-service/</guid>
      <description>&lt;p&gt;With the small iOS team at Hipmunk, having to maintain a box to run Xcode Server would have been costly in terms of:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Buying hardware&lt;/li&gt;&#xA;&lt;li&gt;Upgrading/maintaining the hardware&lt;/li&gt;&#xA;&lt;li&gt;Keeping the OS/software up to date&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Furthermore, we’d have to find a separate solution for our Android team and gain expertise on maintaining their CI as well.&lt;/p&gt;&#xA;&lt;p&gt;We ended up deciding to use &lt;a href=&#34;https://www.bitrise.io&#34;&gt;Bitrise&lt;/a&gt;, a continuous integration and delivery service designed primarily for mobile platforms.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Automated Beta/Internal Change Notes with Fastlane</title>
      <link>https://ivanthinking.net/2019/06/02/automated-beta/internal-change-notes-with-fastlane/</link>
      <pubDate>Sun, 02 Jun 2019 16:51:01 -0700</pubDate>
      <guid>https://ivanthinking.net/2019/06/02/automated-beta/internal-change-notes-with-fastlane/</guid>
      <description>&lt;p&gt;Do your TestFlight or Crashlytics have change notes that say something useless like &lt;code&gt;Fixed bugs&lt;/code&gt;? This is probably as useful as the equally ambiguous commit message &lt;code&gt;fixed&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Or maybe you painstakingly look through your PRs to find out what changes went in since your last release and scribble something out quickly so you can just get the build ready for your product or testing teams.&lt;/p&gt;&#xA;&lt;p&gt;This process of writing up beta/internal change notes can be streamlined and save devs precious brain cells that can be used for more valuable decision making.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
