blog.iankulin.com

Code

You need to enjoy puzzles

After converting a SwiftUI subview from a function to a struct, list items in my habit list app stopped updating correctly. Suspecting a value versus reference type issue, I distilled the problem into a minimal ObservableObject example, only to find that both the example and the original app now worked. The post walks through the code and the debugging process but ends without an explanation of what caused or fixed the bug...

Drawing Feedback

I compare my solutions to the Project 9 drawing challenges from Paul Hudson’s 100 Days of SwiftUI course, covering an Arrow shape, making its shaft width animatable using AnimatableData, and a ColorCyclingRectangle with a controllable gradient. My closing aside considers whether to use US or UK spellings like “color” in Swift code...

Project 9 - Drawing

This is my #100DaysOfSwiftUI journal entry covering days on custom drawing: paths, shapes, transforms, ImagePaint, drawingGroup with Metal, blurs, blend modes, and animatableData. I walk through the challenge solutions, building an Arrow shape with animatable line thickness and a ColorCyclingRectangle whose gradient endpoint is controlled by sliders, and I note the lesson I learned from not using git for scratch code...

Moonshot Feedback

A comparison of my SwiftUI solution to the Hacking With Swift Moonshot challenge against Paul Hudson’s, covering choices like whether to extract sub-views into separate files and using a List versus a ScrollView with HStacks. The key difference I discuss is a toolbar toggle built with a Button instead of an Image with a tap gesture, since using standard controls as intended gives screen readers the information they need for accessibility...

Moonshot Challenges

My solutions to the three wrap-up challenges for the Moonshot app from the 100 Days of SwiftUI course, an information app about the Apollo missions. My work covers displaying formatted launch dates, extracting the crew view and a custom divider into separate structs, and adding a toolbar toggle between grid and list mission layouts, with some notes on the tradeoffs of splitting views out...

Using Swift's map

While working through Day 39 of the Hacking with Swift 100 Days of SwiftUI course, I explain Swift’s map method, which applies a closure to each element of a collection and returns a transformed array. Simple Playground examples demonstrate mapping integers to strings, with equivalent forEach and for loop versions included for comparison...

iExpense Feedback

I compare my iExpense SwiftUI challenge solutions against Paul Hudson’s, covering preferred-currency formatting, styling expense amounts by value, and splitting the list into personal and business sections. After investigating why my ForEach-based split deletes the correct item despite warnings about offset mismatches, I find that SwiftUI’s onDelete already passes correct array indexes and conclude that my approach beats Paul’s filtered-array solution...

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...

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...

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...

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...

Project 5 - Word Scramble

I built a Scrabble-like word game as a 100 Days of SwiftUI project. I cover bundling a large text file and loading it into an array at view launch, plus a brief detour into UIKit to use UITextChecker. My source code is on GitHub...

Word Scramble Feedback

After finishing the Word Scramble challenges in Hacking with Swift’s 100 Days of SwiftUI, I review Paul Hudson’s subscriber-only solution and pick up two improvements. The first is a clearer way of resetting the used-words array; the second replaces my bottom-toolbar score display with a safeAreaInset that initially seemed overcomplicated but looked better in practice...

Project 4 Challenges

I complete the Project 4 challenges of the 100 Days of SwiftUI course and compare my solutions to Paul Hudson’s video solutions. Differences covered include Section header syntax, a picker implementation containing a careless bug, and moving a bedtime calculation into a computed property. Finding the comparison useful, I plan to check the video solutions going forward...

Rock, Paper, Scissors (1)

A working SwiftUI version of the Hacking with SwiftUI Day 25 project, a Rock, Paper, Scissors game where the player must randomly try to win or lose each round. I share the full source code and list aspects of the implementation I’m unhappy with, such as the array-and-int game state, duplicated win-checking functions, and a hidden-view layout workaround, and note the scoring deviates from the project brief...

.self in ForEach

While working through Hacking With SwiftUI, I run into two points of confusion around ForEach: what the id: .self key path actually does when looping over an array of strings, and a compiler warning about non-constant ranges such as 0..<agents.count. Attempts to use key paths directly don’t compile, and a forum explanation of the warning — guarding against the array changing size during the loop — leaves me unconvinced...

Project 3

My solutions to three small SwiftUI challenges: using a ternary with semantic colors to turn the total red at a 0% tip in WeSplit, wrapping the flag Image in a reusable FlagView for GuessTheFlag, and building a custom ViewModifier with a View extension that applies a large blue title style. Each solution includes a short code snippet and a link to my change on GitHub...

Day 23 - Views and Modifiers - Part 4

A SwiftUI tip on decomposing views by extracting them into custom View structs that accept values at initialization, illustrated with a reusable padded green text component. I favor this approach because such building blocks are portable and can be used in other views...

Day 23 - Views and Modifiers - Part 3

A look at how I decompose SwiftUI views into smaller pieces: storing view fragments as properties, why properties can’t reference each other, and why a computed property can’t return multiple views without a single container. I cover fixes including wrapping views in a VStack or Group or applying the @ViewBuilder attribute, and I note a quirk where omitting a VStack unexpectedly produced two preview instances...