blog.iankulin.com

Posts

Where's My App?

My short guide to building a release version of a macOS app in Xcode and finding the resulting .app bundle. I cover creating a new scheme set to Release builds, running the build, and using “Show Build Folder in Finder” to locate the .app file so it can be copied into the Applications folder...

Customizing the default About dialog for MacOS apps

A short how-to on how I customize the default About dialog in a macOS app built with Xcode: add a Credits.rtf (or .html or .rtfd) file to the project, and its contents appear in the dialog after a rebuild...

CodeTrimmer - First MacOS App

Inspired by a StackTrace podcast episode about automating small development tasks, I built my first macOS app with SwiftUI: a utility that strips excess leading indentation from code copied out of Xcode, a chore I previously did by hand before pasting code samples into my blog posts. Screenshots show the paste-and-strip workflow, and I found the move from SwiftUI iOS development to macOS nearly effortless. My source code is linked...

Design Challenge

I give a progress update on translating an external designer’s UI into SwiftUI, covering the rounded-rectangle elements I’ve completed and the .offset modifier I used to create an overlapping layout. My remaining work includes a custom picker and a combined picker/progress indicator...

Color Picker (website)

A short note on using ImageColorPicker, a browser-based tool for identifying colors in an image, while recreating a designer-provided UI in SwiftUI. The site returns RGB values out of 255, which I divide by 255 to get the CGFloat values required by SwiftUI’s Color initializer...

Design Help

Frustrated with the design of my Times Table app, I hired two UX designers through Fiverr to redesign it with kids in mind. I share both drafts and give feedback on each — layout, colors, how to show right and wrong answers — and consider which elements I could realistically implement with my current iOS skills...

iExpense Challenges

Day 38 of my 100 Days of SwiftUI challenge covers three exercises on the iExpense app: showing amounts in the user’s preferred currency (navigating a deprecated Locale API), applying conditional styling based on expense value, and splitting the expense list into personal and business sections. The list-splitting required me to wrap conditionals in a Group to satisfy the compiler’s ViewBuilder type checks...

Times Tables -Day 35 Challenge

My write-up of the Day 35 challenge from 100 Days of SwiftUI: building a times tables drilling app. I cover creating a custom number keypad and replacing the standard iOS modal with a ZStack-based overlay, finding that tap events pass through very transparent overlays but not more solid ones. I also note the finished app is plain-looking and that improving visual design is now a goal...

Gitting Xcode to Push

I explain how to fix Xcode failing to push to GitHub after GitHub stopped accepting RSA keys that use SHA-1. My solution, based on an Apple Developer forum answer, is to switch to a new ECDSA SSH key — with the one step the forum post missed being a restart of Xcode to make it take effect...

Calculator

While building a calculator-style answer keypad for a multiplication tables practice app, I follow an iOS Academy video that recreates the iOS Calculator in SwiftUI and enjoy spotting edge cases the tutorial’s quick implementation leaves unhandled. I also reflect on copying existing Apple apps as a way to skip design work, and on wanting to improve at design over time...

User Defaults & Horizontal Pickers

Day 35 of the 100 Days of SwiftUI challenge, which I spent building a multiplication tables drill app for kids. I cover persisting the user’s table selection with UserDefaults (including an enum to avoid hard-coded key strings and a fallback for missing values), plus a Stack Overflow trick for building a compact horizontal wheel picker using paired rotationEffects...

Gitting up to date

I explain how to bring a feature branch’s changes back into the main branch, comparing merge, squash merge, and rebase with example commit histories. I close with a note on why rebasing commits that have been pushed to a shared repository is considered bad practice. Branching per feature is part of my effort to become more competent with git...

iOS Academy

I briefly recommend Afraz Siddiqui’s iOS Academy YouTube channel, which features iOS development tutorials, including shorter focused videos such as one covering the new SwiftUI chart views...

Ranges

A follow-up to my previous post about the difference between writing a SwiftUI ForEach range as 1..<21 versus 1…20. I found the answer in a Hacking with Swift Day 34 article, which indicates older versions of Swift might not have allowed the closed-range form...

Animating Guess The Flag

This is a write-up of Project 6 of 100 Days of SwiftUI, which adds animations to the earlier Guess the Flag app. The tricky part was that all three flags are built in a ForEach, so animations applied to every button at once; the fix was storing each flag’s animation magnitude separately and animating unclicked flags by zero. I also cover re-animating the flags once the alert closes, along with my criticism of the tutorial’s alert UI...

Animation Feedback

A short comparison of two solutions to the Guess The Flags animation challenge: my approach of storing animation amounts in an Int array versus Paul’s more concise use of ternary operators in the modifiers. Both vary the effect depending on which flag was selected, but Paul’s version needs considerably less code...

Animations in Views

A short walkthrough of three ways to animate SwiftUI views, written as part of my progress through the 100 Days of SwiftUI series: implicit animation via the .animation() modifier, animation bound to controls like sliders, and explicit animation for coordinating simultaneous changes. Each approach is illustrated with example code and a demo video...

Gists for embedding code

I describe using GitHub Gists to embed code snippets in WordPress posts, a simpler alternative to the WordPress code blocks I complained about previously. Pasting a Gist URL into WordPress renders it as a formatted code block, which I demonstrate with a Swift example...

Don't Use Stupid Project Names

While working through Day 32 of 100 Days of SwiftUI — Project 6, a set of animation tutorials rather than a full app — I name a new Xcode project “Project 6 - Animation” and hit seven build errors caused by an unreplaced ___PACKAGENAME macro. Renaming the project without the dash fixes it, and since a web search turned up nothing, I include the exact error message for anyone else who names projects with dashes...

Recording the Simulator

A short note in which I replace QuickTime-based screen recordings with the iOS simulator’s built-in recording, which captures gestures and exports animated GIFs. The technique comes from a linked post by Sarun W...