Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.

All subtopics
Posts under UI Frameworks topic

Post

Replies

Boosts

Views

Created

Slider .rotationEffect broken in MacOS 14.5
In a SwiftUI app for MacOS, vertical sliders that I'd created using a rotationEffect of 90° disappeared when I upgraded to Sonoma 14.5 (23F79). With rotations less than 90°, the slider is still visible, but its button is enlarged, growing in size as the rotation angle approaches 90°. Note that the sliders still work, even when rotated by 90° and invisible! The screenshot and code below demonstrates the problem, which did not exist in MacOS 14.2.1 struct ContentView: View { @State var speed = CGFloat(1) var body: some View { HStack { let angle: [Double] = [0, 45, 80, 85, 90] ZStack { ForEach(0...4, id: \.self) { i in ZStack () { Rectangle() Slider(value: $speed, in: 0...10 ) } .frame(width: 100, height: 10) .rotationEffect(.degrees(angle[i])) .offset(x: CGFloat(i * 100) - 180) } } } .padding() .frame(width: 600, height: 200) } } #Preview { ContentView() }
Topic: UI Frameworks SubTopic: SwiftUI
6
1
825
Jun ’24
Live Activity compact timers
The Human Interface Guidelines for Live Activities provide several examples of compact presentations that have a timer counting down formatted like "3min" or "3m", similar to the timers in the Clock app. Such examples can be found in this Stack Overflow question: https://stackoverflow.com/questions/77551496/is-it-possible-to-make-an-only-minutes-1m-countdown-in-a-live-activity A Timer initialized with init(timerInterval:pauseTime:countsDown:showsHours:) has provided a live countdown timer in widgets and live activities, but the formatting is limited. And since live activities come with limitations that prevent us from using Timers, there's no real way to implement this kind of thing ourselves. What is Apple's official guidance for implementing this kind of timer for the compact presentation?
5
2
2.6k
Jun ’24
SwiftUI Previews broken on local Swift Package with dependencies
I have a project with two local packages One client package with an interface and some models with dynamic type in the Package.Swift One feature package with the UI and a dependency to the client package When I try to preview a view that is not using any models or code from the client package, it loads just fine e.g. a view that is just a container to display things like a card But when I tried to preview any other view that actually uses models from the client package, it just fails the first few lines of the preview error display LinkDylibError: Failed to build <filename>.swift Linking failed: linker command failed with exit code 1 (use -v to see invocation) ld: warning: search path '/Applications/Xcode-15.4.0.app/Contents/SharedFrameworks-iphonesimulator' not found Undefined symbols for architecture arm64: Also, I'm using Xcode 15.4 and iOS 17 as the min version
6
1
1.9k
Jun ’24
Combining Matched Geometry with New Zoom Navigation Transitions in iOS 18
With the introduction of the new matchedTransitionSource from iOS 18, we can apply a zoom transition in the navigation view using .navigationTransition(.zoom) This works well for zoom animations. However, when I try to apply a matched geometry effect to views that are similar in the source and destination views, the zoom transition works, but those views don't transition seamlessly as they do with a matched geometry effect. Is it possible to still use matched geometry for subviews of the source and destination views along with the new navigationTransition? Here’s a little demo that reproduces this behaviour: struct ContentView: View { let colors: [[Color]] = [ [.red, .blue, .green], [.yellow, .purple, .brown], [.cyan, .gray] ] @Namespace() var namespace var body: some View { NavigationStack { Grid(horizontalSpacing: 50, verticalSpacing: 50) { ForEach(colors, id: \.hashValue) { rowColors in GridRow { ForEach(rowColors, id: \.self) { color in NavigationLink { DetailView(color: color, namespace: namespace) .navigationTransition( .zoom( sourceID: color, in: namespace ) ) .edgesIgnoringSafeArea(.all) } label: { ZStack { RoundedRectangle(cornerRadius: 5) .foregroundStyle(color) .frame(width: 48, height: 48) Image(systemName: "star.fill") .foregroundStyle(Material.bar) .matchedGeometryEffect(id: color, in: namespace, properties: .frame, isSource: false) } } .matchedTransitionSource(id: color, in: namespace) } } } } } } } struct DetailView: View { var color: Color let namespace: Namespace.ID var body: some View { ZStack { color Image(systemName: "star.fill") .resizable() .foregroundStyle(Material.bar) .matchedGeometryEffect(id: color, in: namespace, properties: .frame, isSource: false) .frame(width: 100, height: 100) } .navigationBarHidden(false) } } #Preview { ContentView() }
1
4
1.1k
Jun ’24
Title Bar Height Impact on Window Size in SwiftUI on macOS
In a SwiftUI macOS application, when removing the title bar by setting window.titleVisibility to .hidden and window.titlebarAppearsTransparent to true, the title bar space is still accounted for in the window height. This results in a delta (red area) in the height of the window that cannot be ignored by usual SwiftUI view modifiers like .edgesIgnoringSafeArea(.top). My actual view is the blue area. I want to have the view starting in the top safeArea and the window to be the exact size of my view. I am struggling to achieve this. I have also tried with window.styleMask.insert(.fullSizeContentView) to no effect. Can I get some help? 🙂 Here is my source code to reproduce this behavior: windowApp.swift @main struct windowApp: App { @NSApplicationDelegateAdaptor private var appDelegate: AppDelegate var body: some Scene { WindowGroup { ContentView() .edgesIgnoringSafeArea(.top) .background(.red) .border(.red) } } } class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { if let window = NSApplication.shared.windows.first { window.titleVisibility = .hidden window.titlebarAppearsTransparent = true window.styleMask.insert(.fullSizeContentView) } } } ContentView.swift import SwiftUI struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .frame(minWidth: 400, minHeight: 200) .background(.blue) } }
Topic: UI Frameworks SubTopic: SwiftUI
1
1
948
Jun ’24
Location Permission Popup Not Appearing in SwiftUI App
Hello everyone, I'm working on a SwiftUI app that requires location services, and I've implemented a LocationManager class to handle location updates and permissions. However, I'm facing an issue where the location permission popup does not appear when the app is launched. Here is my current implementation: LocationManager.swift: import CoreLocation import SwiftUI class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { private let locationManager = CLLocationManager() @Published var userLocation: CLLocation? @Published var isAuthorized = false @Published var authorizationStatus: CLAuthorizationStatus = .notDetermined override init() { super.init() locationManager.delegate = self checkAuthorizationStatus() } func startLocationUpdates() { locationManager.startUpdatingLocation() } func stopLocationUpdates() { locationManager.stopUpdatingLocation() } func requestLocationAuthorization() { print("Requesting location authorization") DispatchQueue.main.async { self.locationManager.requestWhenInUseAuthorization() } } private func checkAuthorizationStatus() { print("Checking authorization status") authorizationStatus = locationManager.authorizationStatus print("Initial authorization status: \(authorizationStatus.rawValue)") handleAuthorizationStatus(authorizationStatus) } func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) { print("Authorization status changed") authorizationStatus = manager.authorizationStatus print("New authorization status: \(authorizationStatus.rawValue)") handleAuthorizationStatus(authorizationStatus) } private func handleAuthorizationStatus(_ status: CLAuthorizationStatus) { switch status { case .authorizedAlways, .authorizedWhenInUse: DispatchQueue.main.async { self.isAuthorized = true self.startLocationUpdates() } case .notDetermined: requestLocationAuthorization() case .denied, .restricted: DispatchQueue.main.async { self.isAuthorized = false self.stopLocationUpdates() print("Location access denied or restricted") } @unknown default: DispatchQueue.main.async { self.isAuthorized = false self.stopLocationUpdates() } } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { DispatchQueue.main.async { self.userLocation = locations.last } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print("Location manager error: \(error.localizedDescription)") } } MapzinApp.swift: @main struct MapzinApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate @StateObject private var locationManager = LocationManager() var body: some Scene { WindowGroup { Group { if locationManager.authorizationStatus == .notDetermined { Text("Determining location authorization status...") } else if locationManager.isAuthorized { CoordinatorView() .environmentObject(locationManager) } else { Text("Location access is required to use this app. Please enable it in Settings.") } } } } } Log input: Checking authorization status Initial authorization status: 0 Requesting location authorization Authorization status changed New authorization status: 0 Requesting location authorization Despite calling requestWhenInUseAuthorization() when the authorization status is .notDetermined, the permission popup never appears. Here are the specific steps I have taken: Checked the Info.plist to ensure the necessary keys for location usage are present: NSLocationWhenInUseUsageDescription NSLocationAlwaysUsageDescription NSLocationAlwaysAndWhenInUseUsageDescription Verified that the app's target settings include location services capabilities. Tested on a real device to ensure it's not a simulator issue. I'm not sure what I might be missing. Any advice or suggestions to resolve this issue would be greatly appreciated. Thank you!
2
0
2.2k
Jun ’24
Crash After Presenting SwiftUI Alert
I’m seeing a crash in production for a small percentage of users, and have narrowed it down based on logging to happening as or very shortly after an alert is presented using SwiftUI. This seems to be isolated to iOS 17.5.1, but since it’s a low-volume crash I can’t be sure there aren’t other affected versions. What can I understand from the crash report? Here’s a simplified version of the code which presents the alert, which seems so simple I can’t understand why it would crash. And following that is the crash trace. // View (simplified) @MainActor public struct MyView: View { @ObservedObject var model: MyViewModel public init(model: MyViewModel) { self.model = model } public var body: some View { myViewContent .overlay(clearAlert) } var clearAlert: some View { EmptyView().alert( "Are You Sure?", isPresented: $model.isClearAlertVisible, actions: { Button("Keep", role: .cancel) { model.clearAlertKeepButtonWasPressed() } Button("Delete", role: .destructive) { model.clearAlertDeleteButtonWasPressed() } }, message: { Text("This cannot be undone.") } ) } } // Model (simplified) @MainActor public final class MyViewModel: ObservableObject { @Published var isClearAlertVisible = false func clearButtonWasPressed() { isClearAlertVisible = true } func clearAlertKeepButtonWasPressed() { // No-op. } func clearAlertDeleteButtonWasPressed() { // Calls other code. } } Incident Identifier: 36D05FF3-C64E-4327-8589-D8951C8BAFC4 Distributor ID: com.apple.AppStore Hardware Model: iPhone13,2 Process: My App [379] Path: /private/var/containers/Bundle/Application/B589E780-96B2-4A5F-8FCD-8B34F2024595/My App.app/My App Identifier: com.me.MyApp Version: 1.0 (1) AppStoreTools: 15F31e AppVariant: 1:iPhone13,2:15 Code Type: ARM-64 (Native) Role: Foreground Parent Process: launchd [1] Coalition: com.me.MyApp [583] Date/Time: 2024-06-21 20:09:20.9767 -0500 Launch Time: 2024-06-20 18:41:01.7542 -0500 OS Version: iPhone OS 17.5.1 (21F90) Release Type: User Baseband Version: 4.50.06 Report Version: 104 Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x00000001a69998c0 Termination Reason: SIGNAL 5 Trace/BPT trap: 5 Terminating Process: exc handler [379] Triggered by Thread: 0 Kernel Triage: VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter VM - (arg = 0x3) mach_vm_allocate_kernel failed within call to vm_map_enter Thread 0 name: Thread 0 Crashed: 0 libswiftCore.dylib 0x00000001a69998c0 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144) 1 AttributeGraph 0x00000001d0cd61a4 Attribute.init<A>(body:value:flags:update:) + 352 (Attribute.swift:473) 2 SwiftUI 0x00000001ac034054 closure #1 in Attribute.init<A>(_:) + 128 (<compiler-generated>:0) 3 SwiftUI 0x00000001ac033cac partial apply for closure #1 in Attribute.init<A>(_:) + 32 (<compiler-generated>:0) 4 libswiftCore.dylib 0x00000001a6ad0450 withUnsafePointer<A, B>(to:_:) + 28 (LifetimeManager.swift:128) 5 SwiftUI 0x00000001ad624d14 closure #2 in UIKitDialogBridge.startTrackingUpdates(actions:) + 268 (UIKitDialogBridge.swift:370) 6 SwiftUI 0x00000001ad624ae0 UIKitDialogBridge.startTrackingUpdates(actions:) + 248 (UIKitDialogBridge.swift:369) 7 SwiftUI 0x00000001ad6250cc closure #4 in UIKitDialogBridge.showNewAlert(_:id:) + 72 (UIKitDialogBridge.swift:471) 8 SwiftUI 0x00000001abfdd050 thunk for @escaping @callee_guaranteed () -> () + 36 (:-1) 9 UIKitCore 0x00000001aa5722e4 -[UIPresentationController transitionDidFinish:] + 1096 (UIPresentationController.m:651) 10 UIKitCore 0x00000001aa571d88 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.114 + 320 (UIPresentationController.m:1390) 11 UIKitCore 0x00000001aa5cb9ac -[_UIViewControllerTransitionContext completeTransition:] + 116 (UIViewControllerTransitioning.m:304) 12 UIKitCore 0x00000001aa34a91c __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__ + 36 (UIView.m:16396) 13 UIKitCore 0x00000001aa34a800 -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 624 (UIView.m:16429) 14 UIKitCore 0x00000001aa349518 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 436 (UIView.m:0) 15 UIKitCore 0x00000001aa356b14 -[UIViewAnimationState animationDidStop:finished:] + 192 (UIView.m:2400) 16 UIKitCore 0x00000001aa356b84 -[UIViewAnimationState animationDidStop:finished:] + 304 (UIView.m:2422) 17 QuartzCore 0x00000001a96f8c50 run_animation_callbacks(void*) + 132 (CALayer.mm:7714) 18 libdispatch.dylib 0x00000001aff61dd4 _dispatch_client_callout + 20 (object.m:576) 19 libdispatch.dylib 0x00000001aff705a4 _dispatch_main_queue_drain + 988 (queue.c:7898) 20 libdispatch.dylib 0x00000001aff701b8 _dispatch_main_queue_callback_4CF + 44 (queue.c:8058) 21 CoreFoundation 0x00000001a808f710 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16 (CFRunLoop.c:1780) 22 CoreFoundation 0x00000001a808c914 __CFRunLoopRun + 1996 (CFRunLoop.c:3149) 23 CoreFoundation 0x00000001a808bcd8 CFRunLoopRunSpecific + 608 (CFRunLoop.c:3420) 24 GraphicsServices 0x00000001ecf3c1a8 GSEventRunModal + 164 (GSEvent.c:2196) 25 UIKitCore 0x00000001aa6c490c -[UIApplication _run] + 888 (UIApplication.m:3713) 26 UIKitCore 0x00000001aa7789d0 UIApplicationMain + 340 (UIApplication.m:5303) 27 SwiftUI 0x00000001ac27c148 closure #1 in KitRendererCommon(_:) + 168 (UIKitApp.swift:51) 28 SwiftUI 0x00000001ac228714 runApp<A>(_:) + 152 (UIKitApp.swift:14) 29 SwiftUI 0x00000001ac2344d0 static App.main() + 132 (App.swift:114) 30 My App 0x00000001001e7bfc static MyApp.$main() + 52 (MyApp.swift:0) 31 My App 0x00000001001e7bfc main + 64 32 dyld 0x00000001cb73de4c start + 2240 (dyldMain.cpp:1298)
3
0
948
Jun ’24
SwiftUI: listSectionSeparator not working on macOS
Hi, When I use 'listSectionSeparator' on hide the section separator on a List 'section', it works as expected on iOS, but doesn't have any effect on macOS. Is that a known issue? Are there any workarounds for this? Here's a basic reproducible example: import SwiftUI struct TestItem: Identifiable, Hashable { let id = UUID() let itemValue: Int var itemString: String { get { return "test \(itemValue)" } } } struct TestListSelection: View { let testArray = [TestItem(itemValue: 1), TestItem(itemValue: 2), TestItem(itemValue: 3), TestItem(itemValue: 4)] @State private var selectedItem: TestItem? = nil var body: some View { List (selection: $selectedItem) { Section("Header") { ForEach (testArray, id: \.self) { item in Button { print("main row tapped for \(item.itemValue)") } label: { HStack { Text(item.itemString) Spacer() Button("Tap me") { print("button tapped") } .buttonStyle(.borderless) } } .buttonStyle(.plain) } } .listSectionSeparator(.hidden) // has no effect on macOS Section("2nd Header") { ForEach (testArray, id: \.self) { item in Text(item.itemString) } } .listSectionSeparator(.hidden) // has no effect on macOS } .listStyle(.plain) } } #Preview { TestListSelection() }
1
1
532
Jun ’24
Cordova based app not working after updating iOS to 17.5.1
After updating iOS, my Cordova app behaves incorrectly after receiving a voip push. When a push notification is received, my application launches CallKit, displays the Native Dialer screen and starts other necessary services. Until 17.5.1 (possibly 17.5) everything worked correctly. All services and sockets were established/ connected and working. After updating iOS to 17.5, the application crashes, and while voice connection is established the app is no longer active. Xcode logs have these error messages: Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.719601+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.732219+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 Invalidating grant <invalid NS/CF object> failed Type: Error | Timestamp: 2024-06-20 13:27:44.733996+02:00 | Process: MyApp | Library: WebKit | Subsystem: com.apple.WebKit | Category: ProcessCapabilities | TID: 0x3a4929 I am using: Cordova iOS: 6.2 iOS 17.5.1 Can anyone please help?
8
1
5.7k
Jun ’24
macOS SwiftUI Sheets are no longer resizable (Xcode 16 beta2)
For whatever reason SwiftUI sheets don't seem to be resizable anymore. The exact same code/project produces resizable Sheets in XCode 15.4 but unresizable ones with Swift included in Xcode 16 beta 2. Tried explicitly providing .fixedSize(horizontal false, vertical: false) everywhere humanly possible hoping for a fix but sheets are still stuck at an awkward size (turns out be the minWidth/minHeight if I provide in .frame).
6
1
2.5k
Jun ’24
Vertical ScrollView Height and Paging Offset Issues in SwiftUI
Hi everyone, I'm currently working on an iOS app using SwiftUI, and I'm facing an issue with a vertical ScrollView. My goal is to have the ScrollView take up all the safe area space plus the top inset (with the bottom inset being an ultra-thin material) and enable paging behavior. However, I'm encountering two problems: The initial height of the ScrollView is too high (dragging the view (even without changing the page) adjusts the size). The paging offset of the ScrollView is incorrect (page views are not aligned). I’ve tried many things and combinations in desperation, including padding, safeAreaPadding, contentMargins, frame, fixedSize, containerRelativeFrame with callback, custom layout, and others, but nothing seems to work. If by any chance someone can help me find a solution, I’d greatly appreciate it. I suspect there are issues with the height defined by the ScrollView when some safe areas are ignored, leading to strange behavior when trying to set the height. It's challenging to explain everything in a simple post, so if someone from the SwiftUI team could look into this potential bug, that would be incredibly helpful. Thank you! import SwiftUI struct ScrollViewIssue: View { @State private var items: [(String, Color)] = [ ("One", .blue), ("Two", .green), ("Three", .red), ("Four", .purple) ] var body: some View { ZStack(alignment: .top) { ScrollView(.vertical) { VStack(spacing: 0) { ForEach(items, id: \.0) { item in ItemView(text: item.0, color: item.1) .containerRelativeFrame([.horizontal, .vertical]) } } } .printViewSize(id: "ScrollView") .scrollTargetBehavior(.paging) .ignoresSafeArea(edges: .top) VStack { Text("Title") .foregroundStyle(Color.white) .padding() .frame(maxWidth: .infinity) .background(Color.black.opacity(0.2)) Spacer() } } .printViewSize(id: "ZStack") .safeAreaInset(edge: .bottom) { Rectangle() .frame(width: .infinity, height: 0) .overlay(.ultraThinMaterial) } } } struct ItemView: View { let text: String let color: Color var body: some View { ZStack { RoundedRectangle(cornerRadius: 20) .fill(color.opacity(0.2)) .overlay( color, in: RoundedRectangle(cornerRadius: 20) .inset(by: 10 / 2) .stroke(lineWidth: 10) ) Text(text) } .printViewSize(id: "item") } } struct ViewSizeKey: PreferenceKey { static var defaultValue = CGSize() static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() } } extension View { func printViewSize(id: String) -> some View { background( GeometryReader { proxy in Color.clear .preference(key: ViewSizeKey.self, value: proxy.size) } .onPreferenceChange(ViewSizeKey.self) { value in print("\(id) size:\(value)") } ) } } #Preview { ScrollViewIssue() }
3
1
3.2k
Jul ’24
Why can't SwiftUI state be changed in the middle of view updates?
I have arrived at a certain architectural solution for my SwiftUI code which is helped by, in certain situations, modifying the state while the body is being evaluated. Of course, I am always open to realizing that a given solution may be creating difficulties precisely because it is fundamentally ill-advised. However, in this post I won't attempt to explain the details of my architecture or justify my reasoning regarding wanting to change the state in the middle of a view update. I just want to ask, why exactly is it prohibited? Is it not rather like normal recursion, which can of course produce infinite loops if done wrong but which is perfectly logically sound as long as the recursing function eventually stabilizes?
Topic: UI Frameworks SubTopic: SwiftUI
7
0
1k
Jul ’24
Live activities on watchOS not working on simulator
Is there a trick to getting the new Live Activities on Apple Watch working via the simulator? I have an iPhone paired to a watch simulator, but live activities created on the phone aren't appearing on the watch Smart Stack. It looks like maybe the Smart Stack isn't functional on the watch simulator, as there are a bunch of blank tiles where the Smart Stack should be.
3
5
1k
Jul ’24
Regression in UITabBarController on Catalyst when building under Xcode 16
I am running into an issue with UITabBarController in a Catalyst app when building under Xcode 16 and running on macOS 15. If a UITabBarController is used, the tabs are presented in an unwanted title/toolbar at the top of the window. If you have an app where your views run to the top of the window, this can obscure the content and controls that are near the top. I created a sample application that is attached to the Feedback record (FB14293963). When building under Xcode 15, this is what the app looks like: Under Xcode 16, it looks like this: Beyond this simple example, using UITabBarController in a presented view controller can result in the tabs not showing at all. Also, If you switch the view in the main window to something that isn't a UITabBarController, the tabs still remain at the top. This seems to stem from the tab bar/sidebar changes for iPadOS 18. While this approach can work for simpler apps, it may not work well at all for more complex apps and there really needs to be a way to opt out of this behavior so apps where it is not suited for can still take advantage of features in iPadOS/Catalyst 18. Has anyone discovered a workaround or way to disable the new tab bar behavior with having to write their own version of UITabBarController?
2
0
1.2k
Jul ’24
Not receive onDisappear event on the first WindowGroup
Hi, I'm working on visionOS and find I can't get onDisappear event just on the first window after app launch. It comes like that: WindowGroup(id:"WindowA"){ MyView() .onDisappear(){ print("WindowA disappear") } } WindowGroup(id:"WindowB"){ MyView() .onDisappear(){ print("WindowB disappear") } } WindowGroup(id:"WindowC"){ MyView() .onDisappear(){ print("WindowC disappear") } } When the app first launch, it will open WindowA automatically And then I open WindowB and WindowC programatically. Then I tap the close button on window bar below window. If I close WindowB/WindowC, I can receive onDisappear event If I close WindowA, I can't receive onDisappear event If I reopen WindowA after it is closed and then close it again by tap the close button below window, I can receive onDisappear event Is there any logic difference for the first window on app launch? How can I get onDisappear Event for it. I'm using Xcode 16 beta 2
5
0
1k
Jul ’24
SwiftUI : NavigationStack in new iOS 18 TabView pushes twice when path in parameter
Hello, With iOS 18, when NavigationStack is in new TabView, with path parameter containing current navigation state is set, the navigation destination view is pushed twice. See below with example that pushes twice on iOS 18 but is correct on iOS 17 @MainActor class NavigationModel: ObservableObject { static let shared = NavigationModel() @Published var selectedTab: String @Published var homePath: [Route] @Published var testPath: [Route] } struct ContentView: View { @StateObject private var navigationModel: NavigationModel = NavigationModel.shared var body: some View { TabView(selection: $navigationModel.selectedTab){ HomeView() .tabItem { Label("Home", systemImage: "house") } .tag("home") TestView() .tabItem { Label("Test", systemImage: "circle") } .tag("test") } } } struct HomeView: View { @StateObject private var navigationModel: NavigationModel = NavigationModel.shared var body: some View { NavigationStack(path: $navigationModel.homePath){ VStack{ Text("home") NavigationLink(value: Route.test1("test1")){ Text("Go to test1") } } .navigationDestination(for: Route.self){ route in NavigationModelBuilder.findFinalDestination(route:route) } } } } I don't what causes the issue because it works well on iOS 16 and iOS 17. I think the path is somehow reset but I don't why (maybe by the TabView ?) Note that the bug only occurs with TabView. Don't really know if it is a TabView bug or if it is on my side. I filed a feedback with sample project FB14312064
34
11
6.8k
Jul ’24
WidgetBundle with ControlWidget does not work on iOS 17
I'm trying to add a ControlWidget to my WidgetBundle like this: struct MyWidgets: WidgetBundle { var body: some Widget { if #available(iOSApplicationExtension 18.0, *) { LauncherControl() } MyLiveActivityWidget() HomeScreenWidget() LockScreenWidget() } This works exactly as expected on iOS 18. However on iOS 17 my app seems to have no widgets at all. The workaround described here (https://www.avanderlee.com/swiftui/variable-widgetbundle-configuration/) does not work either since WidgetBundleBuilder.buildBlock does not accept ControlWidget as an argument. What is the correct way to include a Control widget conditionally on iOS 18?
5
1
3.4k
Jul ’24
Combining NavigationSplitView and TabView in iOS 18
Hi folks, I've used a NavigationSplitView within one of the tabs of my app since iOS 16, but with the new styling in iOS 18 the toolbar region looks odd. In other tabs using e.g. simple stacks, the toolbar buttons are horizontally in line with the new tab picker, but with NavigationSplitView, the toolbar leaves a lot of empty space at the top (see below). Is there anything I can do to adjust this, or alternatively, continue to use the old style? Thanks!
11
3
2.6k
Jul ’24
iOS 18 beta bug: NavigationStack pushes the same view twice
Hello, community and Apple engineers. I need your help. Our app has the following issue: NavigationStack pushes a view twice if the NavigationStack is inside TabView and NavigationStack uses a navigation path of custom Hashable elements. Our app works with issues in Xcode 18 Beta 13 + iOS 18.0. The same issue happened on previous beta versions of Xcode 18. The issue isn’t represented in iOS 17.x and everything worked well before iOS 18.0 beta releases. I was able to represent the same issue in a clear project with two simple views. I will paste the code below. Several notes: We use a centralised routing system in our app where all possible routes for navigation path are implemented in a View extension called withAppRouter(). We have a enum RouterDestination that contains all possible routes and is resolved in withAppRouter() extension. We use Router class that contains @Published var path: [RouterDestination] = [] and this @Published property is bound to NavigationStack. In the real app, we need to have an access to this path property for programmatic navigation purposes. Our app uses @ObservableObject / @StateObject approach. import SwiftUI struct ContentView: View { @StateObject private var router = Router() var body: some View { TabView { NavigationStack(path: $router.path) { NavigationLink(value: RouterDestination.next, label: { Label("Next", systemImage: "plus.circle.fill") }) .withAppRouter() } } } } enum RouterDestination: Hashable { case next } struct SecondView: View { var body: some View { Text("Screen 2") } } class Router: ObservableObject { @Published var path: [RouterDestination] = [] } extension View { func withAppRouter() -> some View { navigationDestination(for: RouterDestination.self) { destination in switch destination { case .next: return SecondView() } } } } Below you can see the GIF with the issue: What I tried to do: Use iOS 17+ @Observable approach. It didn’t help. Using @State var path: [RouterDestination] = [] directly inside View seems to help. But it is not what we want as we need this property to be @Published and located inside Router class where we can get an access to it, and use for programmatic navigation if needed. I ask Apple engineers to help with that, please, and if it is a bug of iOS 18 beta, then please fix it in the next versions of iOS 18.0
12
4
1.8k
Jul ’24