blog.iankulin.com

100daysofswiftui

FriendFace 61 Feedback

I compare my attempt at a Core Data caching challenge—storing fetched user data so the app can still display it after network failures—against Paul’s model solution. Differences covered include adding a merge policy for handling constraint conflicts, keeping ids as UUIDs, and placing MainActor.run inside the network fetch rather than after it...

61 Done

I complete Day 61 of #100DaysOfSwiftUI, decoding JSON and backing it up into a Core Data graph for display. I get stuck on one:many relationships and an id type mismatch, plus some unexplained Core Data console warnings that linger despite the app working...

FriendFace Feedback

A comparison of my SwiftUI solution to the FriendFace challenge (downloading and displaying user JSON) against Paul Hudson’s version from Hacking with Swift. Differences I discuss include handling user IDs, structuring preview data, loading and error handling in fetchUsers(), and UI choices such as colored circles for user status and a grouped list style for the detail view...

FriendFace

A write-up of my Day 60 milestone challenge in the 100 Days of SwiftUI course: I build a small app that fetches a JSON file of users, decodes it into Codable structs (including ISO-8601 dates), and displays them in a list with a detail view. I share my fetch and view code, note some friction with nested do/catch error handling, and add profile pictures via AsyncImage, deciding against implementing image caching in order to keep the challenge simple...

Project 12 Feedback

I compare my solutions with Paul’s video for a SwiftUI challenge built around FilteredList, covering passing a predicate as a string, converting to enums, and adding sort descriptors. The enum task matched Paul’s exactly, while sort descriptors caused some struggle with NSSortDescriptors until I spotted the hint to use SortDescriptor instead...

Project 12 Challenges

My solutions to the three wrap-up challenges from Project 12 of the Hacking with Swift SwiftUI series, which involve a FilteredList subview whose @FetchRequest is built dynamically in its initializer. The tasks add a predicate format parameter, replace the hard-coded predicate string with an enum using raw values, and support an array of SortDescriptor objects...

You Can Take Big Steps When You Feel Safe

Day 58 of the 100 Days of SwiftUI series covers one-to-many Core Data relationships, using constraints and merge policies to handle conflicts, and underscore syntax for accessing wrapped properties in dynamic filtering. I reflect on Core Data’s pre-SwiftUI complexity, credit Paul Hudson’s teaching style with making the difficult material manageable, and consider how much harder the same functionality would be with raw SQLite...

Bookworm Feedback

I compare my SwiftUI solutions to a coding challenge series with Paul Hudson’s, finding the first two nearly identical and only minor differences on the third. I weigh hiding text with opacity to reserve space against using an if-let, and note that Hudson’s abbreviated date formatting handles locale differences my manual approach didn’t...

Bookworm Challenges

My solutions to the Project 11 challenges from the 100 Days of SwiftUI course, applied to Bookworm, a CoreData-based book tracking app. I add validation so books can’t be saved without a title or author, highlight one-star ratings in the book list, and add a date attribute to the Book entity that’s formatted in the detail view...

CoreData and the Preview

My CoreData project from Day 53 of the 100 Days of SwiftUI course ran fine in the simulator but crashed in Xcode’s SwiftUI preview, which lacked a managed object context. I describe a workaround I found on the Hacking with Swift forums for supplying a context to the preview...

Cupcake Corner Feedback

A comparison of my solutions to Paul Hudson’s for a SwiftUI challenge covering address validation, alerts for failed POST requests, and wrapping a struct in an observable class. I find Paul’s String extension approach to whitespace checking neater than my brute-force version, and I highlight Paul’s use of @dynamicMemberLookup with key paths to shorten chained property access like order.data.street down to order.street...

Cupcake Corner challenges

My solutions to the day 52 challenges for the Hacking with Swift Cupcake Corner app: trimming whitespace before validating the order address, showing an alert when the order submission to the API fails instead of just printing, and converting the Order class to a struct inside an ObservableObject wrapper to eliminate the manual Codable code. I present each change with Swift code snippets and links to the corresponding GitHub commits...

Top Four Reasons why @TwoStraws is a Good Teacher

I reflect on what makes the 100 Days of SwiftUI course effective as a teaching resource: its true/false comprehension questions, carefully pitched difficulty, hands-on learning in context, and the instructor’s knack for anticipating how beginners think. I also praise how reliably the course content stays up to date despite the rapid pace of change in Swift and SwiftUI...

Day 47 - Habits App

I wrap up my Habits app as an MVP, the first of my own apps I have actually installed on my phone, after 120 days on the 100 Days of SwiftUI course with only day 47 completed. Possible future features include setting habits due at a specific time, like 6pm, rather than a fixed interval after the last completion. A growing backlog, including a custom picker for a times table app, remains deferred...

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

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

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