on iOS you can choose to scale to view to have the app resize the screen easily in the developer environment. Scale to view is however not easily done on MacOS using NS to solve on MacOS now. Is it possible for the Apple developer team to make this easier for the Developer, as I understand it is for iOS applications?
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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
So I am looking to use a custom NSWindow application (so I can implement some enhanced resizing/dragging behavior which is only possible overriding NSWindow).
The problem is my whole application is currently SwiftUI-based (see the project here: https://github.com/msdrigg/Roam/blob/50a2a641aa5f2fccb4382e14dbb410c1679d8b0c/Roam/RoamApp.swift).
I know there is a way to make this work by dropping my @main SwiftUI app and replacing it with a SwiftUI root view hosted in a standard AppKit root app, but that feels like I'm going backwards.
Is there another way to get access (and override) the root NSWindow for a SwiftUI app?
As SwiftUI adoption grows, developers face challenges in effectively measuring and optimizing SwiftUI app performance within automated tests.
Currently, the only viable approach to analyzing SwiftUI performance is through Profiling (Instruments), which, while powerful, lacks the ability to be incorporated into automated testing workflows. It would be incredibly valuable if XCTest could introduce new performance metrics specifically tailored for SwiftUI, allowing us to write tests against common performance bottlenecks.
Suggested Metrics:
View Body Evaluation Count – Tracks how often a SwiftUI body is recomputed to detect unnecessary re-renders.
Slow View Bodies – Flags SwiftUI views that take a significant amount of time to compute their body.
These metrics would help developers identify inefficiencies early, enforce performance best practices through CI/CD pipelines, and ensure a smooth user experience. I believe adding these performance metrics would be a game-changer for SwiftUI development.
Thank you for your time and consideration!
I have an App that builds for iOS, iPadOS, macOS and Apple TV, which was last released to all the App Stores in April. Preferences/settings are handled by the App itself except for the Apple TV variant, where I use a Settings bundle. This worked fine until tvOS 15.0, where it appears that tvOS is not updating the value of the App’s settings from NSUserDefaults when the Settings App opens. I have been working on this problem off and on for the last week and am at wits end.
I’ve searched WWDC videos looking for a clue, there must be some simple change I cannot see. I’ve made clean projects for iOS and tvOS, and using the identical OBJ-C code and Settings plist entries, the iOS version works perfectly, the tvOS version fails in the simulator and on the device. I am not trying to synchronize Settings across devices, just persist across restarts on a single device.
My code stores data correctly in NSUserDefaults, it simply seems that tvOS Settings App is not reading values from there for display, nor writing changes that the user makes from Settings back to user defaults. None of the types in the test projects work: TexField, Switch, Title.
The test code is so simple I hesitate to include it, but the code and the NSUserDefaults key identifiers do match. This code will preset my App’s version number for Settings to display in iOS 15 but not tvOS 15. It used to work in tvOS 14:
<key>DefaultValue</key>
<string>DefaultVersionValue</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
<string>VersionKey</string>
</dict>
``` NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud registerDefaults:@{
@"TextFieldKey" : @"TextFieldValue",
@"VersionKey" : @"VersionValue"
}];
[ud setObject:@"3.14" forKey:@"VersionKey"];
Any idea? Many thanks.
Below is a basic test app to resemble an actual app I am working on to hopefully better describe an issue I am having with tab view. It seems only in split screen when I am triggering something onAppear that would cause another view to update, or another view updates on its own, the focus gets pulled to that newly updated view instead of staying on the view you are currently on. This seems to only happen with views that are listed in the more tab. In any other orientation other than 50/50 split this does not happen. Any help would be appreciated.
struct ContentView: View {
@State var selectedTab = 0
var body: some View {
NavigationStack {
NavigationLink(value: 0) {
Text("ENTER")
}.navigationDestination(for: Int.self) { num in
TabsView(selectedTab: $selectedTab)
}
}
}
}
struct TabsView: View {
@Binding var selectedTab: Int
@State var yikes: Int = 0
var body: some View {
if #available(iOS 18.0, *) {
TabView(selection: $selectedTab) {
MyFlightsView(yikes: $yikes)
.tabItem {
Label("My Flights", systemImage: "airplane.circle")
}.tag(0)
FlightplanView()
.tabItem {
Label("Flight Plan", systemImage: "doc.plaintext")
}.tag(1)
PreFlightView()
.tabItem {
Label("Pre Flight", systemImage: "airplane.departure")
}.tag(2)
CruiseView(yikes: $yikes)
.tabItem {
Label("Cruise", systemImage: "airplane")
}.tag(3)
PostFlightView()
.tabItem {
Label("Post Flight", systemImage: "airplane.arrival")
}.tag(4)
MoreView()
.tabItem {
Label("More", systemImage: "ellipsis")
}.tag(5)
NotificationsView()
.tabItem {
Label("Notifications", systemImage: "bell")
}.tag(6)
}.tabViewStyle(.sidebarAdaptable)
}
}
}
Like many applications, mine involves navigation where the user starts a process on one screen and then progresses through several more steps to reach a conclusion. When he confirms that choice, I need to dismiss the entire stack. In my case, he's browsing contacts, selecting one, and then selecting a communication method from those offered by the contact.
This still appears to be a PITA in SwiftUI. NavigationPath is supposed to provide a way to programmatically control a stack of views. Well... I can't find a single example of how to use it for this, except with absurdly shallow (as in a single level) of child views that all take the same datatype.
Nowhere do I see how to use the path as users proceed through your view hierarchy with NavigationLinks. I have not seen any example of how elements get added to the path or how they are related to each added view. Nor can I find an example of popping views off the stack by removing related elements from the path.
I created a class that encloses a NavigationPath:
@Observable
class NavPathController
{
var path: NavigationPath
init()
{
path = NavigationPath()
}
func popOne()
{
path.removeLast()
}
func popAll()
{
path.removeLast(path.count)
}
}
In my root view, I pass a binding to this controller's NavigationPath when creating the NavigationStack:
@State private var viewStack = NavPathController()
var body: some View
{
NavigationStack(path: $viewStack.path)
{
VStack()
{
NavigationLink(destination: UserFindingView(viewPathController: viewStack), label: { Text("Pick a recipient") })
}
}
And likewise each view passes the same view-path controller object to each child view that's invoked with a NavigationLink (instead of using an environment variable, because I find those hokey). But in the end, the path is empty; not surprisingly, clearing it does not pop the views.
So how is one supposed to make this work?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I am running into an issue where two distinct bool bindings are both being toggled when I toggle only one of them. My component looks like
VStack {
Checkbox(label: "Checkbox 1", isOn: $stateVar1)
Checkbox(label: "Checkbox 2", isOn: $stateVar2)
}
where my CheckBox component looks like
struct Checkbox: View {
let label: String
@Binding var isOn: Bool
var body: some View {
Button {
isOn.toggle()
} label: {
HStack {
Image(systemName: isOn ? "checkmark.square" : "square")
Text(label)
}
.foregroundStyle(.black)
}
}
}
If I click on one checkbox, both of them get toggled. However, if I simply remove the checkboxes from the VStack, then I am able to toggle them both independently. I believe this is a bug with bool Bindings, but if anyone can point out why I am mistaken that would be much appreciated :)
Topic:
UI Frameworks
SubTopic:
SwiftUI
This is a very strange behavior when pushing vc that I have never seen since I started coding. The pushed ViewController is transparent and only navBarTitle is shown. After the push, you can't control anything unless you go back to the home screen.
STEPS TO REPRODUCE
Long press currency change button below.(currencyWrapper)
Call selectCountry and this bug happens.
SourceCode
let currencyWrapper = UIView()
private func configureCurrencyCard(){
//The strange behavior shows up after long pressing this
currencyWrapper.backgroundColor = .white
currencyWrapper.addTarget(self, action: #selector(changeCurrency))
currencyWrapper.setWidth(currencyChangeIcon.follow(by: 16, x: true))
currencyWrapper.setCenterX(w1/2)
currencyWrapper.setHeight(currencyLabel.follow(by: 12, x: false))
currencyWrapper.roundToCircle(true)
view.addSubview(currencyWrapper)
}
private func selectCountry(country: Country){
let vc = CountryViewController(country: country)
vc.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(vc, animated: true)
}
When I switched to observable, I noticed a strange behavior of the ViewModel. The ViewModel is created 3x times. And my question is:
How to properly initialize the ViewModel via state?
Below is a minimal example with log output:
ViewModel INIT : EBBB2C41
ViewModel INIT : D8E490DA
ViewModel INIT : 54407300
ViewModel DEINIT: D8E490DA
@Observable
final class ViewModel {
@ObservationIgnored let idd: UUID
init() {
idd = UUID()
print("ViewModel INIT : \(idd.uuidString.prefix(8))")
}
deinit {
print("ViewModel DEINIT: \(idd.uuidString.prefix(8))")
}
}
struct SimpleView: View {
@Environment(ViewModel.self) private var viewModel
var body: some View {
@Bindable var viewModel = viewModel
Text("SimpleView: \(viewModel.idd.uuidString.prefix(8))")
}
}
struct ContentView: View {
@State private var viewModel = ViewModel()
var body: some View {
SimpleView()
.environment(mainViewModel)
}
}
I'm trying to setup a widget to pull an image down from a webserver and I'm running into an error of Widget archival failed due to image being too large [9] - (1024, 1024), totalArea: 1048576 > max[718080.000000].
I've tried two different approaches to resolve this error and both have failed to resolve the image.
I've also confirmed that I'm getting the image in the AppIntentTimelineProvider.
private func getImageUI(urlString: String) -> UIImage? {
guard let url = URL(string: urlString) else { return nil }
guard let imageData = try? Data(contentsOf: url) else { return nil }
return UIImage(data: imageData)?.resizedForWidget()
}
Is there another approach I could take on addressing this issue so the image appears on the widget?
Simple approach
extension UIImage {
func resized(toWidth width: CGFloat, isOpaque: Bool = true) -> UIImage? {
let canvas = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
let format = imageRendererFormat
format.opaque = isOpaque
return UIGraphicsImageRenderer(size: canvas, format: format).image {
_ in draw(in: CGRect(origin: .zero, size: canvas))
}
}
}
extension UIImage {
/// Resize the image to strictly fit within WidgetKit’s max allowed pixel area (718,080 pixels)
func resizedForWidget(maxArea: CGFloat = 718_080.0, isOpaque: Bool = true) -> UIImage? {
let originalWidth = size.width
let originalHeight = size.height
let originalArea = originalWidth * originalHeight
print("🔍 Original Image Size: \(originalWidth)x\(originalHeight) → Total Pixels: \(originalArea)")
// ✅ If the image is already within the limit, return as is
if originalArea <= maxArea {
print("✅ Image is already within the allowed area.")
return self
}
// 🔄 Calculate the exact scale factor to fit within maxArea
let scaleFactor = sqrt(maxArea / originalArea)
let newWidth = floor(originalWidth * scaleFactor) // Use `floor` to ensure area is always within limits
let newHeight = floor(originalHeight * scaleFactor)
let newSize = CGSize(width: newWidth, height: newHeight)
print("🛠 Resizing Image: \(originalWidth)x\(originalHeight) → \(newWidth)x\(newHeight)")
// ✅ Force bitmap rendering to ensure the resized image is properly stored
let format = UIGraphicsImageRendererFormat()
format.opaque = isOpaque
format.scale = 1 // Ensures we are not letting UIKit auto-scale it back up
let renderer = UIGraphicsImageRenderer(size: newSize, format: format)
let resizedImage = renderer.image { _ in
self.draw(in: CGRect(origin: .zero, size: newSize))
}
print("✅ Final Resized Image Size: \(resizedImage.size), Total Pixels: \(resizedImage.size.width * resizedImage.size.height)")
return resizedImage
}
}
These are logs from a failed image render if that helps
🔍 Original Image Size: 720.0x1280.0 → Total Pixels: 921600.0
🛠 Resizing Image: 720.0x1280.0 → 635.0x1129.0
✅ Final Resized Image Size: (635.0, 1129.0), Total Pixels: 716915.0
Hello everyone,
I've run into a peculiar behavior with UINavigationController's setViewControllers on iOS 18.2 (I guess it might be reproducible on older versions) when reordering view controllers, and I wonder if anyone can shed some light on this issue.
Initial State: The navigation stack is [A - B - C].
Without Animation: Setting [A - C - B] updates the stack to: A - C - B as expected.
With Animation: Using the same command with animation changes the stack to [A - B], oddly omitting C.
Has anyone else noticed similar behavior or knows why animations might disrupt the stack's update this way? I'd appreciate any insights or suggestions.
Thanks, Dmytro
When I present a view controller, whose view is a SwiftUI View, via presentAsModalWindow(_:) the presented window is no longer centered horizontally to the screen, but rather its origin is there. I know this issue occurs for macOS 15.2+, but can't tell if it is from 15.0+. I couldn't find any documentation on why was this changed.
Here's an example code that represents my architecture:
class RootViewController: NSViewController {
private lazy var button: NSButton = NSButton(
title: "Present",
target: self,
action: #selector(presentView))
override func viewDidLoad() {
super.viewDidLoad()
// Add button to tree
}
@objc func presentView() {
presentAsModalWindow(PresentedViewController())
}
}
class PresentedViewController: NSViewController {
override loadView() {
view = NSHostingView(rootView: MyView())
}
}
struct MyView: View {
/* impl */
}
Hello, community,
I'm using an HTML editor in a .NET MAUI application running on macOS, and I'm encountering some unexpected behavior during text editing:
Double-click text selection disappears after approximately one second.
Styles randomly revert or are applied to the wrong text unexpectedly.
It appears to be related to macOS spell checking. When using editable elements (, or with contenteditable), the system enables spell checking by default.
During this, MAUI attempts to communicate with a system process:
com.apple.TextInput.rdt, which is not running, leading to repeated errors like:
Error Domain=NSCocoaErrorDomain Code=4099
"The connection to service named com.apple.TextInput.rdt was invalidated: failed at lookup with error 3 - No such process."
Question:
What is com.apple.TextInput.rdt, and why might it not be running?
Thank you for any help!
Hello, I have encountered a question that I hope to receive an answer to. Currently, I am working on a music project for Mac Catalyst and need to enable music files such as FLAC to be opened by right clicking to view my Mac Catalyst app. But currently, I have encountered a problem where I can see my app option in the right-click open mode after debugging the newly created macOS project using the following configuration. But when I created an iOS project and converted it to a Mac Catalyst app, and then modified the info.plist with the same configuration, I couldn't see my app in the open mode after debugging. May I ask how to solve this problem? Do I need to configure any permissions or features in the Mac Catalyst project? I have been searching for a long time but have not found a solution regarding it. Please resolve it, thank you.
Here is the configuration of my macOS project:
CFBundleDocumentTypes
CFBundleTypeExtensions
flac
CFBundleTypeIconSystemGenerated
1
CFBundleTypeName
FLAC Audio File
CFBundleTypeRole
Viewer
LSHandlerRank
Default
Note: Sandbox permissions have been enabled for both the macOS project and the iOS to Mac Catalyst project. The Mac Catalyst project also has additional permissions for com. apple. security. files. user taught. read write
Hi,
I’m practicing with NavigationSplitView for macOS and customizing the sidebar. I’ve managed to adjust most parts, but I couldn’t remove the sidebar’s divider. It seems like it’s not possible in modern SwiftUI. My AppKit knowledge is also not very strong.
How can I remove the sidebar divider?
I want to use a plain background. I also solved it by creating my own sidebar, but I wanted to try it using NavigationSplitView.
In a UIKit application, removing a view from the hierarchy is straightforward—we simply call myView.removeFromSuperview(). This not only removes myView from the UI but also deallocates any associated memory.
Now that I'm transitioning to SwiftUI, I'm struggling to understand the recommended way to remove a view from the hierarchy, given SwiftUI's declarative nature.
I understand that in SwiftUI, we declare everything that should be displayed. However, once a view is rendered, what is the correct way to remove it? Should all UI elements be conditionally controlled to determine whether they appear or not?
Below is an example of how I’m currently handling this, but it doesn’t feel like the right approach for dynamically removing a view at runtime.
Can someone guide me on the best way to remove views in SwiftUI?
struct ContentView: View {
@State private var isVisible = true
var body: some View {
VStack {
if isVisible { // set this to false to remove TextView?
Text("Hello, SwiftUI!")
.padding()
}
Button("Toggle View") {
...
}
}
}
}
Has anyone gotten custom buttons to work on top of tvOS Map()? I've tried many variations of
FocusState
focusSection
.defaultFocus()
and as soon as the map appears at startup the buttons never get focus again. They are on a ZStack over the map. I could post code but truthfully nothing works for me. I'm wondering if anyone has successfully put focusable buttons on top of the map view.
I'm making a custom control, specifically a checkbox next to a "label." I want the label parameter, like many in Apple's built-in controls, to take a view-building closure.
But I can't figure out the correct syntax. I looked at the declaration of Apple's NavigationLink control for clues:
public struct NavigationLink<Label, Destination> : View where Label : View, Destination : View {
/// Creates a navigation link that presents the destination view.
/// - Parameters:
/// - destination: A view for the navigation link to present.
/// - label: A view builder to produce a label describing the `destination`
/// to present.
public init(@ViewBuilder destination: () -> Destination, @ViewBuilder label: () -> Label)
But when I mimic this, the compiler complains about the body() function:
struct CheckboxItem<Label> : View where Label : View
{
let stateCheck: () -> Bool
let label: () -> any View
let boxSize: CGFloat
init(withStateCheck: @escaping () -> Bool, boxSize: CGFloat, @ViewBuilder label: @escaping () -> Label)
{
stateCheck = withStateCheck
self.label = label
self.boxSize = boxSize
}
var body: some View
{
HStack
{ <-- ERROR: "Type 'any View' cannot conform to 'View'"
Image(systemName: stateCheck() ? "checkmark.square" : "square")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: boxSize, height: boxSize)
.foregroundColor(AppStyle.labelColor)
.opacity(0.75)
label()
}
}
}
Also, note that I had to put @escaping before my label parameter, but that's not seen in Apple's.
Any ideas?
Topic:
UI Frameworks
SubTopic:
SwiftUI
I have an application named "XY" that has been launched in several countries. Now, I intend to launch it in Turkey, but we are facing legal issues preventing us from using "XY" as the app's display name. Following the documentation, I localized the app's display name to "ZX" for both Turkish and English (Turkey). However, when users change their device settings, they do not see an option for English (Turkey) language selection. I assumed that for Turkish users, English (Turkey) would be the default language, but this is not the case. Could someone please assist me in resolving this issue? I've investigated options for localizing the display name based on region, but it seems that this functionality isn't feasible on iOS. In contrast, it's relatively straightforward to achieve on Android platforms.
I have a use case in which there is a zoomable and pannable parent view, and a child view that needs to display a custom context menu on long press.
(The reason why I need to implement a custom context menu is this: https://developer.apple.com/forums/thread/773810)
It seems, however, that this setup produces a bug in SwiftUI. The problem is that the onChanged of the drag gesture is only invoked right before its onEnded, hence you cannot smoothly animate the drag:
struct ContentView: View {
var body: some View {
ZStack {
Rectangle()
.foregroundStyle(.green)
.frame(width: 200, height: 200)
.onLongPressGesture {
print("long press")
}
}
.gesture(MagnifyGesture().onEnded { value in
print("magnify end")
})
.gesture(DragGesture()
.onChanged { value in
print("drag change")
}
.onEnded { value in
print("drag end")
})
}
}
Changing the DragGesture to a .highPriorityGesture() makes the drag's onChange execute at the correct time but results in the LongPressGesture only triggering when the user lifts up his/her finger (which was originally not the case).
So it seems that the two gestures are in a sort of conflict with each other.
Is there a workaround?
Topic:
UI Frameworks
SubTopic:
SwiftUI