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

Post

Replies

Boosts

Views

Activity

Observe currentEDRHeadroom for changes
Is there a way to observe the currentEDRHeadroom property of UIScreen for changes? KVO is not working for this property... I understand that I can query the current headroom in the draw(...) method to adapt the rendering. However, our apps only render on-demand when the user changes parameters. But we would also like to re-render when the current EDR headroom changes to adapt the tone mapping to the new environment. The only solution we've found so far is to continuously query the screen for changes, which doesn't seem ideal. It would be better if the property would be observable via KVO or if there would be a system notification to listen for. Thanks!
2
0
1.1k
Jan ’23
Crash in [UIViewController _presentViewController:withAnimationController:completion:]
Our app has a Crash, here is the Crash report. How should I investigate this error? Fatal Exception: NSInvalidArgumentException 0 CoreFoundation 0x9e48 __exceptionPreprocess 1 libobjc.A.dylib 0x178d8 objc_exception_throw 2 UIKitCore 0x326cbc -[UIViewController _presentViewController:withAnimationController:completion:] 3 UIKitCore 0x325c10 __63-[UIViewController _presentViewController:animated:completion:]_block_invoke 4 UIKitCore 0x349598 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] 5 UIKitCore 0x2b7a48 -[_UIViewControllerTransitionContext _runAlongsideCompletions] 6 UIKitCore 0x2b6ad8 -[_UIViewControllerTransitionContext completeTransition:] 7 UIKitCore 0x2b7c38 -[UITransitionView notifyDidCompleteTransition:] 8 UIKitCore 0x2b7838 -[UITransitionView _didCompleteTransition:] 9 UIKit 0xa7e58 -[UITransitionViewAccessibility _didCompleteTransition:] 10 UIKitCore 0x103d464 __UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__ 11 UIKitCore 0xd14ac -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] 12 UIKitCore 0xd0408 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] 13 UIKitCore 0xcfb28 -[UIViewAnimationState animationDidStop:finished:] 14 UIKit 0xb0f50 -[UIViewAnimationStateAccessibility animationDidStop:finished:] 15 UIKitCore 0xcfc3c -[UIViewAnimationState animationDidStop:finished:] 16 UIKit 0xb0f50 -[UIViewAnimationStateAccessibility animationDidStop:finished:] 17 QuartzCore 0x1310c CA::Layer::run_animation_callbacks(void*) 18 libdispatch.dylib 0x3fdc _dispatch_client_callout 19 libdispatch.dylib 0x127f4 _dispatch_main_queue_drain 20 libdispatch.dylib 0x12444 _dispatch_main_queue_callback_4CF 21 CoreFoundation 0x9a6d8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ 22 CoreFoundation 0x7c03c __CFRunLoopRun 23 CoreFoundation 0x80ec0 CFRunLoopRunSpecific 24 GraphicsServices 0x1368 GSEventRunModal 25 UIKitCore 0x3a186c -[UIApplication _run] 26 UIKitCore 0x3a14d0 UIApplicationMain 27 Authenticator 0x9334 main + 26 (AppDelegate.swift:26) 28 ??? 0x1b65de960 (シンボルが不足しています)
4
2
1.4k
Jan ’23
Struggling to display DeviceActivityReport view in a widget
I want to add a widget to my app that will display the # of pickups the user has for the day. I have the DeviceActivityReport working in the main app but can't get it to display in the widget since it is not a supported view for widgets. Is there any workaround for getting this view to the widget? I tried converting the DeviceActivityReport view to a UI image thinking maybe that would be a way to use a widget approved view type but ImageRenderer seems to fail to render an image for the view (which is just a Text view). To summarize my questions: Is it possible to display a DeviceActivityReport in a widget? If so, what is the best practice? Is converting the DeviceActivityReport view into an image and displaying that in a widget an option? Here's my attempt to convert the DeviceActivityReport view into a UIImage: import SwiftUI import _DeviceActivity_SwiftUI struct PickupsDeviceActivityReport: View {     @State private var context: DeviceActivityReport.Context = .totalActivity     @State private var renderedImage = Image(systemName: "exclamationmark.triangle")     @Environment(\.displayScale) var displayScale     var body: some View {         renderedImage             .onAppear { render() }             .onChange(of: context) {                 _ in render()             }     }     @MainActor func render() {         let renderer = ImageRenderer(content: DeviceActivityReport(context))         renderer.scale = displayScale         if let uiImage = renderer.uiImage {             renderedImage = Image(uiImage: uiImage)         }     } } Help is appreciated. Thank you.
3
1
1.1k
Jan ’23
A VZMacGraphicsDisplayConfiguration with a large resolution causes macOS Ventura to incorrectly draw its menu bar items.
Filed as rdar://FB11975037 When macOS Ventura is run as a guest OS within the virtualization framework, the main menu bar items will not be displayed correctly if VZMacGraphicsDisplayConfiguration defines a large resolution. The menu bar titles appear to be using the same color as the menu bar itself. When the Appearance is set to Light, the menu bar items are effectively invisible. When the Appearance is set to Dark, the menu bar items are drawn in what looks like a disabled state. This only affects the menu bar item titles on the left-hand side. The date-time and menu bar icons on the right side are always displayed in the correct color. This appears to be a regression in macOS Ventura as this issue is not present in macOS 12 running as a guest. This bug can be easily reproduced using Apple's own Virtualization sample code titled: "Running macOS in a Virtual Machine on Apple Silicon Macs" Steps to reproduce: Follow the sample code instructions for building and installing a VM.bundle. Before running 'macOSVirtualMachineSampleApp', change the VZMacGraphicsDisplayConfiguration to use: width = 5120, height = 2880, ppi = 144. Run 'macOSVirtualMachineSampleApp' and notice that the menu bar titles on the left side of the screen are not correctly drawn in the guest instance. This has been tested on: Host: macOS 13.1 Guest: macOS 13.x (All versions) Hardware: MBP 14" M1 Pro 32GB/2TB Is there anything that can be done to resolve this issue?
4
2
1.6k
Jan ’23
Allow custom tap gesture in List but maintain default selection gesture
I'm trying to create a List that allows multiple selection. Each row can be edited but the issue is that since there's a tap gesture on the Text element, the list is unable to select the item. Here's some code: import SwiftUI struct Person: Identifiable { let id: UUID let name: String init(_ name: String) { self.id = UUID() self.name = name } } struct ContentView: View { @State private var persons = [Person("Peter"), Person("Jack"), Person("Sophia"), Person("Helen")] @State private var selectedPersons = Set<Person.ID>() var body: some View { VStack { List(selection: $selectedPersons) { ForEach(persons) { person in PersonView(person: person, selection: $selectedPersons) { newValue in // ... } } } } .padding() } } struct PersonView: View { var person: Person @Binding var selection: Set<Person.ID> var onCommit: (String) -> Void = { newValue in } @State private var isEditing = false @State private var newValue = "" @FocusState private var isInputActive: Bool var body: some View { if isEditing { TextField("", text: $newValue, onCommit: { onCommit(newValue) isEditing = false }) .focused($isInputActive) .labelsHidden() } else { Text(person.name) .onTapGesture { if selection.contains(person.id), selection.count == 1 { newValue = person.name isEditing = true isInputActive = true } } } } } Right now, you need to tap on the row anywhere but on the text to select it. Then, if you tap on the text it'll go in edit mode. Is there a way to let the list do its selection? I tried wrapping the tap gesture in simultaneousGesture but that didn't work. Thanks!
3
2
1.6k
Feb ’23
SwiftUI’s LongPressGesture is broken
Problem LongPressGesture ignores minimumDuration parameter and succeeds immediately, also onEnded is never invoked. Steps to reproduce Take Apple’s own sample code from their documentation: LongPressGesture. Remove transaction.animation = Animation.easeIn(duration: 2.0) line to make the effect more obvious. Expected result: The circle must turn red after 3 seconds of pressing on it, and turn green when released. Actual result The circle turns red immediately and never turns green. Notes I tried many combinations of .gesture and .simultaneousGesture applied to different types of views. Was anyone able to make the minimum duration work when passed to .gesture modifier?
3
4
948
Mar ’23
UIDeferredMenuElement With Uncached Provider Not Working on Mac Catalyst. Uncached provider block never called and menu displays as "Loading"
I'm trying to create a dynamic menu on Mac Catalyst. Using a UIBarButtonitem like so to make a "pull down" button: UIDeferredMenuElement *deferredmenuElement; deferredmenuElement = [UIDeferredMenuElement elementWithUncachedProvider:^(void (^ _Nonnull completion)(NSArray<UIMenuElement *> * _Nonnull)) { UIAction *actionOne = [UIAction actionWithTitle:@"Action One" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action one fired."); }]; UIAction *actionTwo = [UIAction actionWithTitle:@"Action Two" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action two fired."); }]; UIAction *actionThree = [UIAction actionWithTitle:@"Action Three" image:nil identifier:nil handler:^(__kindof UIAction * _Nonnull action) { NSLog(@"action three fired."); }]; completion(@[actionOne,actionTwo,actionThree]); }]; UIMenu *wrappedMenu = [UIMenu menuWithChildren:@[deferredmenuElement]]; UIBarButtonItem *uiBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:nil menu:wrappedMenu]; uiBarButtonItem.image = [UIImage systemImageNamed:@"rectangle.and.pencil.and.ellipsis"]; self.navigationItem.rightBarButtonItems = @[uiBarButtonItem]; The button appears in the toolbar but when I click it to expose the menu I get a menu with on element in it that says "Loading...". The the uncached provider block is never called. Running Ventura 13.2.1 and Xcode 14.2.
8
2
1.8k
Mar ’23
NO ANIMATIONS in NavigationStack or NavigationSplitView
I'm building a macOS app using SwiftUI and I recently updated to xcode 14.3. Since then I've been debugging why none of my animations were working, it turned out that the NavigationSplitView or NavigationStack are somehow interfering with all the animations from withAnimation to .transition() and everything in between. Is anyone else experiencing this, knows a work around or knows why this is happening?
11
9
8.2k
Apr ’23
Why isn't the View protocol @MainActor?
Hi, It is known that if a SwiftUI view contains an @ObservedObject or @StateObject property, the View will inherit @MainActor isolation from the property wrappers. Similarly, the body view-builder is also marked @MainActor. What I'm wondering is why the whole SwiftUI View protocol isn't marked @MainActor. It seems to be a deliberate decision, but AFAICT it would make a lot of sense for all data and operations defined in a view to have main-actor isolation unless marked nonisolated. I'm currently adding @MainActor annotations to an existing codebase, and it's a bit awkward that some views automatically gain this attribute one way or another, while others need it explicitly applied. Is there a rationale that can be shared, or is this something which may be revised in future versions of the framework?
1
6
1.9k
May ’23
CloudKit Stopped Syncing after adding new Entities
Can someone please shed some light? I have an app that uses Core Data and CloudKit, up until the last version, I was able to sync data between devices but now after I added two new Entities for some reason it stopped syncing between devices. Here is how I did the change: Created a new Core Data container. Added the new Entities and their Attributes Tested the new Entities locally to be able to send the new schema to CloudKit. Went to CloudKit and made sure that the new Entities and Attributes were reflected on the Developent database. Deploy Schema Cahnges. Went to the Production database to make sure the new schema was deployed; and it was, both databases look the same. Testing: Tested in the simulator and with a real device and everything syncs, even the new Entities. If I download the app from the App Store on two different devices they do NOT sync. Based on the procedure I'm describing above, is there any important step I may have missed when doing the migration? I'm not sure if this is related to the syncing issue but after testing a few times, I no longer can turn the iCloud on, I get the following message when I try to turn iCloud Sync On. CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate resetAfterError:andKeepContainer:]: <NSCloudKitMirroringDelegate: 0x282c488c0> - resetting internal state after error: Error Domain=NSCocoaErrorDomain Code=134410 "CloudKit setup failed because there is another instance of this persistent store actively syncing with CloudKit in this process." UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/73F19BC7-4538-4098-85C7-484B36192CF3/Library/Application%20Support/CoreDataContainer.sqlite, NSLocalizedFailureReason=CloudKit setup failed because there is another instance of this persistent store actively syncing with CloudKit in this process., NSUnderlyingException=Illegal attempt to register a second handler for activity identifier com.apple.coredata.cloudkit.activity.setup.8D4C04F6-8040-445A-9447-E5646484521} Any idea of what could be wrong and preventing the devices from syncing? Any idea or suggestion is welcome. Thanks
3
0
2.8k
May ’23
Memoization in SwiftUI views
I have a view which shows some data based on a complex calculation. Let's say I need to parse some input string and transform it in some way. private func someComplexCalculation(_ input: String) -> String { // ... } The most naive approach would be to perform this in the view's body: struct MyView: View { let input: String var body: some View { Text(someComplexCalculation(input)) } } But of course, we want to keep body nice and fast because SwiftUI may call it very often. The text to be displayed will be constant for a particular view, in a particular place in the hierarchy (barring some major events such as locale changes, which can basically change the entire UI anyway). So the next idea would be to hoist the calculation out of body in to the view's initialiser: struct MyView: View { let value: String init(_ value: String) { self.value = someComplexCalculation(value) } var body: some View { Text(value) } } Except that this view's initialiser will be called in the body of its parent, so this isn't really much of a win at all. So the next idea is that we need to associate the cached data with the underlying view itself somehow. From what we are told about SwiftUI, that's what @State does. struct MyView: View { @State var value: String init(_ value: String) { self._value = State(initialValue: someComplexCalculation(value)) } var body: some View { Text(value) } } Except... apparently this is not recommended because SwiftUI won't honour the value set in the initialiser. That's kind of okay for my purposes - the contents won't change, and every view with the same identity (place in the hierarchy) will be provided the same input. The real problem emerges when we look at the documentation for @State. Its initialiser takes a value directly, so we're still going to perform this expensive calculation every time; we'll just discard the value immediately afterwards and take one which the framework memoised. Which brings me on to my final approach - @StateObject. Unlike @State, its initialiser takes an autoclosure, so we won't recompute the value every time. But it should still be stored in a way that is bound to the underlying view, thereby giving me a place to stash memoised values. struct MyView: View { final class Cache { var transformed: String init(input: String) { self.transformed = someComplexCalculation(value) } } @StateObject var cache: Cache init(_ value: String) { self._cache = StateObject(wrappedValue: Cache(input: value)) } var body: some View { Text(cache.transformed) } } I haven't been able to find much in the way of others online using @StateObject for this purpose, so I'd like to ask - is there some other solution I'm overlooking? Is this considered a misuse of @StateObject for some reason? The documentation for the StateObject initialiser says: Initialize using external data If the initial state of a state object depends on external data, you can call this initializer directly. However, use caution when doing this, because SwiftUI only initializes the object once during the lifetime of the view — even if you call the state object initializer more than once — which might result in unexpected behavior. Which seems fine. This seems like exactly what I want.
2
1
1.8k
May ’23
Instruments: what is static AppName.$main() [inlined]
I have a performance issue with a Mac SwiftUI app. Using instruments I see hangs reported. When I zero in on a hang I see that the time profiler reports most of the hang -- in one example 658 out of 687 ms -- being in 'static AppName.$main() [inlined]'. I think that is saying my app is busy, but busy doing what? The "hangs" are related to SwiftUI table processing. User experience is something like this: select an item, see the view changes based upon selection show up a second or two later. The duration of the hang increases with the number of items in the table. I'm testing with 100 ~ 1200 table entries.
10
0
2.8k
May ’23
How can I integrate my own text changes into UITextView's undo manager?
I have an app that uses UITextView for some text editing. I have some custom operations I can do on the text that I want to be able to undo, and I'm representing those operations in a way that plugs into NSUndoManager nicely. For example, if I have a button that appends an emoji to the text, it looks something like this: func addEmoji() { let inserting = NSAttributedString(string: "😀") self.textStorage.append(inserting) let len = inserting.length let range = NSRange(location: self.textStorage.length - len, length: len) self.undoManager?.registerUndo(withTarget: self, handler: { view in view.textStorage.deleteCharacters(in: range) } } My goal is something like this: Type some text Press the emoji button to add the emoji Trigger undo (via gesture or keyboard shortcut) and the emoji is removed Trigger undo again and the typing from step 1 is reversed If I just type and then trigger undo, the typing is reversed as you'd expect. And if I just add the emoji and trigger undo, the emoji is removed. But if I do the sequence above, step 3 works but step 4 doesn't. The emoji is removed but the typing isn't reversed. Notably, if step 3 only changes attributes of the text, like applying a strikethrough to a selection, then the full undo chain works. I can type, apply strikethrough, undo strikethrough, and undo typing. It's almost as if changing the text invalidates the undo manager's previous operations? How do I insert my own changes into UITextView's NSUndoManager without invalidating its chain of other operations?
4
0
1.4k
May ’23
Gesture: System gesture gate timed out.
Hi everyone I am fighting with a weird problem in my app I use swiftui and ai do not use tabs, but a hierarchy of view created by me that switch one to the other with a slide animation when I tap one of the elements i don't use gesture, but only ontap. The same app launched on two different iPhone has two different behaviours on the iPhone 11 no problem, the animation is fluid and responsive, on the iPhone 10 I got some delay, and in the console I can read Gesture: System gesture gate timed out I have searched but I have not found anything useful and more than this it is extremely difficult to find some info about this warning/error How can I solve this? on the iPhone 10 it seems like the animation got stuck for 1 seconds prior to be executed in the correct way
16
17
10k
May ’23
Intermittent crashes when calling performSegue(withIdentifier:,sender:)
Our app crashes intermittently when calling performSegue(withIdentifier:,sender:). The segue does exist, as most of the time it works fine. The destination view controller only has its view as a connection. Crash report excerpt below. Uploading the crash report isn't working for some reason, so I'll try to do so as a reply. The stack trace shows searchForClientURL... as the last part of our code that gets executed. I'm curious if I should look at things in our code that happen while the segue is being performed such as prepare(for:, sender:), the init of the destination controller, etc. or not because they're not showing up in the stack trace. Thanks for any help! 0 CoreFoundation 0x19e310e38 __exceptionPreprocess + 164 (NSException.m:202) 1 libobjc.A.dylib 0x19749f8d8 objc_exception_throw + 60 (objc-exception.mm:356) 2 UIKitCore 0x1a1306630 __66-[UIStoryboardPushSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 880 (UIStoryboardPushSegueTemplate.m:58) 3 UIKitCore 0x1a08f3c84 -[UIStoryboardSegueTemplate _performWithDestinationViewController:sender:] + 172 (UIStoryboardSegueTemplate.m:134) 4 UIKitCore 0x1a08f3ba4 -[UIStoryboardSegueTemplate _perform:] + 68 (UIStoryboardSegueTemplate.m:121) 5 UIKitCore 0x1a0cc74c0 -[UIViewController performSegueWithIdentifier:sender:] + 300 (UIViewController.m:5017) 6 AWApp 0x10061ce38 closure #1 in ClientSelectorViewController.searchForClientURL(nameOrGUID:shouldTestSession:) + 3616 (ClientSelectorViewController.swift:231)
2
0
987
May ’23
SwiftUI Stepper Crashes (EXC_BAD_ACCESS) on My Mac (Designed for iPhone) but works fine on iOS device/simulator?
I've been working on an iOS project for the iPhone and would like to support running it on macOS computers with Apple Silicon. In the Targets / Supported Destinations we added "Mac (Designed for iPhone)" but experienced Thread 1: EXC_BAD_ACCESS crashes immediately when we tried to run it. We've isolated it down to Stepper UI elements in our view. Starting a new project and just trying to present a single Stepper in the ContentView, we get the same crash. Here is code that presents the issue: // ContentView.swift import SwiftUI struct ContentView: View { @State var someValue = 5 var body: some View { VStack { Stepper("Stepper", value: $someValue, in: 0...10) } } } When run from Xcode on an iOS device or the simulator, it runs fine. Trying to run it on the Mac, it crashes here: // Stepper_01App.swift import SwiftUI @main // <-- Thread 1: EXC_BAD_ACCESS (code=2, address=0x16a643f70) struct Stepper_01App: App { var body: some Scene { WindowGroup { ContentView() } } } Xcode 14.3 (14E222b), MacOS Ventura 13.3.1 (a), Mac mini M2. Target: Mac (Designed for iPhone) We have verified that the same code crashes on all the Apple Silicon Macs we have access to. Searching the Internet and Apple Developer forums I dont find other reports, so I kind of feel there must be some level of either user error or system/project misconfiguration going on? If any iOS app that used Steppers was just crashing when trying to run on a Mac, it seems like this would be a big deal. If anyone has input or can point out what we need to do differently, it would be appreciated!
12
1
1.9k
May ’23
SwiftUI - observing AVPlayer playback state
I am learning SwiftUI, I want to observe an AVPlayer status so I know when the videos is paused or not. My current approach is more less like this: I have VideosView that holds a list of a videos (in ZStack cards). VideoViews has a VideosViewModel. in VideosView i am calling in onAppear VideosViewModel.getItems... struct ItemModel: Identifiable, Codable, Hashable, Equatable { var id: String var author: String // video owner var url: URL? // url to the video var player: AVPlayer? // AVPlayer created based on self.url... mutating func setPlayer(_ avPlayer: AVPlayer) { self.player = avPlayer } } // vm class FeedViewModel: ObservableObject { @Published private(set) var items: [ItemModel] = [] func getItems() async { do { // fetch data from the API let data = try await dataService.fetchFeeds() // download and attach videos downloadFeedVideos(data) } catch { // .... } } private func downloadFeedVideos(_ feeds: [ItemModel]) { for index in feeds.indices { var item = feeds[index] if let videoURL = item.url { self.downloadQueue.queueDownloadIfFileNotExists( videoURL, DownloadOperation( session: URLSession.shared, downloadTaskURL: videoURL, completionHandler: { [weak self] (localURL, response, error) in guard let tempUrl = localURL else { return } let saveResult = self?.fileManagerService.saveInTemp(tempUrl, fileName: videoURL.lastPathComponent) switch saveResult { case .success(let savedURL): DispatchQueue.main.async { // maybe this is a wrong place to have it? item.setPlayer(AVPlayer(url: savedURL)) self?.items.append(item) if self?.items.count ?? 0 > 1 { // once first video is downloaded, use all device cores to fetch next videos // all newest iOS devices has 6 cores self?.downloadQueue.setMaxConcurrentOperationCount(.max) } } case .none: break case .failure(_): EventTracking().track("Video download fail", [ "id": item.id, "ulr": videoURL.absoluteString.decodeURL() ]) } }), { fileCacheURL in // file already downloaded DispatchQueue.main.async { item.setPlayer(AVPlayer(url: fileCacheURL)) self.items.append(item) } }) } } } } I found this article with some pseudo-code of how to track video playback state but I'm not sure how to implement it in my code.... https://developer.apple.com/documentation/avfoundation/media_playback/observing_playback_state
1
0
1.6k
May ’23
How to hide NSToolbar background when NSHostingController's ScrollView is at the top
In Monterey, when a user was at the top of a ScrollView implemented inside of a NSHostingController's view (that was itself embedded in a window with a NSToolbar), the window's toolbar background would be hidden until the user scrolled from the top. In Ventura, this behavior is different, with the toolbar's background visible all of the time unless a traditional NSScrollView is used (which means no SwiftUI). Is there the ability to change this behavior within SwiftUI some how now?
1
1
746
May ’23
SwiftUI view printout on paper
Hello and thanks for reading my post. I have a SwiftUI view, the users should be able to click a button and take printout of that view. Clicking on the button should open the standard print sheet (select printer, pages, layout, etc.). How can I implement such a functionality? I have been trying hard without any success. Please help. It is an iPad app, using Xcode 14.3
5
1
2k
Jun ’23