Show Full thread

Today [2/2]:
- Added URLEncodedForm dependency for creating models github.com/interactord/URLEnco
- Now that creating a model works I need to update the app after you get a result back. Lots to do in this regard starting with networking, data, relationships, and navigation.
- Need to overhaul networking and probably rip out Combine
- Need to fix navigation bugs
- Need to write documentation and do clean-up
- Lots to do after a busy Monday/Tuesday

Today:
- started to rewrite networking out of Combine (dataTaskPublisher) into an actor.
- aiming for groups of generic endpoints mapped to models

Today:
- continuing actor based networking
- mostly defining generic endpoints

Today:
- git push origin -u main
- 🫣 still more to clean and rearrange

Well! Thanksgiving threw off my development streak. Got to get back into it.

Today 1/2
- Continuing API work. Moving to Result and using Result.catching which is very nice.
- thx Andres! See iosdev.space/@andresraigoza/11
- Switched UIKit ASWebAuthentication to Environment(\.webAuthenticationSession)
- thx Andy! See iosdev.space/@andy/11147423796
- Wading back into the project to get building again.

Today 2/2
- Fighting SwiftData lifecycles from: A) fetching and parsing JSON, B) writing to disk, C) with relationships. My key problem is that I'm expecting to "upsert" models when a new instance has the same value for an @Attribute(.unique) field, but that's not happening. The tell is that a relationship’s persistentModelID.storeIdentifier is nil after the parent's init(decoder:).
- Gotta revisit the videos and examples around SwiftData to see how this should be done.

Today 1/2:
- Was hitting fatal SwiftData errors on ~4 of 5 builds.
- Background: server returns nested models in the first endpoint I need to request. Have to solve up that front.
- Synthesizing the resources below I think I switched over to a working approach…
• Started adding the modelContext into JSONDecoder.userInfo and inserting child/related models as decoding progresses
• Changed child/related models to optional vars or provided default values for empty arrays

Ahhhh still figuring this out 🥴

Okay performing the “upsert” manually for the 1:1 relationship is the right path to work toward and not yet complete. This scenario is all about inserting multiple models at once. I'm thinking the easiest way will be to delete any stale primary data, use a cascade to change the relationships' data (or do the manual inserts), and then save everything.

- experimenting and trying to figure out this decoding in unit tests. Inching forward.
- Found the ‘-com.apple.CoreData.SQLDebug 3‘ launch argument to help
- I think I’m going to separate the data models from the decoding and that way I can figure out autosave and inserts on an appropriate timeline

I think to get started with SwiftData you need to first understand CoreData. The sample code is cute but any slightly advanced scenario is obtuse.

Alright I know I’ve said this a lot but back to making progress:
- Split my Decodables and PersistentModels so that the networking code can perform decoding and later on I can safely transform a Decodable into a PersistentModel, establish relationships, save it, and use it.
- stopped accessing ModelContext on different threads!
- found a working relationship set up (cascade on the parent, inverse on the child), can’t explain it, gonna try adding more

Today I did some clean up, deleted comments and unused code, and feel pretty good about this little home grown networking layer.

Today: 🆕 switching over to pushing changes to the public repo. I might've left more things broken but now I'm content with the path forward.

Today: brought all those networking updates into the registration view and [redacted] data model, fixing some errors with POST behavior, correcting some enums to match the API.

Finally getting back to the point with UI changes on the registration view… 🥁 … adding an alert after the POST succeeds or fails. Next I think I’ll get back to displaying the user’s list of [redacted] data models.

Today: fix missing serial number scenario, replace frameColors array with three fields (one required, two optional) because the array manipulation doesn't matter, bump deployment target iOS 17.2 / Xcode 15.1 because I can, add long-press to reach the same Add Bike view with more fields for stolen bikes, begin adding fields for stolen bikes to populate phone, address info.

Yesterday/today: conflicted on how to effectively use NavigationSplitView and NavigationStack. After I got everything working well on iPad I noticed that the approach is incompatible with iPhone.
(That approach was changing the NavigationSplitView detail: { } contents based on a switch-enum in order to fill the detail view as the root view).
To get the UI that I want I think I need to just switch to modals/sheets and explore that paradigm.

This project seems like a better starting point if I go back to NavigationSplitView for this project github.com/gahntpo/DoubleColum

No wait I don't want any of that lol. I think settling on NavigationStack containing a root of a grid of buttons with NavigationPath to control the stack is what I want. That ought to navigate well on iPhone + iPad, still let me display a decent grid across both, look good, and be nice to use for editing.
A task for tomorrow.

Today: yeah I flattened this hierarchy into a ContentView containing NavigationStack containing the root level of buttons and menu options that link to .navigationDestination.
Next I need to revisit that test data and add your own bikes to the ContentView’s root level.

Turns out the way to get a custom navbar background is with

.toolbarColorScheme(.dark, for: .navigationBar)
.toolbarBackground(.blue, for: .navigationBar)
.toolbarBackground(.visible, for: .navigationBar)

Today: fixed up a usage of the old networking pattern, cleaned up the WelcomeView and assets, figured out how to add that navigation bar I wanted.

Today: fixed up the BetterSafariView navigation

hmmm that BetterSafariView integration is gonna need work later, on just because of the nature of SFSafariViewController…

Today: added Acknowledgement section for open source packages, moved Debug menu into nested hierarchy, and most-importantly started on fetching your registered bikes now that the network API is set up how I want for fetching and writing to SwiftData! 🎉

Installed the app to my phone for the first time too 🥲

Today: working on the bike app for so long that my token expired and I haven't built any automatic refresh behavior yet trololol

Today: Add basic bike list and detail view, fixup the title, parse thumbnail and hero image, switch missing serial number to “unknown”, add option for bikes in model year 2025, begin adding other modes to RegisterBikeView, add a FAQ link, lots of clean-up and fixups.
Feels like we're getting close to an MVP!

omg forgot to mention, switched from BetterSafariView to WebViewKit (hi Daniel 🍕) to access shared session state across all webviews. ASWebAuthenticationSession and SFSafariViewController are nice but I didn't have A) any way to ensure the user is logged in to present pages for advanced editing and B) no way to actually clear session state and log out!

(I might've just needed a network request to /logout but the active session in ASWebAuthenticationSession was too aggressively cached IMHO).

This new approach with WebViewKit might run into trouble with app review or macOS potentially but that's a problem for another day

Today 1/2: phew! Lots of busy-work.
- Fixed log-out for “real final final copy_(2)” with a network request to /logout, and keeping a global WKWebViewConfiguration to burn the auth cookie.
- Added scheme validation for auth callbacks
- Added inspectability to web view
- Added javascript+css injection to style the page and remove the main nav header
- Added @Observable NavigableWebView wrapping WebView with a Navigator WKNavigationDelegate…

Today 2/?:
- I want a lil responder-chain of WKNavigationDelegate objects so that I can have a general one useful for back/forward navigation and then a specialized one that does authentication. (This would've been easier if they didn't all conform to WKNavigationDelegate). Made a NavigatorChild that implements _all_ WKNavDel and has a property child: NavigatorChild. Then those specialized uses (back/forward, authentication) are separate subclasses.

Today: still setting up the dev account, still on my mind

Today: shared first TestFlight internal beta, hoping for a long list of strong-opinion/loosely-held priorities, finally settled on a Pride 🏳️‍🌈 icon.
I gotta get back to figuring out everything that was broken and in-progress 😅 I think the first was session renewal so I'm gonna have to start adding tests and making a to-do list for tomorrow.

Today: separated main module sources from tests, fixed grid sizing, fixed app icon display, updated

DEBUG exclusions for production. In-progress: session renewal, starting with local unit tests.

Today: Added a "Scan Text" button for serial numbers. I just wish it had flashlight control for low-light conditions. Maybe that's not necessary.
developer.apple.com/videos/pla

This weekend:
- Fixed session refresh when the session has expired (do not need to tap "Sign in" — refreshed automatically)
- Fixed keyboard when searching/entering a Manufacturer name
- Fixed electric motor toggle behavior for "Has throttle" and "Has pedal"
- Fixed layout for Serial Number "Scan Text" button

This weekend in

:
- minor project configuration clean up
- swing and miss at integrating Fastlane Snapshot, not essential so deferring
- trying out swift 6 concurrency

Tomorrow: app launch??

I’m proud to introduce you to Bike Index: an open-source iOS app for the world’s leading bike registration and recovery service of the same name! Bikes mean everything to their riders: freedom of movement, ability to transport cargo, exercise and empowerment, connecting with nature and the great outdoors. Bike Index helps you recover your bike if it’s ever lost or stolen. Built with

and

Direct link here apps.apple.com/us/app/bike-ind

jack

@j4ck@iosdev.space

Pro-tip: remember the “Authorize this OAuth application" step for your UITests 🧠💡

December 9, 2024 at 1:39:49 AM

Good changes:
1. Refactored navigation.
a. OLD: MainPage > NavigationStack > Settings > NavigationLink > Web Views
b. NEW: MainView > NavigationStack(path: $path) > Settings > Buttons that append to $path > Web Views
2. Settings is faster because it doesn't need to pre-load the web views!

Agh!!!!
Turmoil to get there:
3. This broke the debug-only modal AuthPage > NavigationStack > Settings > Buttons append to $path
a. Settings { @.Environment(\.openURL) var openURL } was causing continuous changes to the view itself and blocking the whole UI 🥴
b. Solved by replacing OpenURL with Link(destination:label:).

I definitely should’ve been using a Link before but this seems like a


4. Now I need to get those disclosure indicators back in a nice way.

Alright NavigationStack + Button + navigationDestination wasn't necessary. Revisited developer.apple.com/documentat and realized that the problem was NavigationLink(destination: () -> View, label:) and the fix is simply NavigationLink(value: Hashable?, label:) + navigationDestination. Glad I didn't spend too much time on it. Still got those speed improvements, more to test too.

> There are several benefits to using folders instead of groups when organizing your Xcode project files. Folders have a much smaller representation in the project file, which can result in fewer merge conflicts because when you add or remove files to the project you don’t modify the project file. Additionally, your Xcode project file automatically updates as you make changes to the file system.
developer.apple.com/documentat

Elk Logo

Welcome to Elk!

Elk is a nimble Mastodon web client. You can login to your Mastodon account and use it to interact with the fediverse.

Expect some bugs and missing features here and there. Elk is Open Source and we're actively improving it as a community project. Join us and let's build it together!

If you'd like to report a bug, help us testing, give feedback, or contribute, reach out to us on GitHub and get involved.

To boost development, you can sponsor the Team through GitHub Sponsors. We hope you enjoy Elk!

Anthony FuPatakTAKAHASHI ShuujiDaniel Roe三咲智子 Kevin DengJoaquín Sánchez

The Elk Team