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

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
105
3h
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
462
2d
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
97
5d
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
860
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
743
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
687
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.8k
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
960
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
639
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
957
Jul ’26
Single Build / Archive for iOS and Catalyst Build
So I am adding Catalyst support to my iOS app. I went through and updated my code and Build Settings to add Catalyst support. I can build for any iOS build or macOS build. I went into App Store Connect and then added a macOS build. I am not able to do a single build and archive that uploads a build for both macOS and iOS. I can do a build and archive for "Any iOS Device (arm64)" and it shows up in the iOS test flight. I can do a build and archive for "Any Mac (Mac Catalyst, arm64, x86_64) and it shows in the macOS test flight. Maybe I'm making a bad assumption ( I could not find any documentation on it) but I assumed Catalyst was a single build and archive that showed up in BOTH macOS and iOS sections. The build settings seem to imply the build is good for a single build and archive process. I want this to be a universal app and my assumption doing it that way would keep everything in sync when you push to the App Store. You can already download the app through the App Store but it is a version of the iPad app. I was hoping to make it more native and available in the Mac App Store without the iPhone/iPad app option. Am I making bad assumptions? Will I just have to do two Build and Archives for every build? I just want to make sure I'm doing this correctly and the best way.
6
0
832
Jul ’26
Linker trying to link Metal toolchain for every object file on Catalyst
When building our project for Mac Catalyst with Xcode 26.2, we get this warning almost a hundred times, once for every object file: directory not found for option '-L/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst' Somehow, every Link <FileName>.o build step got the following parameter, regardless if the target contained Metal files or not: -L/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst The toolchain is mounted at this point, but the directory usr/lib/swift/maccatalyst doesn't exist. When building the project for iOS, the option doesn't exist and the warning is not shown. We already check the build settings, but we couldn't find a reason why the linker is trying to link against the toolchain here. Even for targets that do contain Metal files, we get the following linker warning: search path '/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst' not found Is this a known issue? Is there a way to get rid of these warnings?
2
3
2.0k
Jun ’26
My biggest priorities after 9 months of shipping Albums for macOS
Hi everyone! Adam here, the developer of Albums. Bummed not to get to have our yearly WebEx reunion where I beg y’all to add an endpoint to the Apple Music API to allow deleting items from a user’s library. But that’s not what this thread is about. Back in October, thanks to your team’s multi-year efforts, I was finally able to ship Albums for macOS. It’s been a genuine dream come true to use it on the platform I always envisioned it on, and I hear from users all the time who feel the same way. I know it was a significant engineering effort, and I’m genuinely very grateful. I’ll be judicious with my time here (I’d love to chat in more detail about my adventures in MusicKit on the Mac somehow, sometime). These are the main things on my wishlist for MusicKit on the Mac. There are three main things I hear from users that my app “can’t do” that can be dealbreakers for them. The first two are AirPlay support and a volume slider. Users are only able to AirPlay using the control center utility, because AVRoutePickerView does not work with ApplicationMusicPlayer (FB13934910). Relatedly, the MPVolumeView does not work with ApplicationMusicPlayer (FB21042385), so I can’t allow users app-specific volume control for my app. The lack of those two things is a real detriment to my app being able to be taken seriously alongside all of the other music player apps on the platform for which those features are table stakes. I know there’s a challenge here given the playback actually happens in the subprocess, but hoping some progress can be made here. The other issue is that library tracks played in ApplicationMusicPlayer do not update the last played date or play count in Music.app or in the user’s iCloud Music Library (FB17675148). Some people refuse to use the app for that reason, and I can’t say I blame them. I’ve only been able to test this briefly in Golden Gate, but it seems like this is still the case. Are you able to share anything about your work on the music library in macOS this year? Thank you again for all your work on MusicKit! I’m planning to get the last of the load-bearing MediaPlayer code out of my codebase later this year. Hooray!
1
2
948
Jun ’26
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
105
Activity
3h
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
462
Activity
2d
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
97
Activity
5d
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
860
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
743
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
529
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
687
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.8k
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
960
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
639
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
957
Activity
Jul ’26
Single Build / Archive for iOS and Catalyst Build
So I am adding Catalyst support to my iOS app. I went through and updated my code and Build Settings to add Catalyst support. I can build for any iOS build or macOS build. I went into App Store Connect and then added a macOS build. I am not able to do a single build and archive that uploads a build for both macOS and iOS. I can do a build and archive for "Any iOS Device (arm64)" and it shows up in the iOS test flight. I can do a build and archive for "Any Mac (Mac Catalyst, arm64, x86_64) and it shows in the macOS test flight. Maybe I'm making a bad assumption ( I could not find any documentation on it) but I assumed Catalyst was a single build and archive that showed up in BOTH macOS and iOS sections. The build settings seem to imply the build is good for a single build and archive process. I want this to be a universal app and my assumption doing it that way would keep everything in sync when you push to the App Store. You can already download the app through the App Store but it is a version of the iPad app. I was hoping to make it more native and available in the Mac App Store without the iPhone/iPad app option. Am I making bad assumptions? Will I just have to do two Build and Archives for every build? I just want to make sure I'm doing this correctly and the best way.
Replies
6
Boosts
0
Views
832
Activity
Jul ’26
Linker trying to link Metal toolchain for every object file on Catalyst
When building our project for Mac Catalyst with Xcode 26.2, we get this warning almost a hundred times, once for every object file: directory not found for option '-L/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst' Somehow, every Link <FileName>.o build step got the following parameter, regardless if the target contained Metal files or not: -L/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst The toolchain is mounted at this point, but the directory usr/lib/swift/maccatalyst doesn't exist. When building the project for iOS, the option doesn't exist and the warning is not shown. We already check the build settings, but we couldn't find a reason why the linker is trying to link against the toolchain here. Even for targets that do contain Metal files, we get the following linker warning: search path '/var/run/com.apple.security.cryptexd/mnt/com.apple.MobileAsset.MetalToolchain-v17.3.48.0.UZtKea/Metal.xctoolchain/usr/lib/swift/maccatalyst' not found Is this a known issue? Is there a way to get rid of these warnings?
Replies
2
Boosts
3
Views
2.0k
Activity
Jun ’26
My biggest priorities after 9 months of shipping Albums for macOS
Hi everyone! Adam here, the developer of Albums. Bummed not to get to have our yearly WebEx reunion where I beg y’all to add an endpoint to the Apple Music API to allow deleting items from a user’s library. But that’s not what this thread is about. Back in October, thanks to your team’s multi-year efforts, I was finally able to ship Albums for macOS. It’s been a genuine dream come true to use it on the platform I always envisioned it on, and I hear from users all the time who feel the same way. I know it was a significant engineering effort, and I’m genuinely very grateful. I’ll be judicious with my time here (I’d love to chat in more detail about my adventures in MusicKit on the Mac somehow, sometime). These are the main things on my wishlist for MusicKit on the Mac. There are three main things I hear from users that my app “can’t do” that can be dealbreakers for them. The first two are AirPlay support and a volume slider. Users are only able to AirPlay using the control center utility, because AVRoutePickerView does not work with ApplicationMusicPlayer (FB13934910). Relatedly, the MPVolumeView does not work with ApplicationMusicPlayer (FB21042385), so I can’t allow users app-specific volume control for my app. The lack of those two things is a real detriment to my app being able to be taken seriously alongside all of the other music player apps on the platform for which those features are table stakes. I know there’s a challenge here given the playback actually happens in the subprocess, but hoping some progress can be made here. The other issue is that library tracks played in ApplicationMusicPlayer do not update the last played date or play count in Music.app or in the user’s iCloud Music Library (FB17675148). Some people refuse to use the app for that reason, and I can’t say I blame them. I’ve only been able to test this briefly in Golden Gate, but it seems like this is still the case. Are you able to share anything about your work on the music library in macOS this year? Thank you again for all your work on MusicKit! I’m planning to get the last of the load-bearing MediaPlayer code out of my codebase later this year. Hooray!
Replies
1
Boosts
2
Views
948
Activity
Jun ’26