Is there any way I can know that another app has gone full screen? Please note that this is not what NSWindowDidEnterFullScreenNotification does, that only works for my own windows.
As for why I need to know: Say you're playing a YouTube video full screen. The video fills up the main display, and if there's a second display, it goes black. Well, mostly. I have a utility app with small status windows that remain on top. I'd like to be polite and hide them in this scenario.
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
I have SwiftData models containing arrays of Codable structs that worked fine before adding CloudKit capability. I believe they are the reason I started seeing errors after enabling CloudKit.
Example model:
@Model
final class ProtocolMedication {
var times: [SchedulingTime] = [] // SchedulingTime is Codable
// other properties...
}
After enabling CloudKit, I get this error logged to the console:
'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
CloudKit Console shows this times data as "plain text" instead of "bplist" format.
Other struct/enum properties display correctly (I think) as "bplist" in CloudKit Console.
The local SwiftData storage handled these arrays fine - this issue only appeared with CloudKit integration.
What's the recommended approach for storing arrays of Codable structs in SwiftData models that sync with CloudKit?
I have this sample code
import SwiftUI
struct ContentView: View {
var body: some View {
ParentView()
}
}
struct ParentView: View {
@State var id = 0
var body: some View {
VStack {
Button {
id+=1
} label: {
Text("update id by 1")
}
TestView(id: id)
}
}
}
struct TestView: View {
var sequence = DoubleGenerator()
let id: Int
var body: some View {
VStack {
Button {
sequence.next()
} label: {
Text("print next number").background(content: {
Color.green
})
}
Text("current id is \(id)")
}.task {
for await number in sequence.stream {
print("next number is \(number)")
}
}
}
}
final class DoubleGenerator {
private var current = 1
private let continuation: AsyncStream<Int>.Continuation
let stream: AsyncStream<Int>
init() {
var cont: AsyncStream<Int>.Continuation!
self.stream = AsyncStream { cont = $0 }
self.continuation = cont
}
func next() {
guard current >= 0 else {
continuation.finish()
return
}
continuation.yield(current)
current &*= 2
}
}
the print statement is only ever executed if I don't click on the update id by 1 button. If i click on that button, and then hit the print next number button, the print statement doesn't print in the xcode console. I'm thinking it is because the change in id triggered the view's init function to be called, resetting the sequence property and so subsequent clicks to the print next number button is triggering the new version of sequence but the task is still referring its previous version.
Is this expected behaviour? Why in onChange and Button, the reference to the properties is always up to date but in .task it is not?
既然 iOS 26 必须启用 UIScene 生命周期,那么 UIAlertView/UIActionSheet 就实际已经无法使用了,所以为什么不直接将它们标记为不可用,或者直接移除?
Hi all,
I’m working on the alternative marketplace app and using MarketplaceKit and ActionButton. On the main page, users see a list of items, each with an ActionButton. I’m experiencing significant UI hangs when this page loads.
What I’ve Observed:
Instruments (Hangs and SwiftUI profilers) show that the hangs occur when ActionButton instances are rendered.
Creating or updating ActionButton properties triggers synchronous XPC communication with the managedappdistributiond process on the main thread.
Each XPC call takes about 2-3 ms, but with many ActionButtons, the cumulative delay is noticeable and impacts the user experience.
I have tested on iOS 18.7 and 26.1, using Xcode 26.2. But in general, the issue is not specific to a device or iOS version.
The problem occurs in both Debug and Release builds.
Hangs can be severe depending on the number of items in a section, generally between 200-600 ms, resulting in noticeable lag and a poor user experience.
I haven’t found much documentation on the internal workings of ActionButton or why these XPC calls are necessary.
I have tried Lazy loading and reducing the amount of ActionButton instances. That makes the hangs less noticeable, but there are still hitches when new sections with items are added to the view hierarchy.
This is not an issue with SwiftUI or view updates in general. If I replace ActionButton with UIButton, the hangs are completely gone.
Minimal Example:
Here’s a simplified version of how I’m using ActionButton in my SwiftUI view. The performance issue occurs when many of these views are rendered in the list:
struct ActionButtonView: UIViewRepresentable {
let viewModel: ActionButtonViewModel
let style: ActionButtonStyle
func makeUIView(context: Context) -> ActionButton {
return ActionButton(action: viewModel.action)
}
func updateUIView(_ uiView: ActionButton, context: Context) {
uiView.update(\.size, with: context.coordinator.size)
uiView.update(\.label, with: viewModel.title)
uiView.update(\.isEnabled, with: context.environment.isEnabled)
uiView.update(\.fontSize, with: style.scaledFont(for: viewModel.title))
uiView.update(\.backgroundColor, with: style.backgroundColor.color)
uiView.update(\.tintColor, with: style.textAndIconColor)
uiView.update(\.cornerRadius, with: style.cornerRadius(height: uiView.frame.size.height))
uiView.update(\.accessibilityLabel, with: viewModel.accessibilityLabel)
uiView.update(\.accessibilityTraits, with: .button)
uiView.update(\.accessibilityUserInputLabels, with: viewModel.accesibilityUserInputLabels)
uiView.update(\.tintAdjustmentMode, with: .normal)
}
func makeCoordinator() -> Coordinator {
Coordinator(viewModel: viewModel)
}
class Coordinator: NSObject {
...
}
}
extension ActionButton {
fileprivate func update<T>(_ keyPath: WritableKeyPath<ActionButton, T>, with value: T)
where T: Equatable {
if self[keyPath: keyPath] == value { return }
var mutableSelf = self
mutableSelf[keyPath: keyPath] = value
}
}
From the Instruments samples, it’s clear that the performance issues originate from NativeActionButtonView.makeUIView(context:) and NativeActionButtonView.updateUIView(_:context:). The following stack trace is common for all blocking calls, indicating that NSXPCConnection is being used for cross-process communication:
mach_msg2_trap
mach_msg2_internal
mach_msg_overwrite
mach_msg
_dispatch_mach_send_and_wait_for_reply
dispatch_mach_send_with_result_and_wait_for_reply
xpc_connection_send_message_with_reply_sync
__NSXPCCONNECTION_IS_WAITING_FOR_A_SYNCHRONOUS_REPLY__
-[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:]
___forwarding___
_CF_forwarding_prep_0
__35-[_UISlotView _setContentDelegate:]_block_invoke_2
-[_UISlotView _updateContent]
...
NativeActionButtonView.sizeThatFits(_:uiView:context:)
protocol witness for UIViewRepresentable.sizeThatFits(_:uiView:context:) in conformance NativeActionButtonView
...
Additionally, the Thread State Trace shows that during the XPC calls, the main thread is blocked and is later made runnable by managedappdistributiond. This confirms that the app is indeed communicating with the managedappdistributiond process.
Since there is limited documentation and information available, I have some questions:
Is there a way to batch update ActionButton properties to reduce the number of XPC calls?
Is it possible to avoid or defer XPC communication when creating/updating ActionButton instances?
Are there best practices for efficiently rendering large numbers of ActionButtons in SwiftUI?
Is this a known issue, and are there any recommended workarounds?
Can Apple provide more details on ActionButton’s internal behavior and XPC usage?
Any insights or suggestions would be greatly appreciated!
Topic:
UI Frameworks
SubTopic:
SwiftUI
I’m running into a problem with SwiftUI/AppKit event handling on macOS Tahoe 26.2.
I have a layered view setup:
Bottom: AppKit NSView (NSViewRepresentable)
Middle: SwiftUI view in an NSHostingView with drag/tap gestures
Top: Another SwiftUI view in an NSHostingView
On macOS 26.2, the middle NSHostingView no longer receives mouse or drag events when the top NSHostingView is present. Events pass through to the AppKit view below. Removing the top layer immediately restores interaction. Everything works correctly on macOS Sequoia.
I’ve posted a full reproducible example and detailed explanation on Stack Overflow, including a single-file demo:
Stack Overflow post:
https://stackoverflow.com/q/79862332
I also found a related older discussion here, but couldn’t get the suggested workaround to apply:
https://developer.apple.com/forums/thread/759081
Any guidance would be appreciated.
Thanks!
Consider this code:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
EmptyView()
}
}
}
Which looks like this:
How can I prevent the sidebar from being resized by a mouse and from being hidden?
P.S. Can consider using AppKit if it can help.
Why there is a working animation with ScrollView + ForEach of items removal, but there is none with List?
ScrollView + ForEach:
struct ContentView: View {
@State var items: [String] = Array(1...5).map(\.description)
var body: some View {
ScrollView(.vertical) {
ForEach(items, id: \.self) { item in
Text(String(item))
.frame(maxWidth: .infinity, minHeight: 50)
.background(.gray)
.onTapGesture {
withAnimation(.linear(duration: 0.1)) {
items = items.filter { $0 != item }
}
}
}
}
}
}
List:
struct ContentView: View {
@State var items: [String] = Array(1...5).map(\.description)
var body: some View {
List(items, id: \.self) { item in
Text(String(item))
.frame(maxWidth: .infinity, minHeight: 50)
.background(.gray)
.onTapGesture {
withAnimation(.linear(duration: 0.1)) {
items = items.filter { $0 != item }
}
}
}
}
}```
I failed to resize the icon image from instances of NSRunningApplication. I can only get 32×32 while I'm expecting 16×16.
I felt it unintuitive in first minutes… Then I figured out that macOS menu seems not allowing many UI customizations (for stability?), especially in SwiftUI.
What would be my best solution in SwiftUI? Must I write some boilerplate SwiftUI-AppKit bridging?
We noticed in multiple apps that readableContentGuide is way too wide on iOS 26.x.
Here are changes between iPad 13inch iOS 18.3 and the same device iOS 26.2 (but this affects also iOS 26.0 and iOS 26.1):
13 inch iOS 18
Landscape ContentSizeCategory:
XS, Width: 1376.0 , Readable Width: 560.0
S, Width: 1376.0 , Readable Width: 600.0
M, Width: 1376.0 , Readable Width: 632.0
L, Width: 1376.0 , Readable Width: 664.0
XL, Width: 1376.0 , Readable Width: 744.0
XXL, Width: 1376.0 , Readable Width: 816.0
XXXL,Width: 1376.0 , Readable Width: 896.0
A_M, Width: 1376.0 , Readable Width: 1096.0
A_L, Width: 1376.0 , Readable Width: 1280.0
A_XL,Width: 1376.0 , Readable Width: 1336.0
13 inch iOS 26
Landscape ContentSizeCategory:
XS, Width: 1376.0 , Readable Width: 752.0
S, Width: 1376.0 , Readable Width: 800.0
M, Width: 1376.0 , Readable Width: 848.0
L, Width: 1376.0 , Readable Width: 896.0
XL, Width: 1376.0 , Readable Width: 1000.0
XXL, Width: 1376.0 , Readable Width: 1096.0
XXXL,Width: 1376.0 , Readable Width: 1200.0
A_M, Width: 1376.0 , Readable Width: 1336.0
The code I used:
class ViewController: UIViewController {
lazy var readableView: UIView = {
let view = UIView()
view.backgroundColor = .systemBlue
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(readableView)
NSLayoutConstraint.activate([
readableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
readableView.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor),
readableView.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor),
readableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if readableView.frame.width > 0 {
let orientation = UIDevice.current.orientation
print("""
ContentSizeCategory: \(preferredContentSizeCategoryAsString())
Width: \(view.frame.width) , Readable Width: \(readableView.frame.width), Ratio: \(String(format: "%.1f", (readableView.frame.width / view.frame.width) * 100))%
""")
}
}
func preferredContentSizeCategoryAsString() -> String {
switch UIApplication.shared.preferredContentSizeCategory {
case UIContentSizeCategory.accessibilityExtraExtraExtraLarge:
return "A_XXXL"
case UIContentSizeCategory.accessibilityExtraExtraLarge:
return "A_XXL"
case UIContentSizeCategory.accessibilityExtraLarge:
return "A_XL"
case UIContentSizeCategory.accessibilityLarge:
return "A_L"
case UIContentSizeCategory.accessibilityMedium:
return "A_M"
case UIContentSizeCategory.extraExtraExtraLarge:
return "XXXL"
case UIContentSizeCategory.extraExtraLarge:
return "XXL"
case UIContentSizeCategory.extraLarge:
return "XL"
case UIContentSizeCategory.large:
return "L"
case UIContentSizeCategory.medium:
return "M"
case UIContentSizeCategory.small:
return "S"
case UIContentSizeCategory.extraSmall:
return "XS"
case UIContentSizeCategory.unspecified:
return "U"
default:
return "D"
}
}
}
Please advise, it feels completely broken.
Thank you.
I created an application extension that uses IdentityLookup framework for SMS filtering. How can I deploy my product as a library? I tried wrapping it as a framework, but it was not successful.
I'm building an app with a min iOS of 26.
In iOS 26, bottom toolbars are attached to the NavStack where in ios18 they were attached to a vstack or scrollview. But in ios26 if the toolbar is attached to something like a vstack, it displays too low on an iPhone 16e and sits behind the tab bar. Fine.
But with a parent-child view, the parent has a NavStack (with bottom toolbar attached) and the child view doesn't have a NavStack. So...that's a problem.
The functional impact of this contradiction (bottom toolbars go on the NavStack and child views don't have a NavStack) is actually two problems.
the parent view bottom toolbar shows up on the child view (because it's the closest NavStack) whether it's appropriate on the view or not.
the child view can't have a viable bottom toolbar because without a NavStack any buttons are hidden behind the tab view.
The second problem can be worked around using a top toolbar or safe area edge inset instead of a toolbar at the bottom or something.
But those don't solve the first problem of the parent view bleeding through.
So, I have to be crazy, right. Apple wouldn't create a scenario where bottom toolbars are not functional on parent-child views in ios26.
Any suggestions that I'm missing?
Topic:
UI Frameworks
SubTopic:
SwiftUI
When the guy was talking about structural identity, starting at about 8:53, he mentioned how the swiftui needs to guarantee that the two views can't swap places, and it does this by looking at the views type structure. It guarantees that the true view will always be an A, and the false view will always be a B.
Not sure exactly what he means because views can't "swap places" like dogs. Why isn't just knowing that some View is shown in true, and another is shown in false, enough for its identity? e.g. The identity could be "The view on true" vs
"The view on false", same as his example with "The dog on the left" vs "The dog on the right"
When I have a TextField or TextEditor, tapping into it produces these two console entries about 18 times each:
CHHapticPattern.mm:487 +[CHHapticPattern patternForKey:error:]: Failed to read pattern library data: Error Domain=NSCocoaErrorDomain Code=260 "The file “hapticpatternlibrary.plist” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Library/Audio/Tunings/Generic/Haptics/Library/hapticpatternlibrary.plist, NSURL=file:///Library/Audio/Tunings/Generic/Haptics/Library/hapticpatternlibrary.plist, NSUnderlyingError=0x600000ca1b30 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
<_UIKBFeedbackGenerator: 0x600003505290>: Error creating CHHapticPattern: Error Domain=NSCocoaErrorDomain Code=260 "The file “hapticpatternlibrary.plist” couldn’t be opened because there is no such file." UserInfo={NSFilePath=/Library/Audio/Tunings/Generic/Haptics/Library/hapticpatternlibrary.plist, NSURL=file:///Library/Audio/Tunings/Generic/Haptics/Library/hapticpatternlibrary.plist, NSUnderlyingError=0x600000ca1b30 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
My app does not use haptics.
This doesn't appear to cause any issues, although entering text can feel a bit sluggish (even on device), but I am unable to determine relatedness. None-the-less, it definitely is a lot of log noise.
Code to reproduce in simulator (xcode 26.2; ios 26 or 18, with iPhone 16 Pro or iPhone 17 Pro):
import SwiftUI
struct ContentView: View {
@State private var textEntered: String = ""
@State private var textEntered2: String = ""
@State private var textEntered3: String = ""
var body: some View {
VStack {
Spacer()
TextField("Tap Here", text: $textEntered)
TextField("Tap Here Too", text: $textEntered2)
TextEditor(text: $textEntered3)
.overlay(RoundedRectangle(cornerRadius: 8).strokeBorder(.primary, lineWidth: 1))
.frame(height: 100)
Spacer()
}
}
}
#Preview {
ContentView()
}
Tapping back and forth in these fields generates the errors each time.
Thanks,
Steve
I've integrated PencilKit into my app, but I've noticed that shape recognition isn't working during drawing, even though it works perfectly in the Notes app. Is this a bug, or is shape recognition simply not supported in PencilKit for Swift?
Hello,
I'm trying to make a white-Label sort of thing for my app, that is: a script runs before the app launches, sets a certain LaunchAgent command that sets and environment variable, and based on that variable's value tha main app's icon changes to a certain logo (change only happens in the dock because changing the icon on disk breaks the signature)
When the app launches it takes a noticeable time until the dock icon changes to what I want, so I worked around that by setting the app's plist property to hide the dock icon and then when the app is launched I call an objc++ function to display the icon in the dock again (this time it displays as the new icon)
The showing happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
The problem happens when I try to close the app, it returns back to the old logo before closing which is what I want to prevent. I tried hiding the app dock icon before closing but even the hiding itself changes the icon before hiding
The hiding happens through [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited];
My goal is that the main app icon doesn't appear to the user through the dock, and that the icon that is only visible is the other one that changes during runtime
The reason for this is that I have an app that should be visible differently depending on an environment variable that I set using an installer app. The app is the same for all users with very minor UI adjustments depending on that env variable's value. So instead of creating different versions of the app I'd like to have just 1 version that adjusts differently depending on the env variable's value. Somehow this is the only step left to have a smooth experience
Feel free to ask more clarification questions I'd be happy to help
Thank you
When I navigate to a player controller and switch to landscape mode, and then pop it and choose portrait mode, the tabBar encounters an issue
Topic:
UI Frameworks
SubTopic:
UIKit
I have a text editor where I replace the selected text when a button is tapped. Most of the time it works, but sometimes the new text is inserted at the end of the text instead of at the selected position. Is this a bug?
@Bindable var note: Richnote
@State private var selection = AttributedTextSelection()
var body: some View {
VStack {
TextEditor(text: $note.content, selection: $selection)
Button("Replace text") {
let textToInsert = "A long text that makes me think lalala"
note.content.replaceSelection(&selection, withCharacters: textToInsert)
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
I just found a weird bug:
If you place a Text view using .foregroundStyle(.secondary), .tertiary, or other semantic colors inside a ScrollView, and apply a Material background clipped to an UnevenRoundedRectangle, the text becomes invisible. This issue does not occur when:
The text uses .primary or explicit colors (e.g., .red, Color.blue), or
The background is clipped to a standard shape (e.g., RoundedRectangle).
A minimal reproducible example is shown below:
ScrollView{
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello World.")
.font(.system(size: 15))
.foregroundStyle(.quinary)
}
}
.padding()
.frame(height: 100)
.background(Material.regular)
.clipShape(UnevenRoundedRectangle(topLeadingRadius: 10,bottomLeadingRadius: 8,bottomTrailingRadius:8, topTrailingRadius: 8))
I have (had) a view controller that does a bit of manual layout in a -viewDidLayout override.
This was pretty easy to manage - however since introducing NSGlassEffectView into the view hierarchy I sometimes am getting hit with "Unable to simultaneously satisfy constraints" and Appkit would break a constraint to 'recover.' It appears translatesAutoresizingMaskIntoConstraints is creating some really weird fixed width and height constraints. Here I wasn't doing any autolayout - just add the glass view and set its frame in -viewDidLayout.
At runtime since I do manual layout in -viewDidLayout the frames are fixed and there is no real "error" in my app in practice though I wanted to get rid of the constraint breaking warning being logged because I know Autolayout can be aggressive about 'correctness' who knows if they decide to throw and not catch in the future.
In my perfect world I would probably just prefer a view.doesManualLayout = YES here - the subviews are big containers no labels so localization is not an issue for me. Rather than playing with autoresizing masks to get better translated constraints I decided to set translatesAutoresizingMaskIntoConstraints to NO and make the constraints myself. Now I get hit with the following exception:
"The window has been marked as needing another Layout Window pass, but it has already had more Layout Window passes than there are views in the window"
So this happens because the view which now has constraints -- I adjusted the frame of it one point in -viewDidLayout. My question is - is not legal to make changes in -viewDidLayout - which seems like the AppKit version of -viewDidLayoutSubviews.
In UIKit I always thought it was fine to make changes in -viewDidLayoutSubviews to frames - even if constraints were used - this is a place where you could override things in complex layouts that cannot be easily described in constraints. But in AppKit if you touch certain frames in -viewDidLayout it can now cause this exception (also related: https://developer.apple.com/forums/thread/806471)
I will change the constant of one of the constraints to account for the 1 point adjustment but my question still stands - is it not legal to touch frames in -viewDidLayout when autolayout constraints are used on that subview? It is (or at least was if I remember correctly) permitted to change the layout in -viewDidLayoutSubviews in UIKit but AppKit seems to be more aggressive in its checking for layout correctness).
What about calling -sizeToFit on a control in viewDidLayout or some method that has side effect of invalidating layout in a non obvious way, is doing things like this now 'dangerous?'
Shouldn't AppKit just block the layout from being invalidated from within -viewDidLayout - and leave whatever the layout is as is when viewDidLayout returns (thus making -viewDidLayout a useful place to override layout in the rare cases where you need a sledgehammer?)