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

I can't stand IOS 18 photos app
I made an account on this site for the sole reason to post this. I can not stand the IOS 18 photo app, to put it bluntly its sucks, it's made the app unusable. I was nice, I'd thought I'd give it a month or two but no, it still sucks. I wish I could uninstall IOS 18 solely cause of it. I hate the UI, its utterly unintuitive.
Topic: UI Frameworks SubTopic: AppKit Tags:
1
4
911
Nov ’24
Problem with audio files in Swift
Hi guys, I've been this app for quite a while and I wanted to add audio to it but I've encountered a strange bug. Whenever I try to play the audio from the testing device, it prints out that the audio file cannot be found. I've checked multiple times the names and the code and I get no errors there whatsoever. I have no idea what might be causing this. Here's a part of the code: `import SwiftUI import AVFoundation struct Card: Identifiable { let id = UUID() let heading: String let description: String let imageName: String let detailDescription: String let sonification: String } struct ExplorepageUI: View { @State private var selectedCard: Card? @State private var showMore = false @State private var currentIndex = 0 @State private var currentCards: [Card] = [] let galaxies = [ Card(heading: "The Mice Galaxies", description: "They’re located about 300 million light-years away in the constellation Coma Berenices.", imageName: "TheMiceGalaxiesHubble", detailDescription:""" Their name refers to the long tails produced by tidal action, the relative difference between gravitational pulls on the near and far parts of each galaxy, known here as a galactic tide. It is a possibility that both galaxies, which are members of the Coma Cluster, have experienced collision, and will continue colliding until they coalesce. The colors of the galaxies are peculiar. In NGC 4676A a core with some dark markings is surrounded by a bluish white remnant of spiral arms. The tail is unusual, starting out blue and terminating in a more yellowish color, despite the fact that the beginning of each arm in virtually every spiral galaxy starts yellow and terminates in a bluish color. NGC 4676B has a yellowish core and two arcs; arm remnants underneath are bluish as well. The galaxies were photographed in 2002 by the Hubble Space Telescope. In the background of the Mice Galaxies, there are over 3000 galaxies, at distances up to 13 billion light-years. """, sonification: "SonificationoftheMiceGalaxies"), `class MusicPlayer: ObservableObject { private var audioPlayer: AVPlayer? func playSound(named sonificationFileName: String){ if let url = Bundle.main.url(forResource: sonificationFileName, withExtension: "mp3"){ print("✅ Found audio file at: \(url)") audioPlayer = try? AVPlayer(url: url) audioPlayer?.play() print("🎵 Audio should now be playing!") } else { print("❌ Audio file not found: \(sonificationFileName).mp3") } } func pause(){ audioPlayer?.pause() } }
1
0
562
Nov ’24
How to fix MainActor warning for QLPreviewControllerDelegate
I'm currently migrating a midsize (20k LOC) project to Swift structured concurrency. With complete checking turned on, it currently builds with only two warnings, both of which are related to the QLPreviewControllerDelegate protocol: "Main actor-isolated instance method 'previewControllerDidDismiss' cannot be used to satisfy nonisolated protocol requirement; this is an error in the Swift 6 language mode" as well as the same warning but substituting 'previewController(_:transitionViewFor:)' for the method name. I'm confused as to how to make these nonisolated, as they use UIKit classes/subclasses as arguments and/or return types.
2
0
666
Nov ’24
Bring iOS app to foreground from Apple Watch app
Exploring Live Activity feature for Apple Watch right now and found that it has this default view with "Open on iPhone" button when you tap Live Activity. That button perfectly brings iOS app to foreground as if you tapped iOS's Live Activity. Is there a way to mimic that behavior from inside Watch app code? From inside WKApplicationDelegate, for example Tried openSystemURL but it seems lile it's only available for tel or sms links
1
0
577
Nov ’24
SwiftUI TextSelection crash on macOS
I have a very simple SwiftUI app, works fine on iOS, crashes on macOS: struct ContentView: View { @State var testStr: String = "" @State var selection: TextSelection? = nil var body: some View { VStack { TextField("Test", text: $testStr, selection: $selection) .onChange(of: selection) {print("selection changed")} } .padding() } } • Start app, write something in the TextField and move the cursor around. iOS: "selection changed" Mac: nothing (Bug ?) • double click on some word both Mac and iOS: "selection changed" • write some more in the TextField iOS: selection changed Mac: crash Any idea what I am doing wrong? Gerriet.
Topic: UI Frameworks SubTopic: SwiftUI
2
0
273
Nov ’24
Binding of an array element property inside a struct not working anymore
Hi, I programmed an app to draw cards from a deck. After a card is drawn it is hidden from the deck. The drawn state is a property of a card struct in an array inside a deck struct. This worked well in the past since iOS 14. Since Xcode 16 this does not work as before anymore. This is the Card struct with a Boolfor the drawn state: struct Card: Codable, Identifiable, Equatable, Hashable { var isDrawn: Bool … } The cards are stored in an array that is inside a CardDeck struct among other properties: struct CardDeck: Codable { var cards: [Card] = [] var cardSpacing: CGFloat … mutating func hideCard(card: Card) { if let cardIndex = self.cards.firstIndex(of: card) { self.cards[cardIndex].isDrawn = true } } } The deck is a published property of an observable DeckStore class for permanent storage: class CardDeckStore: ObservableObject { @Published var deck: CardDeck = CardDeck() … } The DeckStore class is @StateObject in the App struct: @main struct CardApp: App { @StateObject var store = OpaliaCardDeckStore() var body: some Scene { WindowGroup { ContentView(deck: $store.deck) } } } Here is the simplified DrawCardsView where I present and draw the cards: struct DrawCardsView: View { @Binding var deck: CardDeck var body: some View { // Was a NavigationView before NavigationStack() { HStack(spacing: deck.cardSpacing) { ForEach($deck.cards) { $card in if card.isDrawn { CardBackView(card: card) .hidden() } else { NavigationLink(destination: DrawnCardView(card: card, deck: $deck)) { CardBackView(card: card) } } } } } } } To hide a drawn card, hideCard() is called in the DrawnCardView: struct DrawnCardView: View { var card: Card @Binding var deck: CardDeck @State var drawnCard: DrawnCard = .init() var body: some View { DrawnCardSimpleView(drawnCard: self.drawnCard) .onDisappear(perform: { deck.hideCard(card: self.card) }) } } I am not a pro in programming and there are better solutions to program this, but this worked until I upgraded to Xcode 16. Now it seems the isDrawn state of a card does not update the DrawCardsView right away anymore. A drawn card is not hidden and still present when returning to DrawCardsView from DrawnCardView. After tapping the same card again or another update of the UI, the card will then be hidden. I do not know the reason. It seems the binding of the isDrawn state inside an element of the card array in the observable object is not working anymore. Other properties of the observable object like cardSpacing do work as expected. I can empty the cards array and fill it with new cards without problems in the DrawCardsView. I eliminated the ForEach loop by addressing the array elements directly, but to no avail. I tried different solutions I found on the internet, but nothing worked. I was under the impression that every change in an observable object would update the UI. Any ideas for a explanation/solution? Thanks, Christian
Topic: UI Frameworks SubTopic: SwiftUI
2
0
224
Nov ’24
Limiting UITableView Width Across Different Table View Configurations
I have an iOS App which looks great on iPhone, portrait only, which makes a lot of use of UITableViews. On iPad those tables look stretched out in Landscape. On MacOS with Apple Silicon the app can be resized to any size and the table views look very stretched. There are views in the App which users want to resize so limiting app size not an option. I've been modifying the app's table views to limit their width and centre them using constraints. This isn't easy, it's a lot of work as UITableViewController doesn't allow for constraining the table width. Or does it? So I've changed them to UIViewControllers with UITableView imbedded in the root UIView with constraints. Looks really nice. Now I've just run into the limitation that static tables, which I have a number of, aren't allowed to be embedded. So how can I limit the width of them? I really don't want to add a lot of dynamic code. Please tell me there's an simpler, more elegant method to what really makes a much more aesthetically pleasing UI on iOS App running on iPad and MacOS? TIA!
3
0
473
Nov ’24
Drag and drop from the Files app onto a List doesn't work anymore in iOS 18
Hi I think I found an issue with SwiftUI List on iOS 18.0 and 18.1 Using the ContentView from the code block below: if you try to drag and drop the globe image onto the blue rows, things work fine on both iOS 17 and 18 with either List or VStack. However if you first drag and drop the image onto the Files app and then drag the newly created PNG file back into our app, it won't work on iOS 18 with the blue row inside the List. Also there's no visual feedback when hovering that blue row (unlike the one inside the VStack). I've tried various view modifiers but no luck so far. Any help is appreciated. Thank you. FB15618535 struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .resizable() .scaledToFit() .frame(height: 100) .draggable(Image(systemName: "globe")) List { Color.gray .frame(height: 100) Color.blue .frame(height: 100) .dropDestination(for: Image.self) { _, _ in print("List dropped") return true } } VStack { Color.gray Color.blue .dropDestination(for: Image.self) { _, _ in print("VStack dropped") return true } } } .padding() } }
Topic: UI Frameworks SubTopic: SwiftUI Tags:
1
1
440
Nov ’24
Prevent macOS window.level floating from showing on all screens in a multi monitor setup?
I am using the window.level set to .floating as described here: https://developer.apple.com/documentation/appkit/nswindow/level The setting itself works okay. However, in a multi monitor setup, the floating window is appearing on both the screens. How can I prevent this? My users report that before macOS Sonoma, this used to not happen. Has this behaviour changed? How can I revert back to the old behaviour?
1
0
557
Nov ’24
SwiftUI/WebKit Allowing popups and links
We are using an imbedded WKWebView in a SwiftUI view. There are links within the pages being viewed - they are company pages - and some link to other pages as well as open named (or unnamed) browser tabs. In our implementation, when there is a named (or unnamed) link to another browser tab, the view does not do anything. Any ideas on how to allow tabs to open in some manner and allow the users to access the links?
2
0
361
Nov ’24
SwiftData: Default value for added property
Let's say I have a model like this: @Model final class DataModel { var firstProperty: String = "" } Later on I create a new property as such: @Model final class DataModel { enum DataEnum { case dataCase } var firstProperty: String = "" var secondProperty: DataEnum? = .dataCase } My expectation is for the data that is already stored, the secondProperty would be added with a default value of .dataCase. However, it's being set to nil instead. I could have sworn it would set to the default value given to it. Has that changed, or has it always been this way? Does this require a migration plan?
0
1
390
Nov ’24
NSToolbarItemGroup dynamically update subitems in toolbar
Developing on Monterey 12.7.5 I'm having trouble with updating subitems on NSToolbarItemGroup when selecting the item directly from the NSToolbar items array. I select the group item off the items array on the toolbar, and then call setSubitems: on the item, with a new array of NSToolbarItems. The group item disappears from the toolbar. It seems to leave a blank invisible item in the toolbar taking up space. I can't manually reinsert the item into the toolbar until I drag out the blank item, then drag back in the real item. Once dragged back in from the palette it displays correctly. The workaround I've come up with is to remove the item with NSToolbar removeItemAtIndex: and reinsert it with NSToollbar insertItemWithItemIdentifier:atIndex:. This works to update the subitems. Every other toolbar item property that I've tried has been able to update the item directly in the toolbar. It's only the group item's subitems that don't want to update correctly. Is there a correct way to do this that I'm missing? Calling [toolbar validateVisibleItems] didn't seem to help.
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
389
Nov ’24
What's the best way to support Genmoji with SwiftUI?
I want to support Genmoji input in my SwiftUI TextField or TextEditor, but looking around, it seems there's no SwiftUI only way to do it? If none, it's kind of disappointing that they're saying SwiftUI is the path forward, but not updating it with support for new technologies. Going back, does this mean we can only support Genmoji through UITextField and UIViewRepresentable? or there more direct options? Btw, I'm also using SwiftData for storage.
0
1
612
Nov ’24
SwiftUI DatePicker size not configurable
Hey guys, I'm totally new to Swift programming and I'm setting up a view for registering users. I use a VStack to organize the TextFields as well as a DatePicker, but the last one seems to be very rebellious. Here's my code: VStack { TextField("E-Mailadresse", text: $mail) .frame(height: 30) .textFieldStyle(.roundedBorder) .multilineTextAlignment(.center) .focused($hasFocus, equals: .mail) .onKeyPress(.tab, action: {hasFocus = .password; return .handled}) SecureField("Passwort", text: $password) .frame(height: 30) .textFieldStyle(.roundedBorder) .multilineTextAlignment(.center) .focused($hasFocus, equals: .password) .onKeyPress(.tab, action: {hasFocus = .name; return .handled}) TextField("Name", text: $name) .frame(height: 30) .textFieldStyle(.roundedBorder) .multilineTextAlignment(.center) .focused($hasFocus, equals: .name) .onKeyPress(.tab, action: {hasFocus = .prename; return .handled}) TextField("Vorname", text: $prename) .frame(height: 30) .textFieldStyle(.roundedBorder) .multilineTextAlignment(.center) .focused($hasFocus, equals: .prename) .onKeyPress(.tab, action: {hasFocus = .birthday; return .handled}) DatePicker("Geb.:", selection: $birthday, displayedComponents: [.date]) .datePickerStyle(.wheel) .clipped() //.focused($hasFocus, equals: .birthday) Button("Registrieren") {self.register()} .padding(.top, 20) .keyboardShortcut(.defaultAction) } .frame(width: 375) } And this is how it looks like: As you can see, neither is the DatePicker centered correctly (it's more left located) nor is it clipped (reduced). I also tried adding a .frame() to itself, then I was ably to reduce it to the preferred height, but I can' reduce its width and as a result of this, I can also not write a full label like "Date of Birth" or something, because the wheel of the DatePicker always overlays it... Is that a kind of misbehavior or am I missing something? Thank you very much in anticipation for your feedback! Kind regards Kevin
1
0
547
Nov ’24
allowedWritingToolsResultOptions has no effect in iOS 18.1 Writing Tools
The UITextView.allowedWritingToolsResultOptions has no effect to how "Writing Tools" feature works. When it is set to empty, it still offer all options in the Writing Tools popup dialog. The result is that it is not possible to limit output results to eg. only plain text, or disable tables in output. let textView = UITextView() textView.isEditable = true textView.writingToolsBehavior = .complete textView.allowedWritingToolsResultOptions = [] resulting Writing Tools has all options available. I Tested with TextKit1 and TextKit 2 setup. tested on iPadOS 18.1 beta (22B5069a) Report: FB15429824
2
0
828
Nov ’24
UITableViewDropItem missing in Xcode 16?
Following instructions from ChatGPT, I'm trying to rearrange the order of rows in a UITableView. - (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator { NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath ?: [NSIndexPath indexPathForRow:self.items.count inSection:0]; [tableView performBatchUpdates:^{ for (UITableViewDropItem *dropItem in coordinator.items) { NSString *movedItem = dropItem.dragItem.localObject; if (movedItem) { NSIndexPath *sourceIndexPath = dropItem.sourceIndexPath; if (sourceIndexPath) { [self.items removeObjectAtIndex:sourceIndexPath.row]; [self.items insertObject:movedItem atIndex:destinationIndexPath.row]; [tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; } } } } completion:nil]; } Xcode is complaining that UITableViewDropItem does not exist. The class is in all the documentation, it is just not showing up when needed! Suggestions?
Topic: UI Frameworks SubTopic: UIKit
1
0
316
Nov ’24
XCUITest snapshot dictionary represenation giving wrong coordinates
Problem I am developing a WebDriver agent for automation and using dictionaryRepresentation to retrieve the coordinates of the iOS app hierarchy. However, I am encountering an issue with the accuracy of the x and y coordinates. Approach Tried I tested the setup on: iPhone 12 Pro Max (iOS 16.2): Accuracy issues with the coordinates were observed. iPhone SE (3rd Generation) (iOS 16.2): Coordinates were accurate for tap actions, with no issues identified. Observation It appears that devices with fingerprint biometric authentication provide accurate coordinates. Can anyone help here to understand is there anything wrong in the code. Are do we have to adjust frame of the element for different devices? Sample Code - (NSDictionary *)json_tree { NSDictionary<XCUIElementAttributeName, id> *dictionaryRepresentation = [[self snapshotWithError:nil] dictionaryRepresentation]; return [self.class dictionaryForElementAttributes:dictionaryRepresentation recursive:YES]; } // This method converts the dictionary to CGRect, handling any broken frame values (e.g., Infinity) + (CGRect)handleBrokenFrameFromDict:(id)frameDict { if ([frameDict isKindOfClass:[NSDictionary class]]) { CGFloat originX = [frameDict[@"X"] floatValue]; CGFloat originY = [frameDict[@"Y"] floatValue]; CGFloat sizeWidth = [frameDict[@"Width"] floatValue]; CGFloat sizeHeight = [frameDict[@"Height"] floatValue]; CGRect frame = CGRectMake(originX, originY, sizeWidth, sizeHeight); // Replace Infinity values with CGRectZero return (isinf(frame.size.width) || isinf(frame.size.height) || isinf(frame.origin.x) || isinf(frame.origin.y)) ? CGRectZero // or another predefined constant like BROKEN_RECT : CGRectIntegral(frame); } return CGRectZero; // If frameDict is not a valid dictionary, return CGRectZero } // This method converts CGRect into a dictionary representation for "rect" + (NSDictionary *)rectDictionaryFromCGRect:(CGRect)rect { return @{ @"x": @(rect.origin.x), @"y": @(rect.origin.y), @"width": @(rect.size.width), @"height": @(rect.size.height) }; } + (NSString *)label:(NSDictionary<XCUIElementAttributeName, id> *)dict { XCUIElementType elementType = [dict[XCUIElementAttributeNameElementType] intValue]; NSString *label = dict[XCUIElementAttributeNameLabel]; if (elementType == XCUIElementTypeTextField || elementType == XCUIElementTypeSecureTextField) { return label; } return FBTransferEmptyStringToNil(label); } + (NSString *)name:(NSDictionary<XCUIElementAttributeName, id> *)dict { NSString *identifier = dict[XCUIElementAttributeNameIdentifier]; if (nil != identifier && identifier.length != 0) { return identifier; } NSString *label = dict[XCUIElementAttributeNameLabel]; return FBTransferEmptyStringToNil(label); } + (NSString *)value:(NSDictionary<XCUIElementAttributeName, id> *)dict { id value = dict[XCUIElementAttributeNameValue]; XCUIElementType elementType = [dict[XCUIElementAttributeNameElementType] intValue]; if (elementType == XCUIElementTypeStaticText) { NSString *label = [self label:dict]; value = FBFirstNonEmptyValue(value, label); } else if (elementType == XCUIElementTypeButton) { NSNumber *isSelected = [dict[XCUIElementAttributeNameSelected] boolValue] ? @YES : nil; value = FBFirstNonEmptyValue(value, isSelected); } else if (elementType == XCUIElementTypeSwitch) { value = @([value boolValue]); } else if (elementType == XCUIElementTypeTextView || elementType == XCUIElementTypeTextField || elementType == XCUIElementTypeSecureTextField) { NSString *placeholderValue = dict[XCUIElementAttributeNamePlaceholderValue]; value = FBFirstNonEmptyValue(value, placeholderValue); } value = FBTransferEmptyStringToNil(value); if (value) { value = [NSString stringWithFormat:@"%@", value]; } return value; } + (NSDictionary *)dictionaryForElementAttributes:(NSDictionary<XCUIElementAttributeName, id> *)dict recursive:(BOOL)recursive { NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; info[@"type"] = [FBElementTypeTransformer shortStringWithElementType:[dict[XCUIElementAttributeNameElementType] intValue]]; info[@"rawIdentifier"] = FBValueOrNull([dict[XCUIElementAttributeNameIdentifier] isEqual:@""] ? nil : dict[XCUIElementAttributeNameIdentifier]); info[@"name"] = FBValueOrNull([self name:dict]); info[@"value"] = FBValueOrNull([self value:dict]); info[@"label"] = FBValueOrNull([self label:dict]); // Handle the frame value CGRect frame = [self handleBrokenFrameFromDict:dict[XCUIElementAttributeNameFrame]]; info[@"frame"] = NSStringFromCGRect(frame); // Add the rect value info[@"rect"] = [self rectDictionaryFromCGRect:frame]; info[@"isEnabled"] = [@([dict[XCUIElementAttributeNameEnabled] boolValue]) stringValue]; // visible // accessible info[@"isFocused"] = [@([dict[XCUIElementAttributeNameHasFocus] boolValue]) stringValue]; if (!recursive) { return info.copy; } NSArray<NSDictionary<XCUIElementAttributeName, id> *> *childElements = [dict[XCUIElementAttributeNameChildren] isKindOfClass:[NSArray class]] ? dict[XCUIElementAttributeNameChildren] : @[]; if ([childElements count]) { info[@"children"] = [[NSMutableArray alloc] init]; for (NSDictionary<XCUIElementAttributeName, id> * childSnapshot in childElements) { [info[@"children"] addObject:[self dictionaryForElementAttributes:childSnapshot recursive:YES]]; } } return info; }
Topic: UI Frameworks SubTopic: General
1
0
314
Nov ’24