This is for anyone experienced with #SwiftUI in #macOS development.
I used MenuBarExtra to make a small status bar utility app. I wanted to add an onboarding view, and I've tried everything.
I can use a WindowGroup to have a window and a MenuBarExtra, but that would display an empty window even if you hide the onboarding view after it's done.
Any thoughts? Ideas? or do I have to abandon SwiftUI 🫠
ScrollKit 0.5.1 for #SwiftUI is out! 🚀 This version adds support for strict concurrency and fixes some bugs for the sticky header scroll view. If you want to create solid SwiftUI designs with sticky & stretchy headers, ScrollKit has you covered. https://github.com/danielsaidi/ScrollKit
If you are looking for a weather app that is simple and does not track your location, try Ducky Weather! One thing I have found in our research group is that the most popular free weather applications send your location to trackers and I wanted to create an app that does not do that. Because it uses NWS data, it is only available in the US.
More features to come but suggestions are welcome!
This is the 5th video in a 7 Part series on building a full #SwiftUI weather app using #WeatherKit.
In this video we will be adding the final forecast type and that is a 10 day daily forecast.
If I want to use String(localized:) to localize a variable, is this the best way? I can’t put it in directly like I used to with NSLocalizedString. In this case, the variable comes from Core Data, otherwise I could probably declare it directly as LocalizedStringResource. #Swift#SwiftUI#UIKit#Localization
While implementing the package previews, I ran across one state that Cork didn't have covered yet: when an app is already installed outside of Homebrew, and you try to install the Homebrew version.
Instead of getting stuck, you now get this status.
I was struggling to figure out a way to have just one selectable item in a List. I thought up elaborate functions that would compare the sets holding the UUIDs of the selection, optimized to shit…
And then I realized I could just make the selection not a collection :nkoFacepalm2:
A BHAG that just popped into my head: get involved enough with #iOS#swiftui development that I am upset when I don’t get a #WWDC invitation (or elated when I do!)
Today, I merged the basic support for Shortcuts into mainline Cork. After that, I decided to take on another challenge
I thought it would be cool to be able to see detailed info about a package before you install it. This feature actually used to be in Cork back in 2022! But I had to remove it… until now!
@swiftui@swift Exciting News! 🎉 Just dropped Part 34 of my "Let's Build WhatsApp clone Using SwiftUI and “firebase” playlist! 📺🛠️ Dive deeper into Swift development as we take our app to the next level. 🚀 Check it out now and let's code together! 🔗 https://www.youtube.com/watch?v=BYV5ZMG-71M#SwiftUI#iOSDev
WWDC24 is right around the corner. Before the excitement and rush of what's to come, I want to share some navigation fun facts and tips. None of this is new, having been discussed previously in sessions, etc. From talking with developers, these are parts of the system that are often overlooked, or forgotten about #21DaysOfSwiftUINavigation#SwiftUI This is all running on macOS Sonoma 14.4, Xcode 15.3
Now that we know what view-destination links and value-destination links are, we can explore the data modeling behind NavigationStack. Today we look at another form of view-destination navigation: navigationDestination(item:destination:). It takes a bound item and presents a view when the item is non-nil. Despite taking a binding to an item, this is not a value-destination link. In today's code example, a few different types of links are composed together. #SwiftUI
8 cont) There are two important concepts this demo shows: 1️⃣ A NavigationStack's path is a run of 0 or more values, followed by a run of 0 or more views. The video calls out "You can not push more value-destinations." once the first view-destination view has been pushed. This is why it's helpful to know the difference between view- and value-destination links. It's fun (IMO) to reason out why this is: #SwiftUI
8 cont) Imagine a path that allowed pushing values after pushing views, so a path was [1, 2, 3] ViewA, ViewB, [4]. In NavigationStack's API, the path would be [1, 2, 3, 4] with two Views somewhere along the path. Given just that state, it's not possible to construct the state of the app. We can't know when the view-destination views were pushed, and which view should be on top of the stack. #SwiftUI
8 cont) It takes more than a few toots to fully explore this concept, but it is problematic if app state depends on how we got there + the state itself. 2️⃣ The second concept we see here is the first example of picking the right navigation tool for the job. navigationDestination(item:destination) is often overlooked in favor of the deprecated NavigationLink(isActive:destination:). A get/set binding is used for the isActive binding that maps an item to the Boolean value under the hood. #SwiftUI
8 cont) When possible, it is advisable to use the item-bound navigationDestination, rather than the deprecated API. When using NavigationLink(isActive:destination), especially in a List, that makes your app state a function of the path AND whether or not that link is in existence (e.g. scrolled on screen). The best way to model this instead, is whether or not the item binding is populated, which is the contract of the modifier.#SwiftUI
8 almost done) Another reason the NavigationLink(isActive:destination:) is deprecated is that it leads to mini update cycles when used in this way. the cycle looks like this: (a) user taps link (b) link view updates attempting to set it's isActive binding to true (c) the get/set binding kicks in its side effect of setting some item binding elsewhere (d) link view updates again because the isActive binding depends on the item binding. The loop terminates there and is sometimes harmless #SwiftUI
8 last one) These mini update cycles are sometimes harmless, but the more complex and app gets, the more work is being done, bindings updating, environment propagating, the higher the chance that the mini-update cycle causes some state change to not propagate correctly. SwiftUI is robust against this and will cut off cycles when it detects them. But it is best avoided, thus, pick the right tool for the job #SwiftUI
Today we look at navigationDestination(isActive:destination:), the boolean form of yesterday's modifier. The same guidelines apply, and here is one more: don't use them in lazy containers. Tying the existence of navigationDestination to whether or not contents of a List have been lazily loaded commits the error again (see Day8) of making navigation state a function of scroll state, AX/dynamic type size (larger type -> fewer rows scrolled on screen), size class, etc. #SwiftUI
9 cont) I've seen some code bases substantiate this construction with modularity. For example, the app's root view may be a List, each team that works on the app adds their feature like:
List {
Feature1()
Feature2()
}
And within those features exist .navigationDestination modifiers. Swift gives facilities for staying modular, and still moving those destinations outside the List. That's how to get robust deep linking, not subject to difficult to debug conditions like device size #SwiftUI
onAppear and onDisappear are not your friends when it comes to tracking navigation state — is it technically possible to track state like this? Yes, but brittle because you've made two sources of truth. If you've ever wondered why onDisappear isn't called when a view in a stack has one pushed atop it, imagine ViewA has @State or some timer that updates a dependency of ViewB. (ViewB is pushed on top of ViewA). ViewA can't be removed from the graph – it is still a dependency of ViewB #SwiftUI
10 cont) by the way, the system takes care to forward these dependencies efficiently. If ViewA has some observable property that updates over time, and ViewB captures that property in a navigationDestination, ViewB will update when the property of ViewA changes. Try putting an Observable at the root of a NavigationStack and updating the observable on a timer. Capture it in a NavigationDestination and watch the pushed view update too. #SwiftUI
We dive deeper into navigationDestination. We learned yesterday the closure passed to navigationDestination is reevaluated when its dependencies change. This keeps the destination presented by a navigationDestination up to date with the values captured by the closure. Be aware of how much you are capturing inside this navigationDestination closure! When you build up a stack of views with a NavigationStack, you might be building up a complex dependency graph — thus, cycles. #SwiftUI