blog.iankulin.com

Swift5-7

ChatGPT's code writing

I ask ChatGPT to write a SwiftUI todo app with items that reoccur after a set number of days, sharing the generated code and the fixes needed to make it run, such as replacing a non-existent date formatter and adding a NavigationView. Iterating toward a more complex app, including CoreData persistence, required progressively more manual correction from me. My brief closing thoughts cover what ChatGPT might mean for developers and internet content...

Sharing is caring

Continuing my SwiftUI demo project, I use ShareLink to let users share a view rendered as an image via the standard share sheet, with SharePreview supplying the thumbnail and title. I also cover adding the Photo Library Additions usage description so a Save Image option appears, along with the permission prompt users see on first use...

Clean code

After listening to a podcast episode about “humane” development, I describe my personal Swift coding style, which centers on being kind to whoever reads the code next. The principles I cover include following community conventions, writing code that reads like natural language, keeping functions small and single-purpose, avoiding hidden dependencies like globals, and using comments as temporary scaffolding that usually gets deleted once the code is written...

ImageRenderer()

A short SwiftUI example showing how ImageRenderer converts a view into a UIImage or CGImage. I build a simple behaviour ticket view, use a Save button to render it to an image, and display the saved result behind a toggle...

Regex to split a string with two different characters

A walkthrough of using Swift 5.7’s regex support as the separator argument to String.split(), in order to parse a string like “Some behaviour (expectation)” into its two parts. I build the expression up step by step, covering escaping of brackets and spaces and the use of the pipe for OR, and note that the Playgrounds app doesn’t yet support Swift 5.7...

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

Core Data basics – Part Three

In part three of my Core Data basics series, I show how to add a one-to-many relationship so each Garden can have multiple Plants. I cover converting the generated NSSet of related plants into a sorted array via a computed property, displaying the plants in a list in the garden detail view, and linking plant instances to a garden when creating sample data...

Core Data basics - Part Two

Part two of my series on Core Data basics, in which I convert a SwiftUI master/detail garden-list app from structs to Core Data. I walk through defining entities in the Xcode data model, generating editable NSManagedObject subclasses, setting up a DataController with NSPersistentContainer, and fetching and saving data with @FetchRequest. I defer one-to-many relationships to the next part, and I draw much of the code from Paul Hudson’s 100 Days of SwiftUI...

Core Data basics - Part One

In the first part of my series on learning Core Data basics, I build a simple SwiftUI master/detail app that lists gardens and their plants using structs and arrays, as a starting point before converting it to Core Data in later parts. My code draws heavily on Paul Hudson’s 100 Days of SwiftUI course, with a GitHub link to the source...

Something weird 'append

A debugging story about a SwiftUI master/detail list where every row displays the first record’s data. While preparing to replicate my app in Core Data, I work through Swift’s value-type semantics, a Playground experiment, and print debugging before finding the real cause: mutating and reusing a single struct created duplicate UUIDs that broke ForEach, despite a console warning early on...

Console spam - No wall clock alignment

A debugging session traces a recurring console message in my SwiftUI app, “No wall clock alignment provided,” to the .date style when formatting dates in a Text view. I reproduce the issue with a minimal code snippet, find little documentation online beyond an old Reddit thread, and file my first Radar bug report with Apple...

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

Profile Photo Rabbit Hole

My #100DaysOfSwiftUI challenge post is about adding profile pictures to a Friendface app. Swift’s hashValue turns out to be non-deterministic between runs, so I write a simple string hash by hand to pick stable photo numbers. After Unsplash proves unreliable, I settle on RandomUser.me portraits and consider using the genderize.io API to match gender from names...

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

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

@Binding - data between views

I explain SwiftUI’s @Binding property wrapper, framed by an analogy to passing pointers in C. A short code example demonstrates a parent view passing an @State variable to a subview with the $ prefix, letting the subview read and mutate the value...

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