Mac Catalyst

RSS for tag

Start building a native Mac app from your current iPad app using Mac Catalyst.

Posts under Mac Catalyst tag

200 Posts

Post

Replies

Boosts

Views

Activity

WebGL linkProgram fails for every program in a Mac Catalyst WKWebView on macOS 27.3 beta
On macOS 27.3 beta (26C5035r), WebGL draws nothing in a WKWebView in a Mac Catalyst app. A WebGL2 context is created and shaders pass COMPILE_STATUS, but linkProgram fails for every program, with LINK_STATUS false and an empty program log. The same source file draws when built for My Mac. The same page also draws in Safari 27.3 and in the iOS 27.0 Simulator. Only the Mac Catalyst build fails. To reproduce, run a trivial vertex and fragment shader pair in a WKWebView, built for My Mac (Mac Catalyst): LINK_STATUS: false program log: "" pixel: 0, 0, 0, 0 getError: 1282 The unified log for the Catalyst app's com.apple.WebKit.GPU process shows this for each shader: (Metal) Metal Compiling Shader (Metal) Compiler failed to build request MTLCompilerService logs "Compilation BEGIN" for each request, then no "Compilation SUCCESS". The Metal source from WEBGL_debug_shaders is byte-identical in the Mac and Catalyst views, and with ANGLE's link placeholders filled in by hand it compiles in a Catalyst process, so the failure seems specific to the Catalyst GPU process. Signing, app sandbox, hardened runtime and a new bundle identifier make no difference. A macOS bundle loaded into the Catalyst process does not help, because its WKWebView is the Catalyst one. Sketchy Workaround: run the page in an AppKit WKWebView in a separate macOS helper process. FB25444425
0
0
29
5h
Mac Catalyst: outgoing CallKit call opens FaceTime and turns on the camera
We're bringing our CallKit-based VoIP app to the Mac with Mac Catalyst. Incoming calls work fine. For outgoing calls we request a CXStartCallAction (audio only, isVideo = false), the provider fulfills it and the call connects. But at the moment the call starts dialing, macOS launches FaceTime.app, which turns on the camera preview and shows its own call screen for our call ("no video"). When the call ends, FaceTime stays open and the camera stays on until FaceTime is quit manually. The system log shows callservicesd deciding to launch the in-call application for our call: callservicesd _shouldLaunchInCallApplicationForCall: 1 callservicesd Opening URL: <private> for call <private> CoreServicesUIAgent LAUNCH: ... com.apple.FaceTime starting stopped process.Reported as FB25284357 (macOS 27.0.1, Xcode 27.1). Is this expected for third-party CallKit providers on macOS? Is there a supported way to keep the call in our own app without dropping CallKit for outgoing calls?
2
0
121
1d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
3
0
477
4d
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
0
0
107
1w
IOServiceAuthorize and USB device redirection on Mac Catalyst
Dear Apple Developer Support, We develop a Mac Catalyst app that has the com.apple.vm.device-access entitlement. We are now able to redirect USB devices to a remote virtual machine using the SPICE remote desktop protocol. We have run into a case where the only working solution we have found depends on an API that the SDK marks as unavailable for Mac Catalyst. We would like to understand the supported approach before submitting a build for review. The app uses libusb's Darwin backend to capture a USB device before redirecting it. The capture sequence is the standard one: IOServiceAuthorize(service, kIOServiceInteractionAllowed) USBDeviceReEnumerate(device, kUSBReEnumerateCaptureDeviceMask) USBDeviceOpenSeize, then USBInterfaceOpen on the captured device A) Behaviour without step 1 IOKitLib.h annotates IOServiceAuthorize with __API_UNAVAILABLE(ios, macCatalyst), so our first implementation skipped it on Catalyst and went straight to the capture re-enumeration. In that configuration: The entitlement is present and readable via SecTaskCopyValueForEntitlement. USBDeviceReEnumerate with kUSBReEnumerateCaptureDeviceMask returns kIOReturnSuccess. The device does re-enumerate — it disappears and reappears on the host, and its volumes are unmounted. The kernel drivers then re-attach, and the following USBInterfaceOpen fails with kIOReturnExclusiveAccess ("another process has device opened for exclusive access"). The capture reports success but does not actually take the device away from the system's drivers. This is reproducible with a USB mass-storage device (a flash drive with a mounted volume). B) Behaviour with step 1 If IOServiceAuthorize is called before the re-enumeration, capture works correctly and USB redirection functions as expected. To call it from a Catalyst target we had to work around the availability annotation by binding the symbol directly: extern kern_return_t my_service_authorize(io_service_t service, uint32_t options) asm("_IOServiceAuthorize"); This compiles, links and runs. We note that IOKit.tbd in the macOS SDK exports _IOServiceAuthorize for the arm64-maccatalyst and x86_64-maccatalyst targets, which is why it links. Our questions are as follows: With com.apple.vm.device-access granted, what is the supported way to authorize USB device capture from a Mac Catalyst app? If IOServiceAuthorize is the intended mechanism, is calling it from Catalyst as shown above acceptable for App Store review, given the __API_UNAVAILABLE(macCatalyst) annotation on its declaration? If it is not acceptable, is there a Catalyst-available equivalent? Or is the entitlement expected to make USBDeviceReEnumerate(kUSBReEnumerateCaptureDeviceMask) sufficient on its own? If the latter is the intent, the behaviour described above suggests it is not currently sufficient, and we would be glad to file a bug report with a reproducible case. We would rather not ship an API usage that could be read as circumventing a platform availability annotation, which is why we are asking before submitting. Thank you, Morpheusly Inc. development team
3
0
871
2w
App-level volume for MusicKit ApplicationMusicPlayer on Mac Catalyst
Our music player plays library and Apple Music catalog content with MusicKit's ApplicationMusicPlayer. On the Mac, we want a volume slider that changes only our app's playback level, like the slider in Music.app. We found no supported way to do this: ApplicationMusicPlayer and MusicPlayer have no volume property. The audio plays in com.apple.MediaPlayer.RemotePlayerService, not in our process, so we cannot change the stream level. MPVolumeView and the deprecated MPMusicPlayerController.volume control the system output volume, not the app's level. AVPlayer cannot play Apple Music catalog content. Questions: Is there a supported API to set the playback volume of ApplicationMusicPlayer on macOS or Mac Catalyst? If there is none, what does Apple recommend for Mac apps that need an app-level volume control for MusicKit playback?
2
0
757
3w
On-screen RealityView starves CADisplayLink to 30 Hz on ProMotion (Mac Catalyst)
FB24536235 On Mac Catalyst under macOS 27, a plain CADisplayLink asking for CAFrameRateRange(minimum: 60, maximum: 60, preferred: 60) gets serviced at 30 Hz for as long as a RealityView is on screen in the same window. The link does nothing per tick but count, so there's nothing of mine to blame it on. RealityKit's own statistics overlay reads 60.41 fps in the same frame. Click a segmented control that removes the RealityView and the same link goes straight back to 60. Nothing else changes. That's the whole reproducer, and I've attached it to the radar. It only happens while the display panel is in ProMotion mode. Set the built-in to a fixed 60 Hz and it's correct again. With an external 60 Hz display attached the roles swap: the built-in is fine and the external drops to somewhere between 18 and 30, and setting the built-in to 60 Hz fixes that one too without touching the external's own settings. A raw MTKView presenting continuously at 60, at 120, and on a 120 Hz link presenting every second callback are all fine, so it isn't continuous presentation and it isn't the requested rate. It's RealityKit specifically. Worth knowing if you're testing: RealityView on Catalyst is an ARView underneath, so both paths give you the same answer. This is VERY rough for anything that puts RealityKit next to a UI. In an editor that's the sidebar, the inspector, gizmos, drag handles, every display-link-driven or UIKit animation in the window running at half rate around a viewport that stays smooth. Likely Related to FB24091347, which is the same defect seen as SwiftUI scroll judder. If you can reproduce either, please file a duplicate. Attached two screenshots; first with promotion enabled, second with promotion off. PLEASE fix this, it drives me crazy and there seems to be no workaround. On release day of macOS 27 our app will likely be blamed for it by users and my hands are tied. Thank you!
2
1
1.3k
3w
AVSpeechSynthesizer Enhanced voices produce silent audio in sandboxed Mac Catalyst app
I have reproduced an issue with AVSpeechSynthesizer on macOS 26.6.2 (25G83) using a minimal Mac Catalyst application. Environment macOS 26.6.2 (25G83) Apple Silicon Xcode 26.x Mac Catalyst AVSpeechSynthesizer Enhanced voice: com.apple.voice.enhanced.en-GB.Daniel The problem is specifically related to App Sandbox. Reproduction I created a completely new minimal Mac Catalyst application. With App Sandbox disabled: let synthesizer = AVSpeechSynthesizer() let utterance = AVSpeechUtterance(string: "Hello, this is a test.") utterance.voice = AVSpeechSynthesisVoice(identifier: "com.apple.voice.enhanced.en-GB.Daniel") synthesizer.speak(utterance) The Enhanced voice works normally. With App Sandbox enabled, with no other sandbox capabilities enabled, the same code no longer produces audible speech.
3
0
1.1k
Sep ’26
ToolbarItem(placement: .topBarPinnedTrailing) is not shown if it is the only toolbar element.
If .topBarPinnedTrailing is used for the placement of a ToolbarItem, if this item is the only one in the toolbar then it is not displayed. This .topBarPinnedTrailing appeared in iOS 27.0 to allow a button to be always visible in the toolbar if when there are overflows with many buttons in the toolbar. A toolbar button should always be visible, this behaviour is a bug. It is a great issue on iPhone Duo which has less space for buttons in the toolbars, this attribute was designed to be sure the button using this attribute would always be visible. Bug is also there on Mac Catalyst and visionOS. A feedback was created FB24882292 /// Shows a View with a toolbar with a .topBarPinnedTrailing button. /// If the tool is the only one, it is not displayed. It is designed to be always visible, but it can be missing on the screen. /// If there are one or more additional buttons, then the .topBarPinnedTrailing is well displayed. /// /// Bug reproduced on iPhone 18 Pro Max simulator 27.0, iPhone Duo simulator iOS 27.1, /// Mac Catalyst 27.0, Vision Pro simulator visionOS 27.0 /// > Warning : to test this ContentView, embed it in a NavigationStack. struct ContentView: View { @State private var twoButtons = false var body: some View { VStack { Text("A toolbar should be always visible") .padding() Button { twoButtons.toggle() } label: { Text(twoButtons ? "Remove second tool" : "Add second tool") } } .toolbar { // ‼️ this button is missing if it is the only one. // ‼️ This is due to .topBarPinnedTrailing which makes it disappear if it is alone. ToolbarItem(placement: .topBarPinnedTrailing) { Button { print("topBarPinnedTrailing pressed") } label: { Label { Text("topBarPinnedTrailing") } icon: { Image(systemName: "ladybug.fill") } .labelStyle(.iconOnly) } } if twoButtons { ToolbarItem(placement: .topBarTrailing) { Button { //Barre d'icône ajouter une scène print("topBarLeading pressed") twoButtons = false } label: { Label { Text("topBarLeading") } icon: { Image(systemName: "minus") } .labelStyle(.iconOnly) } } } } } }
3
0
698
Sep ’26
Bottom toolbar Button truncated on Mac Catalyst 26
On Mac Catalyst 26, a Button bar item in a bottom toolbar look squished. This happens only when the "Mac Catalyst Interface" option is set to "Optimize for Mac". When it is set to "Scale to match iPad", the buttons look fine. For example, in the screenshots below, the text button should say "Press Me", instead of "…" A simple reproducible snippet and a screenshot below. The toolbar button comparison between "Scale to match iPad" and "Optimize for Mac" are shown. Optimize for Mac Scale to match iPad import SwiftUI struct ContentView: View { @State private var selectedItem: String? = "Item 1" let items = ["Item 1", "Item 2"] var body: some View { NavigationSplitView { List(items, id: \.self, selection: $selectedItem) { item in Text(item) } .navigationTitle("Items") } detail: { if let selectedItem = selectedItem { Text("Detail view for \(selectedItem)") .toolbar { ToolbarItemGroup(placement: .bottomBar) { Text("Hello world") Spacer() Button("Press Me") { } Spacer() Button { } label: { Image(systemName: "plus") .imageScale(.large) } } } } else { Text("Select an item") } } } }
4
3
1.9k
Aug ’26
MacCatalyst and Image of AppIcon
In my apps, I have a requirement to display an image of the application icon is certain circumstances. This is fairly straightforward for iOS/iPadOS and it used to be straightforward for macCatalyst. For MacCatalyst, this is no longer true (at least since macOS 26). This is because the app icon is now stored as an .icns file and (in the case of using an IconComposer icon), the `'png' in the Asset Catalog now has an unknown name. So the following code no longer works: public extension Bundle { var icon: UIImage? { #if targetEnvironment(macCatalyst) guard let iconName = infoDictionary?["CFBundleIconName"] as? String else { return nil } return UIImage(named: iconName, in: self, compatibleWith: nil) #else guard let icons = infoDictionary?["CFBundleIcons"] as? [String : Any] else { return nil } guard let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String : Any] else { return nil } guard let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String] else { return nil } guard let file = iconFiles.last else { return nil } return UIImage(named: file, in: self, compatibleWith: nil) #endif } The obvious solution is to place an Image in the Asset Catalog which I can access, but this is a maintenance headache. What I would actually like to do is either create a UIImage directly from the .icns file, or access the .png file in the Asset Catalog (which has a name beginning with the icon file name, but has additional characters in its name that I don't know). Can you help?
3
0
1.2k
Aug ’26
macOS 27 Catalyst: WKWebView text entry impossible, endless keyboard input-view focus loop
Filed as FB24092251. On macOS 27.0 beta (26A5388g), clicking into any text input inside a WKWebView in a Mac Catalyst app makes focus oscillate forever and typing does nothing. CPU pegs at 100% while the editor is focused. The same binary works fine on macOS 26. The DOM element never actually loses focus. Only the window does: window focus -> activeElement=TEXTAREA.inputarea JS focus -> activeElement=TEXTAREA.inputarea window blur -> activeElement=TEXTAREA.inputarea <- window loses key status JS blur -> activeElement=TEXTAREA.inputarea <- element did not ...repeats indefinitely... Pausing during the loop shows why. Focusing the element sends WebKit into UIKit's software-keyboard machinery, on a platform that has no software keyboard: -[UIKeyboardSceneDelegate containerWindowForViewService:] -[UIKeyboardSceneDelegate _setKeyWindowSceneInputViews:animationStyle:] -[UIKeyboardSceneDelegate _reloadInputViewsForResponder:force:fromBecomeFirstResponder:] -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] -[WKContentView(WKInteraction) _continueElementDidFocus:...] -[WKContentView(WKInteraction) _elementDidFocus:...] WebKit::WebPageProxy::elementDidFocus(...) Building that container steals key status from the web view. First responder ends up on the enclosing _UIHostingView, so key presses are delivered there and immediately cancelled: pressesBegan: [...], focusedItem: monacoEditor firstResponder at keypress: _UIHostingView<...> pressesCancelled: [...] The catch: -becomeFirstResponder cannot be used to recover, because it is the trigger. Calling it re-enters _elementDidFocus and re-arms the loop permanently. So there is no app-side way back — the only API that reclaims the keyboard is the one that breaks it. Minimal repro is just a WKWebView in a UIViewRepresentable inside a SwiftUI hierarchy, with any focusable . No Monaco needed. Partial mitigation, if you hit this: do not echo focus/blur commands back at the web view in response to its own focus events, and treat a blur where document.hasFocus() is false but activeElement is unchanged as a window-level blur rather than an editing-ended event. That stops the runaway loop and keeps your focus state correct — but it does not restore typing. Has anyone found a way to get first responder back to the web view without calling -becomeFirstResponder? Or a way to stop the keyboard scene delegate engaging on Catalyst in the first place? If you can reproduce on 27 beta, please file a duplicate referencing FB24092251.
1
0
1.1k
Aug ’26
TextComponent Renders Inverted Text on Mac Catalyst
On Mac Catalyst, RealityKit TextComponent renders vertically inverted text. The issue occurs with both ARView and RealityView. The same text renders correctly on iOS and in a native macOS RealityView application (not Catalyst). Tested on macOS 26 and macOS 27 beta, with Xcode 26 and Xcode 27 Beta. Here is a screenshot of a text entity with a text component rendering the string "Text Component": Workaround On Mac Catalyst: Detect when the model generated by TextComponent becomes available on the text entity. Find the generated UnlitMaterial in the ModelComponent of the text entity. Disable face culling on the material. Invert the Y scale of the text entity. Here is the result: Reproduce Below is the full code that reproduces the problem, with both ARView and RealityView, as well as the workaround implementation. import SwiftUI import RealityKit import Combine // MARK: Text func createTextEntity() -> Entity { let textEntity = Entity() let attributes: [NSAttributedString.Key: Any] = [ .font: MeshResource.Font.systemFont(ofSize: 48, weight: .bold), .foregroundColor: Material.Color.white ] let attributedText = AttributedString( NSAttributedString( string: "Text Component", attributes: attributes ) ) var textComponent = TextComponent() textComponent.text = attributedText textComponent.size = CGSize(width: 400, height: 200) textComponent.backgroundColor = Material.Color.darkGray.cgColor textEntity.components.set(textComponent) return textEntity } // MARK: Camera func createCameraEntity() -> Entity { let cameraEntity = Entity() cameraEntity.components.set(PerspectiveCameraComponent()) cameraEntity.look(at: .zero, from: [0, 0, 0.3], relativeTo: nil) return cameraEntity } // MARK: ARView struct CatalystTextBugARView: UIViewRepresentable { let applyWorkaround: Bool = true func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) arView.cameraMode = .nonAR arView.automaticallyConfigureSession = false arView.environment.background = .color(.black) let rootEntity = AnchorEntity() let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes context.coordinator.modelDidAddSubscription = arView.scene.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } context.coordinator.modelDidChangeSubscription = arView.scene.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif rootEntity.addChild(textEntity) rootEntity.addChild(createCameraEntity()) arView.scene.addAnchor(rootEntity) return arView } func updateUIView(_ uiView: ARView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { /// Retain the scene subscriptions for the lifetime of the ARView. var modelDidAddSubscription: (any Cancellable)? var modelDidChangeSubscription: (any Cancellable)? } } // MARK: RealityView struct CatalystTextBugRealityView: View { let applyWorkaround: Bool = true /// Retain the RealityView subscriptions for the lifetime of the view. @State private var modelDidAddSubscription: EventSubscription? @State private var modelDidChangeSubscription: EventSubscription? var body: some View { RealityView { content in let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes. modelDidAddSubscription = content.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } modelDidChangeSubscription = content.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif content.add(textEntity) content.add(createCameraEntity()) } .background(.black) } } // MARK: Workaround func applyTextBugWorkaround(to textEntity: Entity) { #if targetEnvironment(macCatalyst) guard var modelComponent = textEntity.components[ModelComponent.self] else { return } var foundTextMaterial = false var changedMaterial = false for materialIndex in modelComponent.materials.indices { guard var textMaterial = modelComponent.materials[materialIndex] as? UnlitMaterial else { continue } foundTextMaterial = true /// If face culling is already disabled, skip if case .none = textMaterial.faceCulling { continue } textMaterial.faceCulling = .none modelComponent.materials[materialIndex] = textMaterial changedMaterial = true } guard foundTextMaterial else { return } if changedMaterial { textEntity.components.set(modelComponent) } /// Counteract vertically inverted text. textEntity.scale.y = -abs(textEntity.scale.y) #endif } Usage Run either CatalystTextBugRealityView() or CatalystTextBugARView() on a Mac Catalyst target. Toggle applyWorkaround on either view to try with and without the workaround.
1
0
967
Aug ’26
macOS Tahoe 26.5.1: Mac Catalyst App Crashes at Launch with EXC_BREAKPOINT in libsystem_secinit due to Container Integrity Check Failure
After updating the application following an upgrade from a previous macOS version to macOS Tahoe 26.5.1 (25F80), the sandboxed app immediately crashes on launch. The crash occurs during dyld library initialization, before any application code (including main()) is executed. The crash report identifies that libsystem_secinit.dylib rejects the existing app sandbox container with the following signature: "failed integrity checks for container at /Users/apptest/Library/Containers/77C6DBAA-6E54-4ED4-947C-5C5648BE280B/Data: Invalid argumen" Clearing out the old sandbox container data (e.g., rm -rf ~/Library/Containers/77C6DBAA-6E54-4ED4-947C-5C5648BE280B/Data) resolves the crash. Please help analyze the possible causes of this issue: 1.Could this be a compatibility issue between the new macOS 26.5.1 system and Mac Catalyst apps? 2.Could this be caused by certain APIs used by the app or specific project configuration settings? If so, please provide some relevant hints to help narrow down the scope of analysis. Crash Log excerpt.txt
6
0
1.1k
Jul ’26
Mac Catalyst app built with Xcode 27 beta 3 crashes at launch on macOS 26.5.1 — dyld "Symbol not found: _UIFontTextStyleBody" expected in AppKit
My Mac Catalyst app (distributed via TestFlight) crashes instantly at launch — before main() — on macOS 26.5.1 (25F80) when archived with Xcode 27 beta 3. The same code archived with Xcode 26.5 (GA) launches fine. Crash excerpt: Termination Reason: Namespace DYLD, Code 4, Symbol missing Symbol not found: _UIFontTextStyleBody Referenced from: <...> /Applications/Paku.app/Contents/MacOS/Paku Expected in: <...> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (terminated at launch; ignore backtrace) What appears to be happening The symbol comes from completely ordinary UIKit code — e.g. UIFont.preferredFont(forTextStyle: .body). When linking with the Xcode 27 beta 3 SDK, the two-level namespace bind for _UIFontTextStyleBody in my binary points at AppKit, i.e. the beta SDK's AppKit.tbd declares (re-exports) the UIKit text-style constants for Catalyst. But the shipping OS doesn't provide that: on macOS 26.5.1, _UIFontTextStyleBody is absent from both the installed AppKit binary (checked with dyld_info -exports /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit) and the Xcode 26.5 GA SDK's AppKit.tbd. So any binary linked against the beta SDK hard-binds the symbol to AppKit and then fatally fails to bind on current GA macOS — a 100%-reproducible launch crash for every user not on the macOS 27 beta. Steps to reproduce Mac Catalyst target that uses any UIFont.TextStyle constant (e.g. .preferredFont(forTextStyle: .body)). Archive with Xcode 27 beta 3 and distribute via TestFlight. Launch on macOS 26.5.1 → immediate dyld abort with the report above. Questions Is this a known issue with the macOS 27 beta SDK's AppKit re-export list? It looks like these UIKit constants are being moved/re-exported through AppKit in the 27 cycle, but without availability/weak-linking info that would let binaries back-deploy to macOS 26. Is the intended behavior that Catalyst apps built with the 27 beta SDK simply can't run on macOS 26? If so, should App Store Connect / TestFlight have rejected or flagged the upload?
0
2
645
Jul ’26
Request photo library authorization popup on macOS Catalyst can't be dismissed
I have an iOS app that I want to publish to the Mac App Store as a Catalyst app, but I noticed a situation where the app can't be closed and has to be force quit. The problem happens if the user has 0 photos in their Photo Library, and hits "Limited Access" on the request authorization prompt (In my case PHPhotoLibrary.requestAuthorization(for: .readWrite). Since the popup is a system prompt, I can't manually add a close button to it. I tried wrapping it in a view with a close button but the popup always shows up over any view I'm presenting within my app. If anyone has a workaround that would be greatly appreciated!
2
0
967
Jul ’26
WebGL linkProgram fails for every program in a Mac Catalyst WKWebView on macOS 27.3 beta
On macOS 27.3 beta (26C5035r), WebGL draws nothing in a WKWebView in a Mac Catalyst app. A WebGL2 context is created and shaders pass COMPILE_STATUS, but linkProgram fails for every program, with LINK_STATUS false and an empty program log. The same source file draws when built for My Mac. The same page also draws in Safari 27.3 and in the iOS 27.0 Simulator. Only the Mac Catalyst build fails. To reproduce, run a trivial vertex and fragment shader pair in a WKWebView, built for My Mac (Mac Catalyst): LINK_STATUS: false program log: "" pixel: 0, 0, 0, 0 getError: 1282 The unified log for the Catalyst app's com.apple.WebKit.GPU process shows this for each shader: (Metal) Metal Compiling Shader (Metal) Compiler failed to build request MTLCompilerService logs "Compilation BEGIN" for each request, then no "Compilation SUCCESS". The Metal source from WEBGL_debug_shaders is byte-identical in the Mac and Catalyst views, and with ANGLE's link placeholders filled in by hand it compiles in a Catalyst process, so the failure seems specific to the Catalyst GPU process. Signing, app sandbox, hardened runtime and a new bundle identifier make no difference. A macOS bundle loaded into the Catalyst process does not help, because its WKWebView is the Catalyst one. Sketchy Workaround: run the page in an AppKit WKWebView in a separate macOS helper process. FB25444425
Replies
0
Boosts
0
Views
29
Activity
5h
Mac Catalyst: outgoing CallKit call opens FaceTime and turns on the camera
We're bringing our CallKit-based VoIP app to the Mac with Mac Catalyst. Incoming calls work fine. For outgoing calls we request a CXStartCallAction (audio only, isVideo = false), the provider fulfills it and the call connects. But at the moment the call starts dialing, macOS launches FaceTime.app, which turns on the camera preview and shows its own call screen for our call ("no video"). When the call ends, FaceTime stays open and the camera stays on until FaceTime is quit manually. The system log shows callservicesd deciding to launch the in-call application for our call: callservicesd _shouldLaunchInCallApplicationForCall: 1 callservicesd Opening URL: <private> for call <private> CoreServicesUIAgent LAUNCH: ... com.apple.FaceTime starting stopped process.Reported as FB25284357 (macOS 27.0.1, Xcode 27.1). Is this expected for third-party CallKit providers on macOS? Is there a supported way to keep the call in our own app without dropping CallKit for outgoing calls?
Replies
2
Boosts
0
Views
121
Activity
1d
UITableView row reordering no longer works under macOS 27 with Mac Catalyst
Under macOS 27 using Mac Catalyst for a UIKit-based app, If you present a view controller with a table view as a form sheet or page sheet, row reordering fails to function. You can drag a row as expected but the blue movement bar never appears and if you drop the row it simply returns to its original location. The exact same view controller presented as a popover works just fine. The exact same view controller not presented as a modal (such as the app's root controller) works just fine. This is a serious bug affecting existing applications and being reported by paying customers. This has been reported as FB25038883 which includes a simple sample app demonstrating the issue.
Replies
3
Boosts
0
Views
477
Activity
4d
State Restoration no longer works in a Mac Catalyst based app when run on macOS 27.x
As reported in FB25363417: A UIKit based app running on macOS 27.2 (or macOS 27.0.1) via Mac Catalyst no longer has functioning state restoration. Upon app restart, there is no NSUserActivity being provided to the scene in the UISceneDelegate method scene(_:willConnectTo:options:). This can be tested with Apple’s own sample app “Restoring your app’s state”. Just update the sample project with support for a Mac Catalyst build. Using Xcode 27.2 on a Mac with macOS 27.0 or 27.2, build and run the Mac Catalyst version of the app. The main screen appears with a list of products. Select any product so you see details of the product. Quit the app. Run the app again. Note that you are not returned to the previously selected product detail screen. Instead, you just see the main list of products. If you run the same app and perform the same steps on a Mac running macOS 26.x, then when the app is restarted, you correctly get returned to the previously selected product detail screen. The problem is being caused by no NSUserActivity being passed into the scene delegate on app startup. While running the app on a Mac with macOS 27.x, put a breakpoint on the initial guard statement in scene(_:willConnectTo:options:) and you will see there is no activity on app restart. This is impacting paid customers of my existing app since upgrading to macOS 27. They no longer get returned to the app’s previous state when restarting the app. It is expected that state restoration should work on macOS 27 just as well as it does under macOS 26 in an app built with Mac Catalyst.
Replies
0
Boosts
0
Views
107
Activity
1w
IOServiceAuthorize and USB device redirection on Mac Catalyst
Dear Apple Developer Support, We develop a Mac Catalyst app that has the com.apple.vm.device-access entitlement. We are now able to redirect USB devices to a remote virtual machine using the SPICE remote desktop protocol. We have run into a case where the only working solution we have found depends on an API that the SDK marks as unavailable for Mac Catalyst. We would like to understand the supported approach before submitting a build for review. The app uses libusb's Darwin backend to capture a USB device before redirecting it. The capture sequence is the standard one: IOServiceAuthorize(service, kIOServiceInteractionAllowed) USBDeviceReEnumerate(device, kUSBReEnumerateCaptureDeviceMask) USBDeviceOpenSeize, then USBInterfaceOpen on the captured device A) Behaviour without step 1 IOKitLib.h annotates IOServiceAuthorize with __API_UNAVAILABLE(ios, macCatalyst), so our first implementation skipped it on Catalyst and went straight to the capture re-enumeration. In that configuration: The entitlement is present and readable via SecTaskCopyValueForEntitlement. USBDeviceReEnumerate with kUSBReEnumerateCaptureDeviceMask returns kIOReturnSuccess. The device does re-enumerate — it disappears and reappears on the host, and its volumes are unmounted. The kernel drivers then re-attach, and the following USBInterfaceOpen fails with kIOReturnExclusiveAccess ("another process has device opened for exclusive access"). The capture reports success but does not actually take the device away from the system's drivers. This is reproducible with a USB mass-storage device (a flash drive with a mounted volume). B) Behaviour with step 1 If IOServiceAuthorize is called before the re-enumeration, capture works correctly and USB redirection functions as expected. To call it from a Catalyst target we had to work around the availability annotation by binding the symbol directly: extern kern_return_t my_service_authorize(io_service_t service, uint32_t options) asm("_IOServiceAuthorize"); This compiles, links and runs. We note that IOKit.tbd in the macOS SDK exports _IOServiceAuthorize for the arm64-maccatalyst and x86_64-maccatalyst targets, which is why it links. Our questions are as follows: With com.apple.vm.device-access granted, what is the supported way to authorize USB device capture from a Mac Catalyst app? If IOServiceAuthorize is the intended mechanism, is calling it from Catalyst as shown above acceptable for App Store review, given the __API_UNAVAILABLE(macCatalyst) annotation on its declaration? If it is not acceptable, is there a Catalyst-available equivalent? Or is the entitlement expected to make USBDeviceReEnumerate(kUSBReEnumerateCaptureDeviceMask) sufficient on its own? If the latter is the intent, the behaviour described above suggests it is not currently sufficient, and we would be glad to file a bug report with a reproducible case. We would rather not ship an API usage that could be read as circumventing a platform availability annotation, which is why we are asking before submitting. Thank you, Morpheusly Inc. development team
Replies
3
Boosts
0
Views
871
Activity
2w
App-level volume for MusicKit ApplicationMusicPlayer on Mac Catalyst
Our music player plays library and Apple Music catalog content with MusicKit's ApplicationMusicPlayer. On the Mac, we want a volume slider that changes only our app's playback level, like the slider in Music.app. We found no supported way to do this: ApplicationMusicPlayer and MusicPlayer have no volume property. The audio plays in com.apple.MediaPlayer.RemotePlayerService, not in our process, so we cannot change the stream level. MPVolumeView and the deprecated MPMusicPlayerController.volume control the system output volume, not the app's level. AVPlayer cannot play Apple Music catalog content. Questions: Is there a supported API to set the playback volume of ApplicationMusicPlayer on macOS or Mac Catalyst? If there is none, what does Apple recommend for Mac apps that need an app-level volume control for MusicKit playback?
Replies
2
Boosts
0
Views
757
Activity
3w
On-screen RealityView starves CADisplayLink to 30 Hz on ProMotion (Mac Catalyst)
FB24536235 On Mac Catalyst under macOS 27, a plain CADisplayLink asking for CAFrameRateRange(minimum: 60, maximum: 60, preferred: 60) gets serviced at 30 Hz for as long as a RealityView is on screen in the same window. The link does nothing per tick but count, so there's nothing of mine to blame it on. RealityKit's own statistics overlay reads 60.41 fps in the same frame. Click a segmented control that removes the RealityView and the same link goes straight back to 60. Nothing else changes. That's the whole reproducer, and I've attached it to the radar. It only happens while the display panel is in ProMotion mode. Set the built-in to a fixed 60 Hz and it's correct again. With an external 60 Hz display attached the roles swap: the built-in is fine and the external drops to somewhere between 18 and 30, and setting the built-in to 60 Hz fixes that one too without touching the external's own settings. A raw MTKView presenting continuously at 60, at 120, and on a 120 Hz link presenting every second callback are all fine, so it isn't continuous presentation and it isn't the requested rate. It's RealityKit specifically. Worth knowing if you're testing: RealityView on Catalyst is an ARView underneath, so both paths give you the same answer. This is VERY rough for anything that puts RealityKit next to a UI. In an editor that's the sidebar, the inspector, gizmos, drag handles, every display-link-driven or UIKit animation in the window running at half rate around a viewport that stays smooth. Likely Related to FB24091347, which is the same defect seen as SwiftUI scroll judder. If you can reproduce either, please file a duplicate. Attached two screenshots; first with promotion enabled, second with promotion off. PLEASE fix this, it drives me crazy and there seems to be no workaround. On release day of macOS 27 our app will likely be blamed for it by users and my hands are tied. Thank you!
Replies
2
Boosts
1
Views
1.3k
Activity
3w
Cannot run Catalyst app on other devices?!?
I prepare a private project in Xcode, use Archive, Distribute/Copy, save the application somewhere. Copy it to my other computer, run. Works perfectly with normal MacOS applications. With Catalyst ones though it does not; whatever I try, all I get is “The application XXX cannot be opened”. What do I do wrong and how to fix the problem? Thanks!
Replies
8
Boosts
0
Views
542
Activity
Oct ’26
AVSpeechSynthesizer Enhanced voices produce silent audio in sandboxed Mac Catalyst app
I have reproduced an issue with AVSpeechSynthesizer on macOS 26.6.2 (25G83) using a minimal Mac Catalyst application. Environment macOS 26.6.2 (25G83) Apple Silicon Xcode 26.x Mac Catalyst AVSpeechSynthesizer Enhanced voice: com.apple.voice.enhanced.en-GB.Daniel The problem is specifically related to App Sandbox. Reproduction I created a completely new minimal Mac Catalyst application. With App Sandbox disabled: let synthesizer = AVSpeechSynthesizer() let utterance = AVSpeechUtterance(string: "Hello, this is a test.") utterance.voice = AVSpeechSynthesisVoice(identifier: "com.apple.voice.enhanced.en-GB.Daniel") synthesizer.speak(utterance) The Enhanced voice works normally. With App Sandbox enabled, with no other sandbox capabilities enabled, the same code no longer produces audible speech.
Replies
3
Boosts
0
Views
1.1k
Activity
Sep ’26
ToolbarItem(placement: .topBarPinnedTrailing) is not shown if it is the only toolbar element.
If .topBarPinnedTrailing is used for the placement of a ToolbarItem, if this item is the only one in the toolbar then it is not displayed. This .topBarPinnedTrailing appeared in iOS 27.0 to allow a button to be always visible in the toolbar if when there are overflows with many buttons in the toolbar. A toolbar button should always be visible, this behaviour is a bug. It is a great issue on iPhone Duo which has less space for buttons in the toolbars, this attribute was designed to be sure the button using this attribute would always be visible. Bug is also there on Mac Catalyst and visionOS. A feedback was created FB24882292 /// Shows a View with a toolbar with a .topBarPinnedTrailing button. /// If the tool is the only one, it is not displayed. It is designed to be always visible, but it can be missing on the screen. /// If there are one or more additional buttons, then the .topBarPinnedTrailing is well displayed. /// /// Bug reproduced on iPhone 18 Pro Max simulator 27.0, iPhone Duo simulator iOS 27.1, /// Mac Catalyst 27.0, Vision Pro simulator visionOS 27.0 /// > Warning : to test this ContentView, embed it in a NavigationStack. struct ContentView: View { @State private var twoButtons = false var body: some View { VStack { Text("A toolbar should be always visible") .padding() Button { twoButtons.toggle() } label: { Text(twoButtons ? "Remove second tool" : "Add second tool") } } .toolbar { // ‼️ this button is missing if it is the only one. // ‼️ This is due to .topBarPinnedTrailing which makes it disappear if it is alone. ToolbarItem(placement: .topBarPinnedTrailing) { Button { print("topBarPinnedTrailing pressed") } label: { Label { Text("topBarPinnedTrailing") } icon: { Image(systemName: "ladybug.fill") } .labelStyle(.iconOnly) } } if twoButtons { ToolbarItem(placement: .topBarTrailing) { Button { //Barre d'icône ajouter une scène print("topBarLeading pressed") twoButtons = false } label: { Label { Text("topBarLeading") } icon: { Image(systemName: "minus") } .labelStyle(.iconOnly) } } } } } }
Replies
3
Boosts
0
Views
698
Activity
Sep ’26
Bottom toolbar Button truncated on Mac Catalyst 26
On Mac Catalyst 26, a Button bar item in a bottom toolbar look squished. This happens only when the "Mac Catalyst Interface" option is set to "Optimize for Mac". When it is set to "Scale to match iPad", the buttons look fine. For example, in the screenshots below, the text button should say "Press Me", instead of "…" A simple reproducible snippet and a screenshot below. The toolbar button comparison between "Scale to match iPad" and "Optimize for Mac" are shown. Optimize for Mac Scale to match iPad import SwiftUI struct ContentView: View { @State private var selectedItem: String? = "Item 1" let items = ["Item 1", "Item 2"] var body: some View { NavigationSplitView { List(items, id: \.self, selection: $selectedItem) { item in Text(item) } .navigationTitle("Items") } detail: { if let selectedItem = selectedItem { Text("Detail view for \(selectedItem)") .toolbar { ToolbarItemGroup(placement: .bottomBar) { Text("Hello world") Spacer() Button("Press Me") { } Spacer() Button { } label: { Image(systemName: "plus") .imageScale(.large) } } } } else { Text("Select an item") } } } }
Replies
4
Boosts
3
Views
1.9k
Activity
Aug ’26
MacCatalyst and Image of AppIcon
In my apps, I have a requirement to display an image of the application icon is certain circumstances. This is fairly straightforward for iOS/iPadOS and it used to be straightforward for macCatalyst. For MacCatalyst, this is no longer true (at least since macOS 26). This is because the app icon is now stored as an .icns file and (in the case of using an IconComposer icon), the `'png' in the Asset Catalog now has an unknown name. So the following code no longer works: public extension Bundle { var icon: UIImage? { #if targetEnvironment(macCatalyst) guard let iconName = infoDictionary?["CFBundleIconName"] as? String else { return nil } return UIImage(named: iconName, in: self, compatibleWith: nil) #else guard let icons = infoDictionary?["CFBundleIcons"] as? [String : Any] else { return nil } guard let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String : Any] else { return nil } guard let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String] else { return nil } guard let file = iconFiles.last else { return nil } return UIImage(named: file, in: self, compatibleWith: nil) #endif } The obvious solution is to place an Image in the Asset Catalog which I can access, but this is a maintenance headache. What I would actually like to do is either create a UIImage directly from the .icns file, or access the .png file in the Asset Catalog (which has a name beginning with the icon file name, but has additional characters in its name that I don't know). Can you help?
Replies
3
Boosts
0
Views
1.2k
Activity
Aug ’26
macOS 27 Catalyst: WKWebView text entry impossible, endless keyboard input-view focus loop
Filed as FB24092251. On macOS 27.0 beta (26A5388g), clicking into any text input inside a WKWebView in a Mac Catalyst app makes focus oscillate forever and typing does nothing. CPU pegs at 100% while the editor is focused. The same binary works fine on macOS 26. The DOM element never actually loses focus. Only the window does: window focus -> activeElement=TEXTAREA.inputarea JS focus -> activeElement=TEXTAREA.inputarea window blur -> activeElement=TEXTAREA.inputarea <- window loses key status JS blur -> activeElement=TEXTAREA.inputarea <- element did not ...repeats indefinitely... Pausing during the loop shows why. Focusing the element sends WebKit into UIKit's software-keyboard machinery, on a platform that has no software keyboard: -[UIKeyboardSceneDelegate containerWindowForViewService:] -[UIKeyboardSceneDelegate _setKeyWindowSceneInputViews:animationStyle:] -[UIKeyboardSceneDelegate _reloadInputViewsForResponder:force:fromBecomeFirstResponder:] -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] -[WKContentView(WKInteraction) _continueElementDidFocus:...] -[WKContentView(WKInteraction) _elementDidFocus:...] WebKit::WebPageProxy::elementDidFocus(...) Building that container steals key status from the web view. First responder ends up on the enclosing _UIHostingView, so key presses are delivered there and immediately cancelled: pressesBegan: [...], focusedItem: monacoEditor firstResponder at keypress: _UIHostingView<...> pressesCancelled: [...] The catch: -becomeFirstResponder cannot be used to recover, because it is the trigger. Calling it re-enters _elementDidFocus and re-arms the loop permanently. So there is no app-side way back — the only API that reclaims the keyboard is the one that breaks it. Minimal repro is just a WKWebView in a UIViewRepresentable inside a SwiftUI hierarchy, with any focusable . No Monaco needed. Partial mitigation, if you hit this: do not echo focus/blur commands back at the web view in response to its own focus events, and treat a blur where document.hasFocus() is false but activeElement is unchanged as a window-level blur rather than an editing-ended event. That stops the runaway loop and keeps your focus state correct — but it does not restore typing. Has anyone found a way to get first responder back to the web view without calling -becomeFirstResponder? Or a way to stop the keyboard scene delegate engaging on Catalyst in the first place? If you can reproduce on 27 beta, please file a duplicate referencing FB24092251.
Replies
1
Boosts
0
Views
1.1k
Activity
Aug ’26
TextComponent Renders Inverted Text on Mac Catalyst
On Mac Catalyst, RealityKit TextComponent renders vertically inverted text. The issue occurs with both ARView and RealityView. The same text renders correctly on iOS and in a native macOS RealityView application (not Catalyst). Tested on macOS 26 and macOS 27 beta, with Xcode 26 and Xcode 27 Beta. Here is a screenshot of a text entity with a text component rendering the string "Text Component": Workaround On Mac Catalyst: Detect when the model generated by TextComponent becomes available on the text entity. Find the generated UnlitMaterial in the ModelComponent of the text entity. Disable face culling on the material. Invert the Y scale of the text entity. Here is the result: Reproduce Below is the full code that reproduces the problem, with both ARView and RealityView, as well as the workaround implementation. import SwiftUI import RealityKit import Combine // MARK: Text func createTextEntity() -> Entity { let textEntity = Entity() let attributes: [NSAttributedString.Key: Any] = [ .font: MeshResource.Font.systemFont(ofSize: 48, weight: .bold), .foregroundColor: Material.Color.white ] let attributedText = AttributedString( NSAttributedString( string: "Text Component", attributes: attributes ) ) var textComponent = TextComponent() textComponent.text = attributedText textComponent.size = CGSize(width: 400, height: 200) textComponent.backgroundColor = Material.Color.darkGray.cgColor textEntity.components.set(textComponent) return textEntity } // MARK: Camera func createCameraEntity() -> Entity { let cameraEntity = Entity() cameraEntity.components.set(PerspectiveCameraComponent()) cameraEntity.look(at: .zero, from: [0, 0, 0.3], relativeTo: nil) return cameraEntity } // MARK: ARView struct CatalystTextBugARView: UIViewRepresentable { let applyWorkaround: Bool = true func makeUIView(context: Context) -> ARView { let arView = ARView(frame: .zero) arView.cameraMode = .nonAR arView.automaticallyConfigureSession = false arView.environment.background = .color(.black) let rootEntity = AnchorEntity() let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes context.coordinator.modelDidAddSubscription = arView.scene.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } context.coordinator.modelDidChangeSubscription = arView.scene.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif rootEntity.addChild(textEntity) rootEntity.addChild(createCameraEntity()) arView.scene.addAnchor(rootEntity) return arView } func updateUIView(_ uiView: ARView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator { /// Retain the scene subscriptions for the lifetime of the ARView. var modelDidAddSubscription: (any Cancellable)? var modelDidChangeSubscription: (any Cancellable)? } } // MARK: RealityView struct CatalystTextBugRealityView: View { let applyWorkaround: Bool = true /// Retain the RealityView subscriptions for the lifetime of the view. @State private var modelDidAddSubscription: EventSubscription? @State private var modelDidChangeSubscription: EventSubscription? var body: some View { RealityView { content in let textEntity = createTextEntity() #if targetEnvironment(macCatalyst) if applyWorkaround { /// React when the text entity's ModelComponent becomes available or changes. modelDidAddSubscription = content.subscribe( to: ComponentEvents.DidAdd.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } modelDidChangeSubscription = content.subscribe( to: ComponentEvents.DidChange.self, on: textEntity, componentType: ModelComponent.self ) { _ in applyTextBugWorkaround(to: textEntity) } } #endif content.add(textEntity) content.add(createCameraEntity()) } .background(.black) } } // MARK: Workaround func applyTextBugWorkaround(to textEntity: Entity) { #if targetEnvironment(macCatalyst) guard var modelComponent = textEntity.components[ModelComponent.self] else { return } var foundTextMaterial = false var changedMaterial = false for materialIndex in modelComponent.materials.indices { guard var textMaterial = modelComponent.materials[materialIndex] as? UnlitMaterial else { continue } foundTextMaterial = true /// If face culling is already disabled, skip if case .none = textMaterial.faceCulling { continue } textMaterial.faceCulling = .none modelComponent.materials[materialIndex] = textMaterial changedMaterial = true } guard foundTextMaterial else { return } if changedMaterial { textEntity.components.set(modelComponent) } /// Counteract vertically inverted text. textEntity.scale.y = -abs(textEntity.scale.y) #endif } Usage Run either CatalystTextBugRealityView() or CatalystTextBugARView() on a Mac Catalyst target. Toggle applyWorkaround on either view to try with and without the workaround.
Replies
1
Boosts
0
Views
967
Activity
Aug ’26
macOS Tahoe 26.5.1: Mac Catalyst App Crashes at Launch with EXC_BREAKPOINT in libsystem_secinit due to Container Integrity Check Failure
After updating the application following an upgrade from a previous macOS version to macOS Tahoe 26.5.1 (25F80), the sandboxed app immediately crashes on launch. The crash occurs during dyld library initialization, before any application code (including main()) is executed. The crash report identifies that libsystem_secinit.dylib rejects the existing app sandbox container with the following signature: "failed integrity checks for container at /Users/apptest/Library/Containers/77C6DBAA-6E54-4ED4-947C-5C5648BE280B/Data: Invalid argumen" Clearing out the old sandbox container data (e.g., rm -rf ~/Library/Containers/77C6DBAA-6E54-4ED4-947C-5C5648BE280B/Data) resolves the crash. Please help analyze the possible causes of this issue: 1.Could this be a compatibility issue between the new macOS 26.5.1 system and Mac Catalyst apps? 2.Could this be caused by certain APIs used by the app or specific project configuration settings? If so, please provide some relevant hints to help narrow down the scope of analysis. Crash Log excerpt.txt
Replies
6
Boosts
0
Views
1.1k
Activity
Jul ’26
Mac Catalyst app built with Xcode 27 beta 3 crashes at launch on macOS 26.5.1 — dyld "Symbol not found: _UIFontTextStyleBody" expected in AppKit
My Mac Catalyst app (distributed via TestFlight) crashes instantly at launch — before main() — on macOS 26.5.1 (25F80) when archived with Xcode 27 beta 3. The same code archived with Xcode 26.5 (GA) launches fine. Crash excerpt: Termination Reason: Namespace DYLD, Code 4, Symbol missing Symbol not found: _UIFontTextStyleBody Referenced from: <...> /Applications/Paku.app/Contents/MacOS/Paku Expected in: <...> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (terminated at launch; ignore backtrace) What appears to be happening The symbol comes from completely ordinary UIKit code — e.g. UIFont.preferredFont(forTextStyle: .body). When linking with the Xcode 27 beta 3 SDK, the two-level namespace bind for _UIFontTextStyleBody in my binary points at AppKit, i.e. the beta SDK's AppKit.tbd declares (re-exports) the UIKit text-style constants for Catalyst. But the shipping OS doesn't provide that: on macOS 26.5.1, _UIFontTextStyleBody is absent from both the installed AppKit binary (checked with dyld_info -exports /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit) and the Xcode 26.5 GA SDK's AppKit.tbd. So any binary linked against the beta SDK hard-binds the symbol to AppKit and then fatally fails to bind on current GA macOS — a 100%-reproducible launch crash for every user not on the macOS 27 beta. Steps to reproduce Mac Catalyst target that uses any UIFont.TextStyle constant (e.g. .preferredFont(forTextStyle: .body)). Archive with Xcode 27 beta 3 and distribute via TestFlight. Launch on macOS 26.5.1 → immediate dyld abort with the report above. Questions Is this a known issue with the macOS 27 beta SDK's AppKit re-export list? It looks like these UIKit constants are being moved/re-exported through AppKit in the 27 cycle, but without availability/weak-linking info that would let binaries back-deploy to macOS 26. Is the intended behavior that Catalyst apps built with the 27 beta SDK simply can't run on macOS 26? If so, should App Store Connect / TestFlight have rejected or flagged the upload?
Replies
0
Boosts
2
Views
645
Activity
Jul ’26
Mac Store search defaults to IOS Apps devastating Mac Catalyst sales.
Mac Store search results now default to IOS Apps, devastating Mac Catalyst sales. To compound this issue, there is no way for Mac Catalyst developers to remove their Mac Catalyst version so that their IOS app (for iPad) will appear. They are invisible. I've contacted Apple but no reply yet. Any thoughts?
Replies
10
Boosts
1
Views
1.5k
Activity
Jul ’26
Request photo library authorization popup on macOS Catalyst can't be dismissed
I have an iOS app that I want to publish to the Mac App Store as a Catalyst app, but I noticed a situation where the app can't be closed and has to be force quit. The problem happens if the user has 0 photos in their Photo Library, and hits "Limited Access" on the request authorization prompt (In my case PHPhotoLibrary.requestAuthorization(for: .readWrite). Since the popup is a system prompt, I can't manually add a close button to it. I tried wrapping it in a view with a close button but the popup always shows up over any view I'm presenting within my app. If anyone has a workaround that would be greatly appreciated!
Replies
2
Boosts
0
Views
967
Activity
Jul ’26