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

UIScrollView in UIViewControllerRepresentable - UI freezes when content touches bottom SafeArea
The SwiftUI ScrollView lacks some features I need and so I created a custom MyScrollView based on UIScrollView wrapped within a UIViewControllerRepresentable. While this works fine in general I know came across a very strange problem: When MyScrollView is used in a sheet and its content touches bottom SafeArea, the UI freezes as soon as the should be displayed. The code below shows the problem as well in preview as on the simulator and on devices. Please note that the code is tuned do the display size of an iPhone 16 Pro. When running on different devices one might need to adjust height of the Color.yellow. In the demo code the UI freezes if the Color.yellow has a height between 738 to 771 pixels. Every other height is fine. Is there something wrong with my implementation of MyScrollView? When using ScrollView instead, everything works fine. Code: struct ContentView: View { @State private var showSheet: Bool = false var body: some View { ZStack { Button("Show Sheet") { showSheet = true } } .sheet(isPresented: $showSheet) { VStack { Text("Some Header Content") MyScrollView { VStack { Color.yellow //.frame(height: 737) // works .frame(height: 738) // does NOT works // ... //.frame(height: 771) // does NOT works //.frame(height: 772) // works } } .ignoresSafeArea() } } } } struct MyScrollView<Content: View>: UIViewControllerRepresentable { let content: Content init(@ViewBuilder content: () -> Content) { self.content = content() } func makeUIViewController(context: Context) -> UIViewController { let scrollViewVC = UIViewController() scrollViewVC.view.backgroundColor = .clear let scrollView = UIScrollView() scrollView.backgroundColor = .clear let contentVC = UIHostingController(rootView: self.content) contentVC.view.backgroundColor = .clear context.coordinator.contentVC = contentVC context.coordinator.scrollView = scrollView scrollView.translatesAutoresizingMaskIntoConstraints = false scrollViewVC.view.addSubview(scrollView) NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: scrollViewVC.view.topAnchor), scrollView.bottomAnchor.constraint(equalTo: scrollViewVC.view.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: scrollViewVC.view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: scrollViewVC.view.trailingAnchor) ]) contentVC.willMove(toParent: scrollViewVC) scrollViewVC.addChild(contentVC) contentVC.view.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(contentVC.view) NSLayoutConstraint.activate([ contentVC.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), contentVC.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor), contentVC.view.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), contentVC.view.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), contentVC.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor) ]) contentVC.didMove(toParent: scrollViewVC) return scrollViewVC } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { context.coordinator.contentVC?.rootView = content } func makeCoordinator() -> Coordinator { return Coordinator() } class Coordinator { var contentVC: UIHostingController<Content>? var scrollView: UIScrollView? init() { //... } } } #Preview { ContentView() }
Topic: UI Frameworks SubTopic: SwiftUI
2
0
115
Apr ’25
Open new document in SwiftUI on iOS
I have a SwiftUI document based app. The iOS version has a Scene Delegate: class SceneDelegate: NSObject, UIWindowSceneDelegate { func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { for context in URLContexts { let url = context.url // url.scheme = my custom scheme let text = ... extracted from url ... // I want to open a new untitled document with text // but 'newDocument' has been explicitly marked unavailable for iOS } } }
Topic: UI Frameworks SubTopic: SwiftUI
1
0
67
May ’25
Picker with inline style on tvOS 18
Since tvOS 18, my Picker view with inline style is not showing the checkmark on the selected item. enum Flavor: String, Identifiable { case chocolate, vanilla, strawberry var id: Self { self } } struct ContentView: View { @State private var selectedFlavor: Flavor = .chocolate var body: some View { NavigationView { Form { Picker("Flavor", selection: $selectedFlavor) { Text("Chocolate").tag(Flavor.chocolate) Text("Vanilla").tag(Flavor.vanilla) Text("Strawberry").tag(Flavor.strawberry) }.pickerStyle(.inline) } } } } Am I missing something? When I run this on tvOS 17.x, it works fine.
2
0
103
Mar ’25
When presenting CPNavigationAlert the navigation bar will appear
In my CarPlay app, I am hiding the navigation bar by using the following: self.mapTemplate?.automaticallyHidesNavigationBar = true self.mapTemplate?.hidesButtonsWithNavigationBar = false I don't want the navigation bar to show unless a user interacts with the map by tapping it. Strangely, when I present a CPNavigationAlert the navigation bar will often appear and then disappear after the alert is dismissed. Is there a setting or reason that the navigation bar would be appearing when presenting this alert? I would like to keep the nav bar hidden during this time.
Topic: UI Frameworks SubTopic: UIKit Tags:
0
0
133
May ’25
Abnormal UI and Keyboard Behavior in iPhone App Running on iPadOS 18.x Built with Xcode 16
Case-ID: 12591306 Use Xcode 16.x to compile an iPhone demo app and run it on an iPad (iPadOS 18.x) device or simulator. Launch the iPhone app and activate Picture-in-Picture mode. Attempt to input text; the system keyboard does not appear. Compare the output of [[UIScreen mainScreen] bounds] before and after enabling Picture-in-Picture mode, notice the values change unexpectedly after enabling PiP. This issue can be consistently reproduced on iPadOS 18.x when running an app built with Xcode 16.0 to Xcode 16.3RC(16E137). Beginning April 24, 2025, apps uploaded to App Store Connect must be built with Xcode 16 or later using an SDK for iOS 18, iPadOS 18, tvOS 18, visionOS 2, or watchOS 11.Therefore, I urgently hope to receive a solution provided by Apple.
1
0
164
Mar ’25
Lists, Generics, Views, Navigation Link, SwiftData - ForEach can't pass a binding anymore.
I'm trying out putting most of my business logic in a Protocol that my @Model can conform to, but I'm running into a SwiftUI problem with a Binding that does not get magically offered up like it does when it the subview is not generic. I have a pretty basic List with a ForEach that now can't properly pass to a generic view based on a protocol. When I try to make a binding manually in the row it says that "item is immutable"... but that also doesn't help me with the NavigationLink? Which is seeing the Binding not the ? But before when the subview was concrete to Thing, it took in the and made its own Binding once it hit the view. I'm unclear on precisely where the change happens and what I can do to work around it. Before I go rearchitecting everything... is there a fix to get the NavigationLink to take on the object like before? What needs to be different? I've tried a number of crazy inits on the subview and they all seem to come back to saying either it can't figure out how to pass the type or I'm trying to use the value before it's been initialized. Have I characterized the problem correctly? Thanks! (let me know if I forgot a piece of code, but this should be the List, the Model/Protocol and the subview) import SwiftUI import SwiftData struct ThingsView: View {     @Environment(\.modelContext) var modelContext     @Query var items: [Thing]          var body: some View {         NavigationStack {             List {                 ForEach(items) { item in                     NavigationLink(value: item) {                         VStack(alignment: .leading) {                             Text(item.textInfo)                                 .font(.headline)                                                          Text(item.timestamp.formatted(date: .long, time: .shortened))                         }                     }                 }.onDelete(perform: deleteItems)             }             .navigationTitle("Fliiiing!") //PROBLEM HERE: Cannot convert value of type '(Binding<Thing>) -> EditThingableView<Thing>' to expected argument type '(Thing) -> EditThingableView<Thing>'             .navigationDestination(for: Thing.self, destination: EditThingableView<Thing>.init) #if os(macOS)             .navigationSplitViewColumnWidth(min: 180, ideal: 200) #endif             .toolbar { #if os(iOS)                 ToolbarItem(placement: .navigationBarTrailing) {                     EditButton()                                      } #endif                 ToolbarItem {                     Button(action: addItem) {                         Label("Add Item", systemImage: "plus")                     }                 }                 ToolbarItem {                     Button("Add Samples", action: addSamples)                 }             }         }     }          func addSamples() {         withAnimation {             ItemSDMC.addSamples(context: modelContext)         }     }          private func addItem() {         withAnimation {             let newItem = ItemSDMC("I did a thing!")             modelContext.insert(newItem)         }     }          func deleteItems(_ indexSet:IndexSet) {         withAnimation {             for index in indexSet {                 items[index].delete(from: modelContext)             }         }     } } #Preview {     ThingsView().modelContainer(for: ItemSDMC.self, inMemory: true) } import Foundation import SwiftData protocol Thingable:Identifiable {     var textInfo:String { get set }     var timestamp:Date { get set } } extension Thingable {     var thingDisplay:String {         "\(textInfo) with \(id) at \(timestamp.formatted(date: .long, time: .shortened))"     } } extension Thingable where Self:PersistentModel {     var thingDisplayWithID:String {         "\(textInfo) with modelID \(self.persistentModelID.id) in \(String(describing: self.persistentModelID.storeIdentifier)) at \(timestamp.formatted(date: .long, time: .shortened))"     } } struct ThingLite:Thingable, Codable, Sendable {     var textInfo: String     var timestamp: Date     var id: Int } @Model final class Thing:Thingable {     //using this default value requires writng some clean up logic looking for empty text info.     var textInfo:String = ""     //using this default value would require writing some data clean up functions looking for out of bound dates.     var timestamp:Date = Date.distantPast          init(textInfo: String, timestamp: Date) {         self.textInfo = textInfo         self.timestamp = timestamp     } } extension Thing {     var LiteThing:ThingLite {         ThingLite(textInfo: textInfo, timestamp: timestamp, id: persistentModelID.hashValue)     } } import SwiftUI struct EditThingableView<DisplayItemType:Thingable>: View {     @Binding var thingHolder: DisplayItemType          var body: some View {                  VStack {             Text(thingHolder.thingDisplay)             Form {                 TextField("text", text:$thingHolder.textInfo)                 DatePicker("Date", selection: $thingHolder.timestamp)             }                      } #if os(iOS)         .navigationTitle("Edit Item")         .navigationBarTitleDisplayMode(.inline) #endif     } } //NOTE: First sign of trouble //#Preview { //    @Previewable var myItem = Thing(textInfo: "Example Item for Preview", timestamp:Date()) //    EditThingableView<Thing>(thingHolder: myItem) //}
4
0
204
May ’25
Trigger save of a FileDocument in a DocumentGroup?
I have a DocumentGroup working with a FileDocument, and that's fine. However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created). There seems to be no way to do this on macOS? I basically want to have someone: create a new document enter some basic data hit "create" which saves the file then lets the user start editing it (1), (2), and (4) are done and fairly trivial. (3) seems impossible, though...? This really only needs to support macOS but any pointers would be appreciated.
0
0
283
Apr ’25
Save credentials prompt not shown when login and password aren't the last fields in a form
The save credentials prompt is not shown after clicking the submit button in the following setup. The prompt is shown if I move the email field before the login field. Is it really required to have login and password fields at the end of the registration form? Or is there some API that can trigger the prompt? struct FakeRegistrationView: View { @State private var login = "" @State private var password = "" @State private var repeatPassword = "" @State private var email = "" var navigateBack: () -> Void var body: some View { VStack(spacing: 16) { TextField("Login", text: $login) .textFieldStyle(.roundedBorder) .textContentType(.username) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) SecureField("Password", text: $password) .textFieldStyle(.roundedBorder) .textContentType(.newPassword) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) SecureField("Repeat password", text: $repeatPassword) .textFieldStyle(.roundedBorder) .textContentType(.newPassword) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) TextField("Email", text: $email) .textFieldStyle(.roundedBorder) .textContentType(.emailAddress) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) Button { Task { try? await Task.sleep(for: .seconds(2)) navigateBack() } } label: { Text("Submit") } .buttonStyle(.borderedProminent) } } }
1
0
239
Mar ’25
Save fails after Save As
I have an app with two file types with the following extensions: gop (an exported type), sgf (an imported type). The Save command fails after the following sequence of events: I open a gop file, say the file "A.gop". I save this file as an sgf file, say "A.sgf". This Save As works perfectly and the document name in the document’s title bar has changed to "A.sgf". I change something in the document and then try to Save this change. This should just resave the document to "A.sgf", but "A.sgf" remains untouched. Instead I get a system alert with the message The document “A.sgf” could not be saved. A file with the name “A.gop” already exists. To save the file, either provide a different name, or move aside or delete the existing file, and try again. In the Xcode console I get the following diagnostic: NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 2 [NSFileCoordinator itemAtURL:willMoveToURL:] could not get a sandbox extension. oldURL: file:///Users/francois/Desktop/A.sgf, newURL: file:///Users/francois/Desktop/A.gop The problem seems to relate to the sandbox. But I am at a loss to find a solution. (After closing the alert, I check that A.sgf did not register the change.) If I open an sgf file, say "B.sgf", save it as "B.gop", make a change in the document and then try to save this change (into "B.gop"), I hit the same problem, with "gop" and "sgf" interchanged. If, instead of saving "A.gop" as "A.sgf", I save it as "B.sgf", make a change in the document and then try to save this change into "B.sgf", I get the following system alert: The document “B.sgf” could not be saved. You don’t have permission. To view or change permissions, select the item in the Finder and choose File &gt; Get Info. And in the Xcode console I get the following diagnostic: NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 2 [NSFileCoordinator itemAtURL:willMoveToURL:] could not get a sandbox extension. oldURL: file:///Users/francois/Desktop/B.sgf, newURL: file:///Users/francois/Desktop/B.gop Again the sandbox ! (After closing the alert, I check that B.sgf did not register the change.) It’s clear my code is missing something, but what?
0
0
154
Apr ’25
How to customize item transitions inside a Picker View?
I have a simple Picker where the options available change by the view state. I would like to have the transition animated but the default animation is not good so I tried setting a .transition() and or an .animation() inside an item on the picker but it is ignored. The same happens if the transition is set on the picker itself since it's always present. Am I doing it right and is just not posible or is there something else to do? Code to reproduce the issue: struct ContentView: View { @State var list: [String] = [ "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", ] @State var selected: String? @State var toggle: Bool = false var body: some View { VStack { Picker("List", selection: $selected) { ForEach(list, id: \.self) { Text($0).tag($0) // .transition(.opacity) } } .pickerStyle(.segmented) // .transition(.opacity) HStack { Button(action: swapOptions) { Text("Swap") } } } .padding() } } extension ContentView { func swapOptions() { withAnimation { toggle.toggle() switch toggle { case true: list = [ "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", ] case false: list = [ "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", ] } } } } ``
Topic: UI Frameworks SubTopic: SwiftUI
0
0
98
May ’25
Remove "copy cursor" when dragging a view in SwiftUI
Hi, Im new to SwiftUI and Im trying to implement some drag and drop functionality for some tabs in my application. Im using .draggable(_) and .dropDestination for this and the issue I have is that as I drag the view, the mouse cursor changes to the copy cursor with the green plus sign and I don't like it but I can't figure out how to avoid it. Any help would be appreciated.
1
0
76
Apr ’25
[SwiftUI] Gesture Conflict: simultaneousGesture Causes Incorrect Gesture Recognition in iOS 18
Subject: SwiftUI Gesture Conflict in iOS 18: Simultaneous Recognition of Drag and Tap Gestures Description: In SwiftUI on iOS 18 and above, we've identified an issue with gesture handling that affects user experience. When implementing .simultaneousGesture(DragGesture()), the system incorrectly recognizes and processes both drag and tap gestures concurrently, resulting in unintended behavior. Technical Details: Environment: SwiftUI, iOS 18+ Issue: Simultaneous recognition of horizontal drag gestures and vertical scroll/tap gestures Current Behavior: Both vertical and horizontal scrolling occur simultaneously when using .simultaneousGesture(DragGesture()) Expected Behavior: Gestures should be properly disambiguated to prevent concurrent scrolling in multiple directions Impact: This behavior significantly impacts user experience, particularly in custom carousel implementations and other UI components that rely on precise gesture handling. The simultaneous recognition of both gestures creates a confusing and unpredictable interaction pattern. Steps to Reproduce: Create a SwiftUI view with horizontal scrolling (e.g., custom carousel) Implement .simultaneousGesture(DragGesture()) Add tap gesture recognition to child views Run on iOS 18 Attempt to scroll horizontally Observed Result: Both horizontal dragging and vertical scrolling/tapping are recognized and processed simultaneously, creating an inconsistent user experience. Expected Result: The system should properly disambiguate between horizontal drag gestures and vertical scroll/tap gestures, allowing only one type of gesture to be recognized at a time based on the user's intent. Please let me know if you need any additional information or reproduction steps.
0
0
125
Apr ’25
.onTapGesture does not work when SwiftUI component sits in a flipped NSVIew
Take a look at this simple code: import Cocoa import SwiftUI struct DemoView: View { var body: some View { Text("Click me!") .onTapGesture { print("Clicked") } } } class FlippedView: NSView { override var isFlipped: Bool { return true } } class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() let stackView = NSStackView() stackView.orientation = .vertical stackView.alignment = .leading stackView.spacing = 0 stackView.translatesAutoresizingMaskIntoConstraints = false let hostView = NSHostingView(rootView: DemoView()) stackView.addArrangedSubview(hostView) let scrollView = NSScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false let flippedView = FlippedView() flippedView.addSubview(stackView) scrollView.documentView = flippedView view.addSubview(scrollView) NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.topAnchor), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } } I need my scroll view to start at the very top, so i put it inside a flipped document view. But now .onTapGesture does not fire.
1
0
163
Apr ’25
The @Environment(\.dismiss) value in SwiftUI for macOS does not dismiss a sheet presented by an NSWindowController.
I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work. Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself. I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be. Is there a better strategy to leverage here? final class MyViewController: NSViewController { @IBAction func buttonClicked(_ sender: NSButton) { if let presenter = window?.contentViewController { presenter.presentAsSheet(NSHostingController(rootView: SettingsView())) } } } struct SettingsView: View { @Environment(\.dismiss) private var dismiss var body: some View { VStack { Button("Cancel", role: .cancel) { dismiss() // This call does not dismiss the sheet. } .keyboardShortcut(.cancelAction) } } } Thank you. macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
0
0
96
Apr ’25
SwiftUI + OSlog breaks previews in Swift 6
import SwiftUI import OsLog let logger = Logger(subsystem: "Test", category: "Test") struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() .task { logger.info("Hallo") } } } #Preview { ContentView() } 27 | .padding() 28 | .task { 29 | logger.info(__designTimeString("#6734_2", fallback: "Hallo")) | `- error: argument must be a string interpolation 30 | } 31 | } Should OsLog be compatible with __designTimeString?
1
0
143
Mar ’25
App Crashes on Paper Selection After Background Printer Connection
Description: When initiating the print flow via UIPrintInteractionController, and no printer is initially connected, iOS displays all possible paper sizes in the paper selection UI. However, if a printer connects in the background after this view is shown, the list of paper sizes does not automatically refresh to reflect only the options supported by the connected printer. If the user selects an incompatible paper size (one not supported by the printer that has just connected), the app crashes due to an invalid configuration. Steps to Reproduce: Launch the app and navigate to the print functionality. Tap the Print button to invoke UIPrintInteractionController. At this point, no printer is yet connected. iOS displays all available paper sizes. While the paper selection UI is visible, the AirPrint-compatible printer connects in the background. Without dismissing the controller, the user selects a paper size (e.g., one that is not supported by the printer). The app crashes. Expected Result: App should not crash Once the printer becomes available (connected in the background), the paper size options should refresh automatically. The list should be filtered to only include sizes that are compatible with the connected printer. This prevents the user from selecting an invalid option, avoiding crashes. Actual Result: App crashes The paper size list remains unfiltered. The user can still select unsupported paper sizes. Selecting an incompatible option causes the app to crash, due to a mismatch between UI selection and printer capability.
Topic: UI Frameworks SubTopic: UIKit
0
0
95
Apr ’25
Activate hoverEffect on separate entity attachment view
Hi, I'm working on RealityView and I have two entities in RCP. In order to set views for both entities, I have to create two separate attachments for each entity. What I want to achieve is that when I hover (by eye) on one entity's attachment, it would trigger the hover effect of the other entity's attachment. I try to use the hoverEffectGroup, but it would only activate the hover effect in a subview, instead a complete separate view. I refer to the following WWDC instruction for the hover effect. https://developer.apple.com/videos/play/wwdc2024/10152/
0
0
80
Apr ’25
Display a broader track of a user on ios app with Mapkit.
Hello I'm currently building a feature within an ios app using SwiftUI and Mapkit to record the gps cordinates of a user as they move and render the track on the map. the idea is not really to have a "track" but to have a visual representation of the area the user sees while they are moving around. I need this width/breadth to be relative to the map and not the screen, such that when I zoom in and out of the map, the size will adjust automatically.
0
0
74
May ’25
iOS18 iPad Custom UITabBar invalid
After my XCode was upgraded to 16.2, the custom bottom tabbar of iPadAPP could not be displayed properly (I set "traitOverrides.horizontalSizeClass = .compact", otherwise the tabbar would be displayed at the top and it was not the style I wanted) Below are my code and pictures of the running effects of iOS17 and iOS18 override func viewDidLoad() { super.viewDidLoad() setValue(CustomTabBar(), forKey: "tabBar") if #available(iOS 18.0, *) { self.mode = .tabBar self.traitOverrides.horizontalSizeClass = .compact } } } class CustomTabBar: UITabBar { var leftView = UIView() var rightView = UIView() override func sizeThatFits(_ size: CGSize) -> CGSize { var sizeThatFits = super.sizeThatFits(size) sizeThatFits.height = 60 // 自定义高度 return sizeThatFits } override func layoutSubviews() { super.layoutSubviews() self.backgroundColor = .red addSubview(leftView) addSubview(rightView) leftView.backgroundColor = .green leftView.frame = CGRect(x: 10, y: 4, width: 80, height: 40) rightView.backgroundColor = .green rightView.frame = CGRect(x: 600, y: 4, width: 80, height: 40) } } ![]("https://developer.apple.com/forums/content/attachment/66988297-26dc-4b40-af37-103f6a277563" "title=20250409151648.jpg;width=2394;height=1716")
Topic: UI Frameworks SubTopic: UIKit
4
0
285
Apr ’25
UIScrollView in UIViewControllerRepresentable - UI freezes when content touches bottom SafeArea
The SwiftUI ScrollView lacks some features I need and so I created a custom MyScrollView based on UIScrollView wrapped within a UIViewControllerRepresentable. While this works fine in general I know came across a very strange problem: When MyScrollView is used in a sheet and its content touches bottom SafeArea, the UI freezes as soon as the should be displayed. The code below shows the problem as well in preview as on the simulator and on devices. Please note that the code is tuned do the display size of an iPhone 16 Pro. When running on different devices one might need to adjust height of the Color.yellow. In the demo code the UI freezes if the Color.yellow has a height between 738 to 771 pixels. Every other height is fine. Is there something wrong with my implementation of MyScrollView? When using ScrollView instead, everything works fine. Code: struct ContentView: View { @State private var showSheet: Bool = false var body: some View { ZStack { Button("Show Sheet") { showSheet = true } } .sheet(isPresented: $showSheet) { VStack { Text("Some Header Content") MyScrollView { VStack { Color.yellow //.frame(height: 737) // works .frame(height: 738) // does NOT works // ... //.frame(height: 771) // does NOT works //.frame(height: 772) // works } } .ignoresSafeArea() } } } } struct MyScrollView<Content: View>: UIViewControllerRepresentable { let content: Content init(@ViewBuilder content: () -> Content) { self.content = content() } func makeUIViewController(context: Context) -> UIViewController { let scrollViewVC = UIViewController() scrollViewVC.view.backgroundColor = .clear let scrollView = UIScrollView() scrollView.backgroundColor = .clear let contentVC = UIHostingController(rootView: self.content) contentVC.view.backgroundColor = .clear context.coordinator.contentVC = contentVC context.coordinator.scrollView = scrollView scrollView.translatesAutoresizingMaskIntoConstraints = false scrollViewVC.view.addSubview(scrollView) NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: scrollViewVC.view.topAnchor), scrollView.bottomAnchor.constraint(equalTo: scrollViewVC.view.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: scrollViewVC.view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: scrollViewVC.view.trailingAnchor) ]) contentVC.willMove(toParent: scrollViewVC) scrollViewVC.addChild(contentVC) contentVC.view.translatesAutoresizingMaskIntoConstraints = false scrollView.addSubview(contentVC.view) NSLayoutConstraint.activate([ contentVC.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor), contentVC.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor), contentVC.view.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor), contentVC.view.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor), contentVC.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor) ]) contentVC.didMove(toParent: scrollViewVC) return scrollViewVC } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { context.coordinator.contentVC?.rootView = content } func makeCoordinator() -> Coordinator { return Coordinator() } class Coordinator { var contentVC: UIHostingController<Content>? var scrollView: UIScrollView? init() { //... } } } #Preview { ContentView() }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
2
Boosts
0
Views
115
Activity
Apr ’25
Open new document in SwiftUI on iOS
I have a SwiftUI document based app. The iOS version has a Scene Delegate: class SceneDelegate: NSObject, UIWindowSceneDelegate { func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { for context in URLContexts { let url = context.url // url.scheme = my custom scheme let text = ... extracted from url ... // I want to open a new untitled document with text // but 'newDocument' has been explicitly marked unavailable for iOS } } }
Topic: UI Frameworks SubTopic: SwiftUI
Replies
1
Boosts
0
Views
67
Activity
May ’25
Picker with inline style on tvOS 18
Since tvOS 18, my Picker view with inline style is not showing the checkmark on the selected item. enum Flavor: String, Identifiable { case chocolate, vanilla, strawberry var id: Self { self } } struct ContentView: View { @State private var selectedFlavor: Flavor = .chocolate var body: some View { NavigationView { Form { Picker("Flavor", selection: $selectedFlavor) { Text("Chocolate").tag(Flavor.chocolate) Text("Vanilla").tag(Flavor.vanilla) Text("Strawberry").tag(Flavor.strawberry) }.pickerStyle(.inline) } } } } Am I missing something? When I run this on tvOS 17.x, it works fine.
Replies
2
Boosts
0
Views
103
Activity
Mar ’25
When presenting CPNavigationAlert the navigation bar will appear
In my CarPlay app, I am hiding the navigation bar by using the following: self.mapTemplate?.automaticallyHidesNavigationBar = true self.mapTemplate?.hidesButtonsWithNavigationBar = false I don't want the navigation bar to show unless a user interacts with the map by tapping it. Strangely, when I present a CPNavigationAlert the navigation bar will often appear and then disappear after the alert is dismissed. Is there a setting or reason that the navigation bar would be appearing when presenting this alert? I would like to keep the nav bar hidden during this time.
Topic: UI Frameworks SubTopic: UIKit Tags:
Replies
0
Boosts
0
Views
133
Activity
May ’25
Abnormal UI and Keyboard Behavior in iPhone App Running on iPadOS 18.x Built with Xcode 16
Case-ID: 12591306 Use Xcode 16.x to compile an iPhone demo app and run it on an iPad (iPadOS 18.x) device or simulator. Launch the iPhone app and activate Picture-in-Picture mode. Attempt to input text; the system keyboard does not appear. Compare the output of [[UIScreen mainScreen] bounds] before and after enabling Picture-in-Picture mode, notice the values change unexpectedly after enabling PiP. This issue can be consistently reproduced on iPadOS 18.x when running an app built with Xcode 16.0 to Xcode 16.3RC(16E137). Beginning April 24, 2025, apps uploaded to App Store Connect must be built with Xcode 16 or later using an SDK for iOS 18, iPadOS 18, tvOS 18, visionOS 2, or watchOS 11.Therefore, I urgently hope to receive a solution provided by Apple.
Replies
1
Boosts
0
Views
164
Activity
Mar ’25
Lists, Generics, Views, Navigation Link, SwiftData - ForEach can't pass a binding anymore.
I'm trying out putting most of my business logic in a Protocol that my @Model can conform to, but I'm running into a SwiftUI problem with a Binding that does not get magically offered up like it does when it the subview is not generic. I have a pretty basic List with a ForEach that now can't properly pass to a generic view based on a protocol. When I try to make a binding manually in the row it says that "item is immutable"... but that also doesn't help me with the NavigationLink? Which is seeing the Binding not the ? But before when the subview was concrete to Thing, it took in the and made its own Binding once it hit the view. I'm unclear on precisely where the change happens and what I can do to work around it. Before I go rearchitecting everything... is there a fix to get the NavigationLink to take on the object like before? What needs to be different? I've tried a number of crazy inits on the subview and they all seem to come back to saying either it can't figure out how to pass the type or I'm trying to use the value before it's been initialized. Have I characterized the problem correctly? Thanks! (let me know if I forgot a piece of code, but this should be the List, the Model/Protocol and the subview) import SwiftUI import SwiftData struct ThingsView: View {     @Environment(\.modelContext) var modelContext     @Query var items: [Thing]          var body: some View {         NavigationStack {             List {                 ForEach(items) { item in                     NavigationLink(value: item) {                         VStack(alignment: .leading) {                             Text(item.textInfo)                                 .font(.headline)                                                          Text(item.timestamp.formatted(date: .long, time: .shortened))                         }                     }                 }.onDelete(perform: deleteItems)             }             .navigationTitle("Fliiiing!") //PROBLEM HERE: Cannot convert value of type '(Binding<Thing>) -> EditThingableView<Thing>' to expected argument type '(Thing) -> EditThingableView<Thing>'             .navigationDestination(for: Thing.self, destination: EditThingableView<Thing>.init) #if os(macOS)             .navigationSplitViewColumnWidth(min: 180, ideal: 200) #endif             .toolbar { #if os(iOS)                 ToolbarItem(placement: .navigationBarTrailing) {                     EditButton()                                      } #endif                 ToolbarItem {                     Button(action: addItem) {                         Label("Add Item", systemImage: "plus")                     }                 }                 ToolbarItem {                     Button("Add Samples", action: addSamples)                 }             }         }     }          func addSamples() {         withAnimation {             ItemSDMC.addSamples(context: modelContext)         }     }          private func addItem() {         withAnimation {             let newItem = ItemSDMC("I did a thing!")             modelContext.insert(newItem)         }     }          func deleteItems(_ indexSet:IndexSet) {         withAnimation {             for index in indexSet {                 items[index].delete(from: modelContext)             }         }     } } #Preview {     ThingsView().modelContainer(for: ItemSDMC.self, inMemory: true) } import Foundation import SwiftData protocol Thingable:Identifiable {     var textInfo:String { get set }     var timestamp:Date { get set } } extension Thingable {     var thingDisplay:String {         "\(textInfo) with \(id) at \(timestamp.formatted(date: .long, time: .shortened))"     } } extension Thingable where Self:PersistentModel {     var thingDisplayWithID:String {         "\(textInfo) with modelID \(self.persistentModelID.id) in \(String(describing: self.persistentModelID.storeIdentifier)) at \(timestamp.formatted(date: .long, time: .shortened))"     } } struct ThingLite:Thingable, Codable, Sendable {     var textInfo: String     var timestamp: Date     var id: Int } @Model final class Thing:Thingable {     //using this default value requires writng some clean up logic looking for empty text info.     var textInfo:String = ""     //using this default value would require writing some data clean up functions looking for out of bound dates.     var timestamp:Date = Date.distantPast          init(textInfo: String, timestamp: Date) {         self.textInfo = textInfo         self.timestamp = timestamp     } } extension Thing {     var LiteThing:ThingLite {         ThingLite(textInfo: textInfo, timestamp: timestamp, id: persistentModelID.hashValue)     } } import SwiftUI struct EditThingableView<DisplayItemType:Thingable>: View {     @Binding var thingHolder: DisplayItemType          var body: some View {                  VStack {             Text(thingHolder.thingDisplay)             Form {                 TextField("text", text:$thingHolder.textInfo)                 DatePicker("Date", selection: $thingHolder.timestamp)             }                      } #if os(iOS)         .navigationTitle("Edit Item")         .navigationBarTitleDisplayMode(.inline) #endif     } } //NOTE: First sign of trouble //#Preview { //    @Previewable var myItem = Thing(textInfo: "Example Item for Preview", timestamp:Date()) //    EditThingableView<Thing>(thingHolder: myItem) //}
Replies
4
Boosts
0
Views
204
Activity
May ’25
Trigger save of a FileDocument in a DocumentGroup?
I have a DocumentGroup working with a FileDocument, and that's fine. However, when someone creates a new document I want them to have to immediately save it. This is the behavior on ipadOS and iOS from what I can understand (you select where before the file is created). There seems to be no way to do this on macOS? I basically want to have someone: create a new document enter some basic data hit "create" which saves the file then lets the user start editing it (1), (2), and (4) are done and fairly trivial. (3) seems impossible, though...? This really only needs to support macOS but any pointers would be appreciated.
Replies
0
Boosts
0
Views
283
Activity
Apr ’25
Save credentials prompt not shown when login and password aren't the last fields in a form
The save credentials prompt is not shown after clicking the submit button in the following setup. The prompt is shown if I move the email field before the login field. Is it really required to have login and password fields at the end of the registration form? Or is there some API that can trigger the prompt? struct FakeRegistrationView: View { @State private var login = "" @State private var password = "" @State private var repeatPassword = "" @State private var email = "" var navigateBack: () -> Void var body: some View { VStack(spacing: 16) { TextField("Login", text: $login) .textFieldStyle(.roundedBorder) .textContentType(.username) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) SecureField("Password", text: $password) .textFieldStyle(.roundedBorder) .textContentType(.newPassword) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) SecureField("Repeat password", text: $repeatPassword) .textFieldStyle(.roundedBorder) .textContentType(.newPassword) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) TextField("Email", text: $email) .textFieldStyle(.roundedBorder) .textContentType(.emailAddress) .disableAutocorrection(true) .autocapitalization(.none) .frame(maxWidth: 300) Button { Task { try? await Task.sleep(for: .seconds(2)) navigateBack() } } label: { Text("Submit") } .buttonStyle(.borderedProminent) } } }
Replies
1
Boosts
0
Views
239
Activity
Mar ’25
Save fails after Save As
I have an app with two file types with the following extensions: gop (an exported type), sgf (an imported type). The Save command fails after the following sequence of events: I open a gop file, say the file "A.gop". I save this file as an sgf file, say "A.sgf". This Save As works perfectly and the document name in the document’s title bar has changed to "A.sgf". I change something in the document and then try to Save this change. This should just resave the document to "A.sgf", but "A.sgf" remains untouched. Instead I get a system alert with the message The document “A.sgf” could not be saved. A file with the name “A.gop” already exists. To save the file, either provide a different name, or move aside or delete the existing file, and try again. In the Xcode console I get the following diagnostic: NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 2 [NSFileCoordinator itemAtURL:willMoveToURL:] could not get a sandbox extension. oldURL: file:///Users/francois/Desktop/A.sgf, newURL: file:///Users/francois/Desktop/A.gop The problem seems to relate to the sandbox. But I am at a loss to find a solution. (After closing the alert, I check that A.sgf did not register the change.) If I open an sgf file, say "B.sgf", save it as "B.gop", make a change in the document and then try to save this change (into "B.gop"), I hit the same problem, with "gop" and "sgf" interchanged. If, instead of saving "A.gop" as "A.sgf", I save it as "B.sgf", make a change in the document and then try to save this change into "B.sgf", I get the following system alert: The document “B.sgf” could not be saved. You don’t have permission. To view or change permissions, select the item in the Finder and choose File &gt; Get Info. And in the Xcode console I get the following diagnostic: NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 2 [NSFileCoordinator itemAtURL:willMoveToURL:] could not get a sandbox extension. oldURL: file:///Users/francois/Desktop/B.sgf, newURL: file:///Users/francois/Desktop/B.gop Again the sandbox ! (After closing the alert, I check that B.sgf did not register the change.) It’s clear my code is missing something, but what?
Replies
0
Boosts
0
Views
154
Activity
Apr ’25
How to customize item transitions inside a Picker View?
I have a simple Picker where the options available change by the view state. I would like to have the transition animated but the default animation is not good so I tried setting a .transition() and or an .animation() inside an item on the picker but it is ignored. The same happens if the transition is set on the picker itself since it's always present. Am I doing it right and is just not posible or is there something else to do? Code to reproduce the issue: struct ContentView: View { @State var list: [String] = [ "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", ] @State var selected: String? @State var toggle: Bool = false var body: some View { VStack { Picker("List", selection: $selected) { ForEach(list, id: \.self) { Text($0).tag($0) // .transition(.opacity) } } .pickerStyle(.segmented) // .transition(.opacity) HStack { Button(action: swapOptions) { Text("Swap") } } } .padding() } } extension ContentView { func swapOptions() { withAnimation { toggle.toggle() switch toggle { case true: list = [ "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", ] case false: list = [ "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", ] } } } } ``
Topic: UI Frameworks SubTopic: SwiftUI
Replies
0
Boosts
0
Views
98
Activity
May ’25
Remove "copy cursor" when dragging a view in SwiftUI
Hi, Im new to SwiftUI and Im trying to implement some drag and drop functionality for some tabs in my application. Im using .draggable(_) and .dropDestination for this and the issue I have is that as I drag the view, the mouse cursor changes to the copy cursor with the green plus sign and I don't like it but I can't figure out how to avoid it. Any help would be appreciated.
Replies
1
Boosts
0
Views
76
Activity
Apr ’25
[SwiftUI] Gesture Conflict: simultaneousGesture Causes Incorrect Gesture Recognition in iOS 18
Subject: SwiftUI Gesture Conflict in iOS 18: Simultaneous Recognition of Drag and Tap Gestures Description: In SwiftUI on iOS 18 and above, we've identified an issue with gesture handling that affects user experience. When implementing .simultaneousGesture(DragGesture()), the system incorrectly recognizes and processes both drag and tap gestures concurrently, resulting in unintended behavior. Technical Details: Environment: SwiftUI, iOS 18+ Issue: Simultaneous recognition of horizontal drag gestures and vertical scroll/tap gestures Current Behavior: Both vertical and horizontal scrolling occur simultaneously when using .simultaneousGesture(DragGesture()) Expected Behavior: Gestures should be properly disambiguated to prevent concurrent scrolling in multiple directions Impact: This behavior significantly impacts user experience, particularly in custom carousel implementations and other UI components that rely on precise gesture handling. The simultaneous recognition of both gestures creates a confusing and unpredictable interaction pattern. Steps to Reproduce: Create a SwiftUI view with horizontal scrolling (e.g., custom carousel) Implement .simultaneousGesture(DragGesture()) Add tap gesture recognition to child views Run on iOS 18 Attempt to scroll horizontally Observed Result: Both horizontal dragging and vertical scrolling/tapping are recognized and processed simultaneously, creating an inconsistent user experience. Expected Result: The system should properly disambiguate between horizontal drag gestures and vertical scroll/tap gestures, allowing only one type of gesture to be recognized at a time based on the user's intent. Please let me know if you need any additional information or reproduction steps.
Replies
0
Boosts
0
Views
125
Activity
Apr ’25
.onTapGesture does not work when SwiftUI component sits in a flipped NSVIew
Take a look at this simple code: import Cocoa import SwiftUI struct DemoView: View { var body: some View { Text("Click me!") .onTapGesture { print("Clicked") } } } class FlippedView: NSView { override var isFlipped: Bool { return true } } class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() let stackView = NSStackView() stackView.orientation = .vertical stackView.alignment = .leading stackView.spacing = 0 stackView.translatesAutoresizingMaskIntoConstraints = false let hostView = NSHostingView(rootView: DemoView()) stackView.addArrangedSubview(hostView) let scrollView = NSScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false let flippedView = FlippedView() flippedView.addSubview(stackView) scrollView.documentView = flippedView view.addSubview(scrollView) NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.topAnchor), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) } } I need my scroll view to start at the very top, so i put it inside a flipped document view. But now .onTapGesture does not fire.
Replies
1
Boosts
0
Views
163
Activity
Apr ’25
The @Environment(\.dismiss) value in SwiftUI for macOS does not dismiss a sheet presented by an NSWindowController.
I'm wondering what the correct, or recommended, way is to dismiss a SwiftUI that is being presented as a sheet hosted by an NSHostingController. The usual technique of invoking @Environment(\.dismiss) does not appear to work. Consider the code below. An NSWindowController is attempting to display a SwiftUI SettingsView as a sheet. The sheet is correctly presented, but the SettingsView is unable to dismiss itself. I am able to make it work by passing a closure into SettingsView that calls back to the NSWindowController but it's rather convoluted because SettingsView doesn't know the view controller that's hosting it until after SettingsView has been created, which means "finding" that view controller in the window controller to dismiss is more involved than it should be. Is there a better strategy to leverage here? final class MyViewController: NSViewController { @IBAction func buttonClicked(_ sender: NSButton) { if let presenter = window?.contentViewController { presenter.presentAsSheet(NSHostingController(rootView: SettingsView())) } } } struct SettingsView: View { @Environment(\.dismiss) private var dismiss var body: some View { VStack { Button("Cancel", role: .cancel) { dismiss() // This call does not dismiss the sheet. } .keyboardShortcut(.cancelAction) } } } Thank you. macOS 15.4.1 (24E263), Xcode 16.3 (16E140)
Replies
0
Boosts
0
Views
96
Activity
Apr ’25
SwiftUI + OSlog breaks previews in Swift 6
import SwiftUI import OsLog let logger = Logger(subsystem: "Test", category: "Test") struct ContentView: View { var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") } .padding() .task { logger.info("Hallo") } } } #Preview { ContentView() } 27 | .padding() 28 | .task { 29 | logger.info(__designTimeString("#6734_2", fallback: "Hallo")) | `- error: argument must be a string interpolation 30 | } 31 | } Should OsLog be compatible with __designTimeString?
Replies
1
Boosts
0
Views
143
Activity
Mar ’25
App Crashes on Paper Selection After Background Printer Connection
Description: When initiating the print flow via UIPrintInteractionController, and no printer is initially connected, iOS displays all possible paper sizes in the paper selection UI. However, if a printer connects in the background after this view is shown, the list of paper sizes does not automatically refresh to reflect only the options supported by the connected printer. If the user selects an incompatible paper size (one not supported by the printer that has just connected), the app crashes due to an invalid configuration. Steps to Reproduce: Launch the app and navigate to the print functionality. Tap the Print button to invoke UIPrintInteractionController. At this point, no printer is yet connected. iOS displays all available paper sizes. While the paper selection UI is visible, the AirPrint-compatible printer connects in the background. Without dismissing the controller, the user selects a paper size (e.g., one that is not supported by the printer). The app crashes. Expected Result: App should not crash Once the printer becomes available (connected in the background), the paper size options should refresh automatically. The list should be filtered to only include sizes that are compatible with the connected printer. This prevents the user from selecting an invalid option, avoiding crashes. Actual Result: App crashes The paper size list remains unfiltered. The user can still select unsupported paper sizes. Selecting an incompatible option causes the app to crash, due to a mismatch between UI selection and printer capability.
Topic: UI Frameworks SubTopic: UIKit
Replies
0
Boosts
0
Views
95
Activity
Apr ’25
Activate hoverEffect on separate entity attachment view
Hi, I'm working on RealityView and I have two entities in RCP. In order to set views for both entities, I have to create two separate attachments for each entity. What I want to achieve is that when I hover (by eye) on one entity's attachment, it would trigger the hover effect of the other entity's attachment. I try to use the hoverEffectGroup, but it would only activate the hover effect in a subview, instead a complete separate view. I refer to the following WWDC instruction for the hover effect. https://developer.apple.com/videos/play/wwdc2024/10152/
Replies
0
Boosts
0
Views
80
Activity
Apr ’25
UITextField The input space cursor is gone
UITextField The input space cursor is gone
Topic: UI Frameworks SubTopic: UIKit
Replies
2
Boosts
0
Views
55
Activity
Mar ’25
Display a broader track of a user on ios app with Mapkit.
Hello I'm currently building a feature within an ios app using SwiftUI and Mapkit to record the gps cordinates of a user as they move and render the track on the map. the idea is not really to have a "track" but to have a visual representation of the area the user sees while they are moving around. I need this width/breadth to be relative to the map and not the screen, such that when I zoom in and out of the map, the size will adjust automatically.
Replies
0
Boosts
0
Views
74
Activity
May ’25
iOS18 iPad Custom UITabBar invalid
After my XCode was upgraded to 16.2, the custom bottom tabbar of iPadAPP could not be displayed properly (I set "traitOverrides.horizontalSizeClass = .compact", otherwise the tabbar would be displayed at the top and it was not the style I wanted) Below are my code and pictures of the running effects of iOS17 and iOS18 override func viewDidLoad() { super.viewDidLoad() setValue(CustomTabBar(), forKey: "tabBar") if #available(iOS 18.0, *) { self.mode = .tabBar self.traitOverrides.horizontalSizeClass = .compact } } } class CustomTabBar: UITabBar { var leftView = UIView() var rightView = UIView() override func sizeThatFits(_ size: CGSize) -> CGSize { var sizeThatFits = super.sizeThatFits(size) sizeThatFits.height = 60 // 自定义高度 return sizeThatFits } override func layoutSubviews() { super.layoutSubviews() self.backgroundColor = .red addSubview(leftView) addSubview(rightView) leftView.backgroundColor = .green leftView.frame = CGRect(x: 10, y: 4, width: 80, height: 40) rightView.backgroundColor = .green rightView.frame = CGRect(x: 600, y: 4, width: 80, height: 40) } } ![]("https://developer.apple.com/forums/content/attachment/66988297-26dc-4b40-af37-103f6a277563" "title=20250409151648.jpg;width=2394;height=1716")
Topic: UI Frameworks SubTopic: UIKit
Replies
4
Boosts
0
Views
285
Activity
Apr ’25