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

Activity

A Summary of the WWDC25 Group Lab - UI Frameworks
At WWDC25 we launched a new type of Lab event for the developer community - Group Labs. A Group Lab is a panel Q&A designed for a large audience of developers. Group Labs are a unique opportunity for the community to submit questions directly to a panel of Apple engineers and designers. Here are the highlights from the WWDC25 Group Lab for UI Frameworks. How would you recommend developers start adopting the new design? Start by focusing on the foundational structural elements of your application, working from the "top down" or "bottom up" based on your application's hierarchy. These structural changes, like edge-to-edge content and updated navigation and controls, often require corresponding code modifications. As a first step, recompile your application with the new SDK to see what updates are automatically applied, especially if you've been using standard controls. Then, carefully analyze where the new design elements can be applied to your UI, paying particular attention to custom controls or UI that could benefit from a refresh. Address the large structural items first then focus on smaller details is recommended. Will we need to migrate our UI code to Swift and SwiftUI to adopt the new design? No, you will not need to migrate your UI code to Swift and SwiftUI to adopt the new design. The UI frameworks fully support the new design, allowing you to migrate your app with as little effort as possible, especially if you've been using standard controls. The goal is to make it easy to adopt the new design, regardless of your current UI framework, to achieve a cohesive look across the operating system. What was the reason for choosing Liquid Glass over frosted glass, as used in visionOS? The choice of Liquid Glass was driven by the desire to bring content to life. The see-through nature of Liquid Glass enhances this effect. The appearance of Liquid Glass adapts based on its size; larger glass elements look more frosted, which aligns with the design of visionOS, where everything feels larger and benefits from the frosted look. What are best practices for apps that use customized navigation bars? The new design emphasizes behavior and transitions as much as static appearance. Consider whether you truly need a custom navigation bar, or if the system-provided controls can meet your needs. Explore new APIs for subtitles and custom views in navigation bars, designed to support common use cases. If you still require a custom solution, ensure you're respecting safe areas using APIs like SwiftUI's safeAreaInset. When working with Liquid Glass, group related buttons in shared containers to maintain design consistency. Finally, mark glass containers as interactive. For branding, instead of coloring the navigation bar directly, consider incorporating branding colors into the content area behind the Liquid Glass controls. This creates a dynamic effect where the color is visible through the glass and moves with the content as the user scrolls. I want to know why new UI Framework APIs aren’t backward compatible, specifically in SwiftUI? It leads to code with lots of if-else statements. Existing APIs have been updated to work with the new design where possible, ensuring that apps using those APIs will adopt the new design and function on both older and newer operating systems. However, new APIs often depend on deep integration across the framework and graphics stack, making backward compatibility impractical. When using these new APIs, it's important to consider how they fit within the context of the latest OS. The use of if-else statements allows you to maintain compatibility with older systems while taking full advantage of the new APIs and design features on newer systems. If you are using new APIs, it likely means you are implementing something very specific to the new design language. Using conditional code allows you to intentionally create different code paths for the new design versus older operating systems. Prefer to use if #available where appropriate to intentionally adopt new design elements. Are there any Liquid Glass materials in iOS or macOS that are only available as part of dedicated components? Or are all those materials available through new UIKit and AppKit views? Yes, some variations of the Liquid Glass material are exclusively available through dedicated components like sliders, segmented controls, and tab bars. However, the "regular" and "clear" glass materials should satisfy most application requirements. If you encounter situations where these options are insufficient, please file feedback. If I were to create an app today, how should I design it to make it future proof using Liquid Glass? The best approach to future-proof your app is to utilize standard system controls and design your UI to align with the standard system look and feel. Using the framework-provided declarative API generally leads to easier adoption of future design changes, as you're expressing intent rather than specifying pixel-perfect visuals. Pay close attention to the design sessions offered this year, which cover the design motivation behind the Liquid Glass material and best practices for its use. Is it possible to implement your own sidebar on macOS without NSSplitViewController, but still provide the Liquid Glass appearance? While technically possible to create a custom sidebar that approximates the Liquid Glass appearance without using NSSplitViewController, it is not recommended. The system implementation of the sidebar involves significant unseen complexity, including interlayering with scroll edge effects and fullscreen behaviors. NSSplitViewController provides the necessary level of abstraction for the framework to handle these details correctly. Regarding the SceneDelagate and scene based life-cycle, I would like to confirm that AppDelegate is not going away. Also if the above is a correct understanding, is there any advice as to what should, and should not, be moved to the SceneDelegate? UIApplicationDelegate is not going away and still serves a purpose for application-level interactions with the system and managing scenes at a higher level. Move code related to your app's scene or UI into the UISceneDelegate. Remember that adopting scenes doesn't necessarily mean supporting multiple scenes; an app can be scene-based but still support only one scene. Refer to the tech note Migrating to the UIKit scene-based life cycle and the Make your UIKit app more flexible WWDC25 session for more information.
Topic: UI Frameworks SubTopic: General
0
0
658
Jun ’25
siri caused the app to crash
Some users experience this kind of crash: NSInternalInconsistencyException:Use of the class INVocabulary requires the entitlement com.apple.developer.siri. Make sure you have enabled the Siri capability in your Xcode project. During app startup, calling the following code causes a crash: INVocabulary *vocabulary = [INVocabulary sharedVocabulary]; But our project definitely has siri configured to be available. Now that we can't figure it out, is it a bug in the system?
Topic: UI Frameworks SubTopic: UIKit Tags:
1
0
379
Dec ’24
UIKit Internal bug: Unbalanced call to _endOcclusion, please file a feedback report with any information you have that helps reproduce this bug!
Hi, I'm getting a bug in SwiftUI when dismissing a sheet and then hitting the back button or swiping to go back in a navigation stack. This issue happens inconsistently but causes undesirable behavior where the screen freezes in a partially dismissed state but does not crash. A user can click on another tab and return back and the view will have completed dismissal. The error seems more likely to happen if the time between dismissing the sheet and navigating backwards is minimal. I've experimenting using different forms of navigation, NavigationStack using NavigationPaths and NavigationDestinations, NavigationLinks, NavigationViews, etc. The issue persists. Is there a nice fix or intended fix to this issue coming soon? Thank you!
Topic: UI Frameworks SubTopic: UIKit
1
0
337
Dec ’24
Discovered a bug where Alert button colors are changed by the tint modifier.
I used .tint(.yellow) to change the default back button color. However, I noticed that the color of the alert button text, except for .destructive, also changed. Is this a bug or Apple’s intended behavior? this occurs in iOS 18.1 and 18.1.1 Below is my code: // App struct TintTestApp: App { var body: some Scene { WindowGroup { MainView() .tint(.yellow) } } } // MainView var mainContent: some View { Text("Next") .foregroundStyle(.white) .onTapGesture { isShowingAlert = true } .alert("Go Next View", isPresented: $isShowingAlert) { Button("ok", role: .destructive) { isNextButtonTapped = true } Button("cancel", role: .cancel) { } } } thank you!
Topic: UI Frameworks SubTopic: SwiftUI Tags:
1
1
505
Dec ’24
Macos 15.2 beta 4 App Crash
I have a SwiftUI based program that has compiled and run consistently on previous macos versions. After upgrading to 15.2 beta 4 to address a known issue with TabView in 15.1.1, my app is now entering a severe hang and crashing with: "The window has been marked as needing another Update Contraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window. .<SwiftUI.AppKitWindow: 0x11d82a800> 0x87 (2071) {{44,0},{1468,883}} en" Is there a known bug that could be causing this crash or known change in the underlying layout model?
Topic: UI Frameworks SubTopic: SwiftUI
1
0
404
Dec ’24
MTKView delegate ownership during view controller transitions
The Problem When transitioning between view controllers that each have their own MTKView but share a Metal renderer backend, we run into delegate ownership conflicts. Only one MTKView can successfully render at a time, since setting the delegate on one view requires removing it from the other, leading to paused views during transitions. For my app, I need to display the same visuals across multiple views and have them all render correctly. Current Implementation Approach I've created a container object that manages the MTKView and its relationship with the shared renderer: class RenderContainer { let metalView: MTKView private let renderer: MetalRenderer func startRendering() { metalView.delegate = renderer metalView.isPaused = false } func stopRendering() { metalView.isPaused = true metalView.delegate = nil } } View controllers manage the rendering lifecycle in their view appearance methods: override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) renderContainer.startRendering() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) renderContainer.stopRendering() } Observations & Issues During view controller transitions, one MTKView must stop rendering before the other can start. Also there is no guarantee that the old view will stop rendering before the new one starts, with the current API design. This creates a visual "pop" during animated transitions Setting isPaused = true helps prevent unnecessary render calls but doesn't solve the core delegate ownership problem The shared renderer maintains its state but can only output to one view at a time Questions What's the recommended approach for handling MTKView delegate ownership during animated transitions? Are there ways to maintain visual continuity without complex view hierarchies? Should I consider alternative architectures for sharing the Metal content between views? Any insights for this scenario would be appreciated.
1
0
533
Dec ’24
Crash with UITextView intelligenceCollectContent Apple Intelligence
Hello, I am using Xcode 15.3 and doesn't add any support for Apple Intelligence yet as it requires Xcode 16+. But I see many crashlogs related to Apple Intelligence, I assume crash is related to UITextView element of UIKit. Can you please help me to resolve this issue, how can I fix it? There are few lines of the crashlog, they are all similar. Thread 0 name: Thread 0 Crashed: 0 UIKitCore 0x0000000196692d74 specialized UITextView._intelligenceCollectContent(in:collector:) + 2748 (UITextView_IntelligenceSupport.swift:37) 1 UIKitCore 0x0000000196691eb0 @objc UITextView._intelligenceCollectContent(in:collector:) + 60 (<compiler-generated>:17) 2 UIIntelligenceSupport 0x000000026b91f1e4 UIIntelligenceElementCollector.performCollection(_:) + 424 (UIIntelligenceElementCollector.swift:46) 3 UIKitCore 0x0000000196473b70 specialized UIView._intelligenceElement(in:using:transformToRoot:) + 1440 (UIView_IntelligenceSupport.swift:132) 4 UIKitCore 0x000000019647a800 specialized UIView._intelligenceCollectElement(for:in:using:transformToRoot:) + 424 (UIView_IntelligenceSupport.swift:84) 5 UIKitCore 0x00000001964792ec @objc UIView._intelligenceCollectElement(for:in:using:transformToRoot:) + 136 (<compiler-generated>:77) 6 UIKitCore 0x0000000196472c20 closure #1 in UIView._intelligenceCollectSubelements(in:using:transformToRoot:) + 256 (UIView_IntelligenceSupport.swift:55) 7 UIIntelligenceSupport 0x000000026b91f728 UIIntelligenceElementCollector.performElementCollection(_:) + 424 (UIIntelligenceElementCollector.swift:61) v 8 UIKitCore 0x00000001964728f4 UIView._intelligenceCollectSubelements(in:using:transformToRoot:) + 928 (UIView_IntelligenceSupport.swift:54) 9 UIKitCore 0x0000000196473354 @objc UIView._intelligenceCollectSubelements(in:using:transformToRoot:) + 136 (<compiler-generated>:0) 10 UIKitCore 0x0000000196479810 closure #3 in UIView._intelligenceElement(in:using:transformToRoot:) + 256 (UIView_IntelligenceSupport.swift:165) 11 UIIntelligenceSupport 0x000000026b91fb54 UIIntelligenceElementCollector.performElementArrayCollection(_:) + 144 (UIIntelligenceElementCollector.swift:78) ... ... 225 UIIntelligenceSupport 0x000000026b8ee630 closure #1 in IntelligenceCollectionListener.collectFragments(_:) + 192 (IntelligenceCollectionListener.swift:60) 226 UIIntelligenceSupport 0x000000026b91b138 thunk for @escaping @callee_guaranteed () -> () + 36 227 CoreFoundation 0x000000019376b6e4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 28 (CFRunLoop.c:1818) 228 CoreFoundation 0x0000000193759910 __CFRunLoopDoBlocks + 356 (CFRunLoop.c:1860) 229 CoreFoundation 0x00000001937595f4 __CFRunLoopRun + 2432 (CFRunLoop.c:3217) 230 CoreFoundation 0x0000000193758830 CFRunLoopRunSpecific + 588 (CFRunLoop.c:3434) 231 GraphicsServices 0x00000001df7381c4 GSEventRunModal + 164 (GSEvent.c:2196) 232 UIKitCore 0x00000001962beeb0 -[UIApplication _run] + 816 (UIApplication.m:3844)
3
0
792
Dec ’24
Screen record restriction in MacOS app
I have a MacOs AppKit app. This app we are developing for examination purposes. We dont want the user to screen record and also to take screen shot. We created a window and set the sharingType to none. also we have set window.level to CGShieldingWindowLevel() Below is the code if let window = NSApp.windows.first { window.title = "Test" window.sharingType = .none // Disable screen capture and recording window.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel())) // } As per documentation the windows should be excluded from screen capture and also recording But the window is excluded only from screen capture and not from screen recording. Please give us a solution to prevent screen recording in MacOs native app.
Topic: UI Frameworks SubTopic: AppKit Tags:
3
0
605
Dec ’24
Sharelink in WatchOS and Messages App
I’m relatively new to SwiftUI, so I’ve got a pretty basic question here. In my watchOS app, I’m using ShareLink to share a string of text to the Mail and Messages apps. Mail shows up in the ShareLink sheet just fine, but Messages doesn’t appear. What’s odd is that when I run the app in Xcode’s preview or in the Simulator, Messages does show up as a sharing option… So now I’m wondering if this is just a quirk with my device or if Apple doesn’t actually support sharing text to Messages from third-party watchOS apps yet? I know some Apple Watch apps (like Contacts) do support sending text/files to Messages, so I’m curious if anyone’s had a similar experience or knows more about this. Any insights would be super helpful!
8
2
629
Dec ’24
ActivityKit crashes when requesting to create a Live Activity
Our app occasionally crashes when creating a Live Activity using ActivityKit. Crash log analysis indicates a wild pointer issue originating within ActivityKit. The crash appears to be linked to the coexistence of multiple Live Activities. Could this be a compatibility issue with ActivityKit? We would appreciate any guidance or potential workarounds to resolve this issue. Looking forward to your response. Thread 0 Crashed: 0 ActivityKit 0x000000023023d034 0x230235000 + 32820 ( + 13792) 1 ActivityKit 0x000000023023d014 0x230235000 + 32788 ( + 13760) 2 Combine 0x00000001ac5bd168 0x1ac5b5000 + 33128 ( + 292) 3 Combine 0x00000001ac5c0658 0x1ac5b5000 + 46680 ( + 24) 4 Combine 0x00000001ac5d1714 0x1ac5b5000 + 116500 ( + 204) 5 Combine 0x00000001ac5c8da0 0x1ac5b5000 + 81312 ( + 24) 6 Combine 0x00000001ac5e8e98 0x1ac5b5000 + 212632 ( + 2520) 7 Combine 0x00000001ac5d1a4c 0x1ac5b5000 + 117324 ( + 24) 8 Combine 0x00000001ac68316c 0x1ac5b5000 + 844140 ( + 56) 9 Combine 0x00000001ac5d4a4c 0x1ac5b5000 + 129612 ( + 176) 10 Combine 0x00000001ac5bd43c 0x1ac5b5000 + 33852 ( + 392) 11 Combine 0x00000001ac5b7198 0x1ac5b5000 + 8600 ( + 24) 12 Combine 0x00000001ac5ead74 0x1ac5b5000 + 220532 ( + 712) 13 Combine 0x00000001ac5e2320 0x1ac5b5000 + 185120 ( + 24) 14 Combine 0x00000001ac5bfe74 0x1ac5b5000 + 44660 ( + 488) 15 Combine 0x00000001ac5b81b8 0x1ac5b5000 + 12728 ( + 24) 16 Combine 0x00000001ac5b8804 0x1ac5b5000 + 14340 (Just.receive(subscriber:) + 424) 17 Combine 0x00000001ac5f7a7c 0x1ac5b5000 + 273020 (Publishers.Merge.receive(subscriber:) + 820) 18 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 19 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 20 Combine 0x00000001ac5dc9cc 0x1ac5b5000 + 162252 ( + 548) 21 Combine 0x00000001ac5dc764 0x1ac5b5000 + 161636 (Publishers.HandleEvents.receive(subscriber:) + 620) 22 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 23 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 24 Combine 0x00000001ac5d92e8 0x1ac5b5000 + 148200 (Publishers.FlatMap.receive(subscriber:) + 416) 25 Combine 0x00000001ac5dc9cc 0x1ac5b5000 + 162252 ( + 548) 26 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 27 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 28 Combine 0x00000001ac5f062c 0x1ac5b5000 + 243244 (Publishers.CompactMap.receive(subscriber:) + 572) 29 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 30 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 31 Combine 0x00000001ac5e64e4 0x1ac5b5000 + 201956 (Publishers.SetFailureType.receive(subscriber:) + 552) 32 Combine 0x00000001ac5d92e8 0x1ac5b5000 + 148200 (Publishers.FlatMap.receive(subscriber:) + 416) 33 Combine 0x00000001ac5dc9cc 0x1ac5b5000 + 162252 ( + 548) 34 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 35 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 36 Combine 0x00000001ac5f062c 0x1ac5b5000 + 243244 (Publishers.CompactMap.receive(subscriber:) + 572) 37 Combine 0x00000001ac5d9850 0x1ac5b5000 + 149584 (PublisherBox.receive(subscriber:) + 108) 38 Combine 0x00000001ac5b8154 0x1ac5b5000 + 12628 (AnyPublisher.receive(subscriber:) + 64) 39 Combine 0x00000001ac5bdd68 0x1ac5b5000 + 36200 (Publishers.ReceiveOn.receive(subscriber:) + 812) 40 Combine 0x00000001ac5f1e10 0x1ac5b5000 + 249360 (Publisher.sink(receiveCompletion:receiveValue:) + 304) 41 ActivityKit 0x00000002302594a0 0x230235000 + 148640 ( + 6064) 42 ActivityKit 0x0000000230258c18 0x230235000 + 146456 ( + 3880) 43 ActivityKit 0x0000000230258410 0x230235000 + 144400 ( + 1824) 44 ActivityKit 0x0000000230258124 0x230235000 + 143652 ( + 1076) 45 ActivityKit 0x0000000230258080 0x230235000 + 143488 ( + 912) 46 ActivityKit 0x000000023026d280 0x230235000 + 230016 ( + 4228) 47 ActivityKit 0x000000023026d39c 0x230235000 + 230300 ( + 4512) 48 libswiftDispatch.dylib 0x00000001ac59e7f4 0x1ac59d000 + 6132 ( + 28) 49 libswiftDispatch.dylib 0x00000001ac5a5a90 0x1ac59d000 + 35472 ( + 16) 50 libswiftDispatch.dylib 0x00000001ac59f97c 0x1ac59d000 + 10620 ( + 188) 51 libswiftDispatch.dylib 0x00000001ac59fa90 0x1ac59d000 + 10896 ( + 28) 52 libswiftDispatch.dylib 0x00000001ac59f5ec 0x1ac59d000 + 9708 ( + 28) 53 libdispatch.dylib 0x00000001ab37feac 0x1ab37c000 + 16044 ( + 20) 54 libdispatch.dylib 0x00000001ab38f428 0x1ab37c000 + 78888 ( + 56) 55 libswiftDispatch.dylib 0x00000001ac59ef38 0x1ac59d000 + 7992 ( + 180) 56 libswiftDispatch.dylib 0x00000001ac59e0dc 0x1ac59d000 + 4316 ( + 56) 57 libswiftDispatch.dylib 0x00000001ac59ec48 0x1ac59d000 + 7240 ( + 396) 58 libswiftDispatch.dylib 0x00000001ac59e188 0x1ac59d000 + 4488 (OS_dispatch_queue.sync(execute:) + 164) 59 ActivityKit 0x000000023026be70 0x230235000 + 224880 ( + 3228) 60 ActivityKit 0x000000023026b400 0x230235000 + 222208 ( + 556) 61 ActivityKit 0x00000002302d10b4 0x230235000 + 639156 ( + 25780) 62 ActivityKit 0x00000002302d0cd0 0x230235000 + 638160 ( + 24784) 63 ActivityKit 0x00000002302d0b94 0x230235000 + 637844 ( + 24468) 64 xxxx 0x0000000100919638 specialized static LiveActivityManager.startActivity(title:) + 169528 (LiveActivityManager.swift:96)
1
0
401
Dec ’24
Application terminates on sleep even if windows are not closed
I've received some reports from users of my macOS app that the application quits when putting their Mac to sleep after hiding all windows. The NSApplicationDelegate implements applicationShouldTerminateAfterLastWindowClosed and returns true. However this method is called even though there are still windows open. Unfortunately I'm not able to reproduce the issue, but here are the steps to reproduce according to the user: Open app (single NSWindow visible) Press Command-H to hide the single window Put Mac to sleep The app is terminated when the Mac wakes. These steps have been confirmed by a user in Safe Mode, so I expect no interference of other applications (macOS 15.1.1). When this happens the application logs show that applicationShouldTerminateAfterLastWindowClosed is called when the Mac goes to sleep. But the main NSWindow is still open (yet hidden). The close() method on NSWindow is not called before applicationShouldTerminateAfterLastWindowClosed. Order of events: NSApplicationDelegate.applicationWillHide NSApplicationDelegate.applicationWillResignActive [...] NSApplicationDelegate.applicationShouldTerminateAfterLastWindowClosed NSApplicationDelegate.applicationShouldTerminate NSApplicationDelegate.applicationWillTerminate NSWindow.close I assumed that applicationShouldTerminateAfterLastWindowClosed is only called after all windows are closed. Is that assumption incorrect? Does a user-hidden NSWindow count as a closed window? For me (and other users) the API works as expected and the app stays running when the app is hidden as the Mac sleeps. applicationShouldTerminateAfterLastWindowClosed is not called until all windows are actually closed.
Topic: UI Frameworks SubTopic: AppKit
1
1
414
Dec ’24
UIDocumentPickerViewController Dismisses Automatically Twice When Selecting Multiple Files Quickly
Description: When using UIDocumentPickerViewController in iOS, if the user taps two or more files in quick succession, the picker view controller dismisses itself automatically twice. This results in an unintended behavior, leading to inconsistent screen states or redundant dismiss animations. Steps to Reproduce: Initialize a UIDocumentPickerViewController instance in UIDocumentPickerModeImport. UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[(NSString *)kUTTypeData] inMode:UIDocumentPickerModeImport]; documentPicker.delegate = self; documentPicker.modalPresentationStyle = UIModalPresentationFullScreen; documentPicker.allowsMultipleSelection = NO; [self presentViewController:documentPicker animated:YES completion:nil]; Launch the document picker. Quickly tap two or more files in succession. Expected Behavior: The UIDocumentPickerViewController should dismiss once and call the delegate method documentPicker:didPickDocumentsAtURLs: with the selected file(s). Actual Behavior: The UIDocumentPickerViewController automatically dismisses twice. This issue occurs even when no explicit call to dismissViewControllerAnimated: is made in the delegate method. Observed Results: The didPickDocumentsAtURLs: callback is invoked after the picker is already dismissed. During this process, unintended behavior such as multiple dismiss animations, view controller state corruption, or UI inconsistencies may occur. Impact: This issue disrupts the user experience and causes UI glitches when selecting documents. It prevents developers from having full control over dismiss behavior or mitigating the problem programmatically. Environment: iOS Version: iOS 15.0 and later (also reproduced on iOS 17.4) Device: Reproducible on multiple iPhone and iPad models Framework: UIKit Conclusion: This appears to be a system-level issue with UIDocumentPickerViewController. The automatic dismiss behavior is not correctlyhandling multiple taps, causing unintended dismiss events. Developers have no explicit way to prevent this behavior or gain full control over the dismissal process. We kindly request Apple to investigate and resolve this issue to ensure UIDocumentPickerViewController behaves as expected when interacting with multiple taps.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
1
377
Dec ’24
iOS 18 crash issue for unnecessary dequeuing
My code extension MyViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell { if let cell = collectionView.dequeueReusableCell( withReuseIdentifier: "CollectionViewCellID", for: indexPath ) as? CollectionViewCell { cell.setup() return cell } return UICollectionViewCell() } func collectionView( _ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath ) { // Unnecessary dequeue guard collectionView.dequeueReusableCell( withReuseIdentifier: "CollectionViewCellID", for: indexPath ) is CollectionViewCell else { return } // My action for selecting cell print("Cell Selected") } } Error: *** Assertion failure in -[UICollectionView _updateVisibleCellsNow:], UICollectionView.m:5673 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:]. Solution: The problem was doing unnecessary dequeuing in didSelectItemAt when selecting the cell. In previous iOS like 17 or 16 or lower, it was allowed to dequeue where it is not really needed but from iOS 18, it may restricted to unnecessary dequeuing. So better to remove dequeue and use cellForItem(at) if we need to get cell from collection view. Example extension MyViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell { if let cell = collectionView.dequeueReusableCell( withReuseIdentifier: "CollectionViewCellID", for: indexPath ) as? CollectionViewCell { cell.setup() return cell } return UICollectionViewCell() } func collectionView( _ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath ) { guard collectionView.cellForItem(at: indexPath) is CollectionViewCell else { return } // My action for selecting cell print("Cell Selected") } }
0
0
3.6k
Dec ’24
iOS 18 iPad Toolbar .principal Placement
Hi, I am having some spacing issues with the new TabViewStyle.sidebarAdaptable. My app uses @ToolBarContentBuilder for navigationBar elements as there are some custom design requirements. One of these is title text that is set in the principal position. Simplified example: var body: some View { Text("Body") .toolbar { toolbar() } } @ToolbarContentBuilder private func toolbar() -> some ToolbarContent { ToolbarItem(placement: placement) { Text("Title") } } Everything with this setup works fine till I use an iPad with iOS 18 where the new toggleable sidebar is present. Upon switching to the sidebar layout the title does not move to the space adjacent to the navigation button (where the tab bar just was) and instead remains in its own bar, below the rest of the navigation. I've noticed that when navigationTitle is set the the title set in toolbar() does appear in the right place. var body: some View { Text("Body") .toolbar { toolbar() } .navigationTitle("anything") } Is this expected behaviour? How can I achieve a single line nav bar with a title set this way? Happy to provide a sandbox app to reproduce this issue. Many thanks, Matt
0
1
622
Dec ’24
SwiftUI Toolbar Item buttons not registering taps
Before I updated to iOS 18 everything worked fine. I pushed out an update to my application on the App Store and I had no issues. After updating to the latest OS many of my touch events are no longer working and I have no idea why. Sometimes when the app runs the touch events work fine and other times I can't click on half of my views & buttons. I am completely lost as to what might be happening. I am having issues all over the application but let's focus on the navigation stack and the toolbar item buttons. I will post some code snippets, I have been unable to replicate this in a small playground project. This is my setup, I have two buttons but lets focus on the home & notifications view. The custom Router import SwiftUI import Foundation @Observable class HomeRouter { var navPath = NavigationPath() @MainActor func navigate(to destination: HOME_ROUTES) { navPath.append(destination) } @MainActor func navigateBack() { navPath.removeLast() } @MainActor func navigateToRoot() { navPath.removeLast(navPath.count) } } Home View import os import SwiftUI import CoreLocation import NotificationCenter struct Home: View { @State public var router: HomeRouter @State private var showDetail = false @State private var showMoreFields = false @EnvironmentObject private var session: SessionStore private var log = Logger(subsystem: "com.olympsis.client", category: "home_view") init(router: HomeRouter = HomeRouter()) { self._router = State(initialValue: router) } var body: some View { NavigationStack(path: $router.navPath) { ScrollView(.vertical) { //MARK: - Welcome message WelcomeCard() .padding(.top, 25) .environmentObject(session) // MARK: - Announcements AnnouncementsView() .environmentObject(session) // MARK: - Next Events NextEvents() .environmentObject(session) // MARK: - Hot Events HotEvents() .environmentObject(session) // MARK: - Nearby Venues NearbyVenues() .environmentObject(session) Spacer(minLength: 100) } .toolbar { ToolbarItem(placement: .topBarLeading) { Text("Olympsis") .italic() .font(.largeTitle) .fontWeight(.black) } ToolbarItemGroup(placement: .topBarTrailing) { Button(action: { router.navigate(to: .messages) }) { ZStack(alignment: .topTrailing) { Image(systemName: "bubble.left.and.bubble.right") .foregroundStyle(Color.foreground) if session.invitations.count > 0 { NotificationCountView(value: $session.invitations.count) } } } Button(action: { router.navigate(to: .notifications) }) { ZStack(alignment: .topTrailing) { Image(systemName: "bell") .foregroundStyle(Color.foreground) if session.invitations.count > 0 { NotificationCountView(value: $session.invitations.count) } } } } } .background(Color("background-color/primary")) .navigationDestination(for: HOME_ROUTES.self, destination: { route in switch route { case .notifications: NotificationsView() .id(HOME_ROUTES.notifications) .environment(router) .environmentObject(session) .navigationBarBackButtonHidden() case .messages: HomeMessagesView() .id(HOME_ROUTES.messages) .environment(router) .environmentObject(session) .navigationBarBackButtonHidden() case .full_post_view(let id): AsyncPostView(postId: id) .id(HOME_ROUTES.full_post_view(id)) .environmentObject(session) .navigationBarBackButtonHidden() } }) } } } #Preview { Home() .environmentObject(SessionStore()) } The Notifications View import SwiftUI struct NotificationsView: View { @State private var notifications: [NotificationModel] = [] @Environment(HomeRouter.self) private var router @EnvironmentObject private var session: SessionStore var body: some View { ScrollView { if notifications.count > 0 { ForEach(notifications, id: \.id){ note in NotificationModelView(notification: note) } } else { VStack { Text("No new notifications") HStack { Spacer() } }.padding(.top, 50) } } .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .topBarLeading) { Button(action:{ router.navigateBack() }) { Image(systemName: "chevron.left") .foregroundStyle(Color.foreground) } } ToolbarItem(placement: .principal) { Text("Notifications") } } .task { notifications = session.invitations.map({ i in NotificationModel(id: UUID().uuidString, type: "invitation", invite: i, body: "") }) } } } #Preview { NavigationStack { NotificationsView() .environment(HomeRouter()) .environmentObject(SessionStore()) } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
481
Dec ’24
what it that func in CoreText ?
I can use CGContextShowText to display character. and what I should use in CoreText? I find there is NSAttributedString but there is lack of setShouldAntialias and setAllowsAntialiasing(Bool) in NSAttributedString I DO NOT want to use Antialiase which means I want to set Antialiase to FALSE when I display characters
1
0
332
Dec ’24
SwiftUI.Stepper bug from `onIncrement` and `onDecrement`?
Ok… I'm baffled here… this is very strange. Here is a SwiftUI app: import SwiftUI @main struct StepperDemoApp: App { func onIncrement() { print(#function) } func onDecrement() { print(#function) } var body: some Scene { WindowGroup { Stepper { Text("Stepper") } onIncrement: { self.onIncrement() } onDecrement: { self.onDecrement() } } } } When I run in the app in macOS (Xcode 16.0 (16A242) and macOS 14.6.1 (23G93)), I see some weird behavior from these buttons. My experiment is tapping + + + - - -. Here is what I see printed: onIncrement() onIncrement() onIncrement() onIncrement() onDecrement() What I expected was: onIncrement() onIncrement() onIncrement() onDecrement() onDecrement() onDecrement() Why is an extra onIncrement being called? And why is one onDecrement dropping on the floor? Deploying the app to iPhone Simulator does not repro this behavior (I see the six "correct" logs from iPhone Simulator).
9
0
750
Dec ’24
Image Playground API
Hi, WWDC24 videos have a lot of references to an "Image Playground" API, and the "What's New in AppKit" session even shows it in action, with a "ImagePlaygroundViewController". However, there doesn't seem to be any access to the new API, even with Xcode 16.2 beta. Am I missing something, or is that 'coming later'?
5
1
1.3k
Dec ’24
How to draw emojis like the Lock Screen customisation?
On iOS you can create a new Lock Screen that contains a bunch of emoji, and they'll get put on the screen in a repeating pattern, like this: When you have two or more emoji they're placed in alternating patterns, like this: How do I write something like that? I need to handle up to three emoji, and I need the canvas as large as the device's screen, and it needs to be saved as an image. Thanks! (I've already written an emojiToImage() extension on String, but it just plonks one massive emoji in the middle of an image, so I'm doing something wrong there.)
1
0
604
Dec ’24