Post

Replies

Boosts

Views

Activity

Reply to Puzzling Window Menu problem
I found a solution: After adding the menu option to the Window menu, tell the window to not manage its own Window menu entry by setting window.isExcludedFromWindowsMenu to true. Managing the checked state on this item can be done through the windowDidBecomeKey(_:) and windowDidResignKey(_:) methods on the NSWindowDelegate. Also, if its window is closed, Calendar brings its own window back if you click on the Dock icon or double-click the app in the Finder. You can mimic this behavior by adding a applicationShouldHandleReopen(_:hasVisibleWindows:) handler to your NSApplicationDelegate.
Jul ’20
Reply to Safari app extension not detected in showPreferencesForExtension
I've also encountered this issue with the same circumstances. The app built fine on my Mac, but when I airdropped it to another Mac running Catalina and Safari 13.1.1, it kept producing SFErrorDomain Code=1 when checking the extension status. The solve was to move the containing app from ~/Downloads to /Applications.This is an app signed with a Developer ID, but I also saw the problem after notarization.I often try apps from my Downloads folder, and I'd bet I'm not the only person who does that. Hope this can be fixed...
May ’20
Reply to Problems using keychain in macOS Content Blocker extensions
I've also encountered this issue. My app, Safari app extension, and content blocker extension share code that accesses the macOS keychain. My content blocker can't access the keychain, but my other two processes can.My extension allows users to whitelist websites for the content blocker. Because of this, I'm trying to avoid storing my blocklist JSON in plaintext. I'd planned to encrypt this using keys stored in the keychain, but that appears to be a non-starter.What alternative options do I have to achieve this goal?
May ’20
Reply to Safari App Extension Process Questions
I've discovered that I can work around this parallel initialization problem through the use of a singleton, like so:final class Setup { static var main = Setup() private init() {} var bootstrapRun = false func bootstrap() { guard !bootstrapRun else { return } bootstrapRun = true // Put your setup logic here; it will only run once. // ... } }Then, call the bootstrap method from wherever your extension enters the world: override func beginRequest(with context: NSExtensionContext) { super.beginRequest(with: context) Setup.main.bootstrap()Hope this helps anyone trying to run initialization logic inside their extension.
May ’20
Reply to Safari App Extension Process Questions
Hi Brian,Safari App Extensions are automatically discovered, without launching the containing app, when downloaded through the App Store. Therefore, I must support a use case where the user installs my containing app from the App Store, goes to Safari's prefs without opening my containing app first, and turns my extension on. That means I have to have initialization logic in my app and my extension.Your post says that there's one instance of the process per App Extension, but I can't independently verify this.I'm debugging a Safari app extension in Xcode 11.4.1 (11E503a), Safari 13.1 (15609.1.20.111.8) and macOS Catalina 10.15.4 (19E287). When I choose to run my extension (not the containing app) and attach to Safari, Safari runs, then my extension's initializer is run several times in sub-millisecond succession, and runs in parallel (along with the beginRequest(with:) method). I tested the parallelization by running many NSLog statements in my init and verifying the printed order in the console.If I tried to run initialization logic in this sort of environment, I'm afraid of the kinds of bugs that might appear!In the course of writing this post, I created a blank Safari App Extension project and had the same thing happen. Simply adding this code to the SafariExtensionHandler, then attaching the app extension to Safari shows the problem: var counter = 0 override init() { super.init() counter += 1 NSLog(String(counter)) } deinit { NSLog("Disappearing...") }objc[58615]: Class AMSupportURLConnectionDelegate is implemented in both /System/Library/PrivateFrameworks/OSPersonalization.framework/Versions/A/OSPersonalization (0x7fff92e61b68) and /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x1048fe228). One of the two will be used. Which one is undefined. objc[58615]: Class AMSupportURLSession is implemented in both /System/Library/PrivateFrameworks/OSPersonalization.framework/Versions/A/OSPersonalization (0x7fff92e61bb8) and /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/MobileDevice (0x1048fe278). One of the two will be used. Which one is undefined. 2020-05-15 19:25:31.213733-0700 Safari[58615:5517884] [Extensions] Unable to access keychain item for the list of installed extensions because it does not exist 2020-05-15 19:25:32.848653-0700 basicsafariextension Extension[58618:5517957] [subsystems ] Bootstrapping; external subsystem UIKit_PKSubsystem refused setup 2020-05-15 19:25:32.878416-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.878689-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.878864-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.879073-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.879233-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.879501-0700 basicsafariextension Extension[58618:5517957] 1 2020-05-15 19:25:32.893023-0700 basicsafariextension Extension[58618:5517957] Disappearing... 2020-05-15 19:25:32.893492-0700 basicsafariextension Extension[58618:5517957] Disappearing...(Yes, deinit is only run twice after Safari loads...)Why is my init code being run so many times if there's only one instance of the process?EDIT: I discovered that the first number after the name of the process is the PID, which clearly shows one copy of the process. But the multiple, parallel inits are still a cause for concern. How can I handle this?
May ’20