Post

Replies

Boosts

Views

Created

How can I share a developer-signed app through my website?
In the past, I used to export a developer-signed test version of my macOS app in Xcode, create a zip archive from the Finder, upload it to my website and share the link to the testers. The last time I did this with macOS 14 the tester was still able to download the test app and run it. But it seems that with macOS 15 the trick to open the context menu on the downloaded app and click Open to bypass the macOS warning that the app couldn't be checked when simply double-clicking it, doesn't work anymore. Now I'm always shown an alert that macOS couldn't check the app for malware, and pushes me to move it to the bin. In this StackOverflow topic from 10 years ago they suggested to use ditto and tar to compress and uncompress the app, but neither worked for me. How can I share macOS apps that I signed myself with testers without physically handing them a drive containing the uncompressed app?
3
0
812
Nov ’24
How to get GKMatch instance after accepting GKInvite?
In my SceneKit game I'm able to connect two players with GKMatchmakerViewController. Now I want to support the scenario where one of them disconnects and wants to reconnect. I tried to do this with this code: nonisolated public func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) { Task { @MainActor in switch state { case .connected: break case .disconnected, .unknown: let matchRequest = GKMatchRequest() matchRequest.recipients = [player] do { try await GKMatchmaker.shared().addPlayers(to: match, matchRequest: matchRequest) } catch { } @unknown default: break } } } nonisolated public func player(_ player: GKPlayer, didAccept invite: GKInvite) { guard let viewController = GKMatchmakerViewController(invite: invite) else { return } viewController.matchmakerDelegate = self present(viewController) } But after presenting the view controller with GKMatchmakerViewController(invite:), nothing else happens. I would expect matchmakerViewController(_:didFind:) to be called, or how would I get an instance of GKMatch? Here is the code I use to reproduce the issue, and below the reproduction steps. Code Run the attached project on an iPad and a Mac simultaneously. On both devices, tap the ship to connect to GameCenter. Create an automatched match by tapping the rightmost icon on both devices. When the two devices are matched, on iPad close the dialog and tap on the ship to disconnect from GameCenter. Wait some time until the Mac detects the disconnect and automatically sends an invitation to join again. When the notification arrives on the iPad, tap it, then tap the ship to connect to GameCenter again. The iPad receives the call player(_:didAccept:), but nothing else, so there’s no way to get a GKMatch instance again.
6
0
830
Nov ’24
copyfile causes NSPOSIXErrorDomain 12 "Cannot allocate memory" when copying symbolic link from NTFS partition
I was able to confirm with a customer of mine that calling copyfile with a source file that is a symbolic link on a NTFS partition always causes the error NSPOSIXErrorDomain 12 Cannot allocate memory They use NTFS drivers from Paragon. They tried copying a symbolic link from NTFS to both APFS and NTFS with the same result. Is this an issue with macOS, or with the NTFS driver? Copying regular files on the other hand always works. Copying manually from the Finder also seems to always work, both with regular files and symbolic links, so I'm wondering how the Finder does it. Here is the sample app that they used to reproduce the issue. The first open panel allows to select the source directory and the second one the destination directory. The variable filename holds the name of the symbolic link to be copied from the source to the destination. Apparently it's not possible to select a symbolic link directly in NSOpenPanel, as it always resolves to the linked file. @main class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.runModal() let filename = "Modules" let source = openPanel.urls[0].appendingPathComponent(filename) openPanel.runModal() let destination = openPanel.urls[0].appendingPathComponent(filename) do { let state = copyfile_state_alloc() defer { copyfile_state_free(state) } var bsize = UInt32(16_777_216) if copyfile_state_set(state, UInt32(COPYFILE_STATE_BSIZE), &bsize) != 0 { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } if copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), unsafeBitCast(copyfileCallback, to: UnsafeRawPointer.self)) != 0 || copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CTX), unsafeBitCast(self, to: UnsafeRawPointer.self)) != 0 || copyfile(source.path, destination.path, state, copyfile_flags_t(COPYFILE_NOFOLLOW)) != 0 { throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno)) } } catch { let error = error as NSError let alert = NSAlert() alert.messageText = "\(error.localizedDescription)\n\(error.domain) \(error.code)" alert.runModal() } } private let copyfileCallback: copyfile_callback_t = { what, stage, state, src, dst, ctx in if what == COPYFILE_COPY_DATA { if stage == COPYFILE_ERR { return COPYFILE_QUIT } var size: off_t = 0 copyfile_state_get(state, UInt32(COPYFILE_STATE_COPIED), &size) } return COPYFILE_CONTINUE } }
3
0
599
Nov ’24
SKNode.zPosition causes nodes to flicker by reordering them for 1 frame
When running the sample code below, every 3 seconds the middle sprite is replaced by a new one. When this happens, most of the time a flicker is noticeable. When recording the screen and stepping through the recording frame by frame, I noticed that the flicker is caused by a temporary reordering of the nodes’. Below you find two screenshots of two consecutive frames where the reordering is clearly visible. This only happens for a SpriteKit scene used as an overlay for a SceneKit scene. Commenting out buttons.zPosition = 1 or avoiding the fade in/out animations solves the issue. I have created FB15945016. import SceneKit import SpriteKit class GameViewController: NSViewController { let overlay = SKScene() var buttons: SKNode! var previousButton: SKSpriteNode! var nextButton: SKSpriteNode! var pageContainer: SKNode! var pageViews = [SKNode]() var page = 0 override func viewDidLoad() { super.viewDidLoad() let scene = SCNScene(named: "art.scnassets/ship.scn")! let scnView = self.view as! SCNView scnView.scene = scene overlay.anchorPoint = CGPoint(x: 0.5, y: 0.5) scnView.overlaySKScene = overlay buttons = SKNode() buttons.zPosition = 1 overlay.addChild(buttons) previousButton = SKSpriteNode(systemImage: "arrow.uturn.backward.circle") previousButton.position = CGPoint(x: -100, y: 0) buttons.addChild(previousButton) nextButton = SKSpriteNode(systemImage: "arrow.uturn.forward.circle") nextButton.position = CGPoint(x: 100, y: 0) buttons.addChild(nextButton) pageContainer = SKNode() pageViews = [SKSpriteNode(systemImage: "square.and.arrow.up"), SKSpriteNode(systemImage: "eraser")] overlay.addChild(pageContainer) setPage(0) Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [self] _ in setPage((page + 1) % 2) } } func setPage(_ page: Int) { pageViews[self.page].run(.sequence([ .fadeOut(withDuration: 0.2), .removeFromParent() ]), withKey: "fade") self.page = page let pageView = pageViews[page] pageView.alpha = 0 pageView.run(.fadeIn(withDuration: 0.2), withKey: "fade") pageContainer.addChild(pageView) } override func viewDidLayout() { overlay.size = view.frame.size } } extension SKSpriteNode { public convenience init(systemImage: String) { self.init() let width = 100.0 let image = NSImage(systemSymbolName: systemImage, accessibilityDescription: nil)!.withSymbolConfiguration(.init(hierarchicalColor: NSColor.black))! let scale = NSScreen.main!.backingScaleFactor image.size = CGSize(width: width * scale, height: width / image.size.width * image.size.height * scale) texture = SKTexture(image: image) size = CGSize(width: width, height: width / image.size.width * image.size.height) } }
1
0
708
Nov ’24
App Intent title and other localized strings not showing correctly in Shortcuts app on macOS 15
I rarely use the Shortcuts app, so it took me a while to notice that my app's app intents all show incorrectly on macOS 15. On macOS 14 and 13, they used to show correctly, but now it seems that all localized strings show the key rather than the localized value. @available(iOS 16.0, macOS 13.0, *) struct MyAppIntent: AppIntent { static let title = LocalizedStringResource("key1", comment: "") static let description = IntentDescription(LocalizedStringResource("key2", comment: "")) ... } In Localizable.xcstrings file I have defined all the strings, for instance I have associated key1 with the value Title, but while the Shortcuts app used to display Title, it now displays key1. Is this a known issue or did something change in macOS 15 that would require me to update something?
10
0
1.3k
Dec ’24
Testing app intents and forcing Shortcuts app to refresh
The Verify the behavior of your intent in Simulator or on-device documentation says that it's sufficient to build and run the app and open the Shortcuts app to test an app intent, but that doesn't seem to be the case. I always needed to at least move the debugged app to the Applications folder before the app intents showed up in Shortcuts, and even then, most of the times I also need to wait a lot or restart the Mac. When updating an existing app intent (for instance by changing its title), building the app, overwriting the existing one in the Applications folder and restarting Shortcuts is not sufficient to make the new title appear in Shortcuts. Is there an efficient way to test app intents in the Shortcuts app? I already created FB15638502 one month ago but got no response.
0
0
408
Dec ’24
Basic app intent always showing error in Shortcuts app "The action could not run because an internal error occurred."
I have a very basic App Intent extension in my macOS app that does nothing than accepting two parameters, but running it in Shortcuts always produces the error "The action “Compare” could not run because an internal error occurred.". What am I doing wrong? struct CompareIntent: AppIntent { static let title = LocalizedStringResource("intent.compare.title") static let description = IntentDescription("intent.compare.description") static let openAppWhenRun = true @Parameter(title: "intent.compare.parameter.original") var original: String @Parameter(title: "intent.compare.parameter.modified") var modified: String func perform() async throws -> some IntentResult { return .result() } }
8
0
1.2k
Dec ’24
Camera zoom in to 3D point in SceneKit scene
I would like to implement zoom functionality in my SceneKit game: when the user performs the pinch gesture on a point on the screen, the scene zooms in to make that point larger. Until now I simply changed SCNCamera.focalLength, but this simply zooms in to the center of what is currently visible on screen. Is it somehow possible to implement the zoom functionality described above by perhaps interactively rotating the camera at the same time towards the pinched point? Is there a formula for this? I would like to avoid suddenly rotating the camera to face the pinched point when the pinch gesture begins and then zoom in while the pinch is in progress.
0
0
613
Dec ’24
Feedback Assistant: „This Feedback will no longer be monitored, and incoming messages will not be reviewed.“
Every now and then I get this very frustrating message on Feedback Assistant. For instance, in FB14696726 I reported an issue with the App Store Connect API. 4 weeks later, I got a reply, asking among other things for a „correlation key and Charles log“. I immediately replied saying that I didn‘t know what those are, and they replied After reviewing your feedback, it is unclear what the exact issue is. I pointed out that I had asked a question which was left unanswered, and they replied explaining what the correlation key is. Then I asked again what the Charles log is. They replied The Apple Developer website provides access to a range of videos covering various topics on using and developing with Apple technologies. You can find these videos on our Development Videos page: http://developer.apple.com/videos. I opened the link and searched for „Charles“ but there were no results, so I asked to kindly point me to the video answering my question. They replied 3 months later (today): Following up on our last message, we believe this issue is either resolved or not reproducible with the information provided and will now consider this report closed internally. This Feedback will no longer be monitored, and incoming messages will not be reviewed. This is not the first time I ask for clarification and get back a message basically telling me that „we won‘t answer any questions you may have and won‘t hear anything you still may have to say about this issue“. They didn‘t even ask me to verify if the issue is resolved or not, like they sometimes do. No, they just shut the door in my face. I just wanted to share this frustrating experience. Perhaps an Apple engineer wants to say something about it or a developer has had a similar experience?
1
0
574
Dec ’24
NSDictionary.isEqual(to:) with Swift dictionary compiles on macOS but not on iOS
The following code works when compiling for macOS: print(NSMutableDictionary().isEqual(to: NSMutableDictionary())) but produces a compiler error when compiling for iOS: 'NSMutableDictionary' is not convertible to '[AnyHashable : Any]' NSDictionary.isEqual(to:) has the same signature on macOS and iOS. Why does this happen? Can I use NSDictionary.isEqual(_:) instead?
2
0
540
Feb ’25
Getting a file icon on iOS
Some time ago I read somewhere that one can get a file icon on iOS like this: UIDocumentInteractionController(url: url).icons.last!) but this always returns the following image for every file: Today I tried the following, which always returns nil: (try? url.resourceValues(forKeys: [.effectiveIconKey]))?.allValues[.effectiveIconKey] as? UIImage Is there any way to get a file icon on iOS? You can try the above methods in this sample app: struct ContentView: View { @State private var isPresentingFilePicker = false @State private var url: URL? var body: some View { VStack { Button("Open") { isPresentingFilePicker = true } if let url = url { Image(uiImage: UIDocumentInteractionController(url: url).icons.last!) if let image = (try? url.resourceValues(forKeys: [.effectiveIconKey]))?.allValues[.effectiveIconKey] as? UIImage { Image(uiImage: image) } else { Text("none") } } } .padding() .fileImporter(isPresented: $isPresentingFilePicker, allowedContentTypes: [.data]) { result in do { let url = try result.get() if url.startAccessingSecurityScopedResource() { self.url = url } } catch { preconditionFailure(error.localizedDescription) } } } }
2
0
514
Feb ’25
Notification when mounting volume on iOS
On macOS, we have didMountNotification but there doesn't seem to be an equivalent for iOS. Is there a way to be notified when a volume is mounted on iOS? I would like to use it in my iOS app I'm currently porting from macOS, which starts a synchronization from the volume (which has been previously selected in a NSOpenPanel) as soon as it's mounted.
3
0
414
Feb ’25
Resolving URL from bookmark data doesn't automatically mount SMB volume on iOS
On macOS, the Finder allows to connect to a server and store the login credentials. When creating a bookmark to a file on a server and resolving it again, the server is mounted automatically (unless I provide the option URL.BookmarkResolutionOptions.withoutMounting). I just tried connecting to my Mac from my iPad via SMB in the Files app and storing a bookmark to a file on the server, but disconnecting the server and trying to resolve the bookmark throws the error (I translated the English text from Italian): Error Domain=NSFileProviderErrorDomain Code=-2001 "No file provider was found with the identifier "com.apple.SMBClientProvider.FileProvider"'" UserInfo={NSLocalizedDescription=No file provider was found with the identifier "com.apple.SMBClientProvider.FileProvider"., NSUnderlyingError=0x302a1a340 {Error Domain=NSFileProviderErrorDomain Code=-2013 "(null) "}} Every time I disconnect and reconnect to the server, selecting the same file returns a different path. The first time I got /private/var/mobile/Library/LiveFiles/com.apple.filesystems.smbclientd/WtFD3Ausername/path/to/file.txt The next time WtFD3A changed to EqHc2g and so on. Is it not possible to automatically mount a server when resolving a bookmark on iOS? The following code allows to reproduce the issue: struct ContentView: View { @State private var isPresentingFilePicker = false @AppStorage("bookmarkData") private var bookmarkData: Data? @State private var url: URL? @State private var stale = false @State private var error: Error? var body: some View { VStack { Button("Open") { isPresentingFilePicker = true } if let url = url { Text(url.path) } else if bookmarkData != nil { Text("couldn't resolve bookmark data") } else { Text("no bookmark data") } if stale { Text("bookmark is stale") } if let error = error { Text("\(error)") .foregroundStyle(.red) } } .padding() .fileImporter(isPresented: $isPresentingFilePicker, allowedContentTypes: [.data]) { result in do { let url = try result.get() if url.startAccessingSecurityScopedResource() { bookmarkData = try url.bookmarkData() } } catch { self.error = error } } .onChange(of: bookmarkData, initial: true) { _, bookmarkData in if let bookmarkData = bookmarkData { do { url = try URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &stale) } catch { self.error = error } } } } }
2
0
476
Feb ’25