Communicate between helper app and main app in sandbox - macos

I have a status bar application from which I can launch a helper application for preferences. All preferences are stored in NSUserDefaults in the helper app and are read using addSuiteNamed: in the main app.
I would like to notify the main app when preferences are changed in the helper app. What is the best way to do this?
I have tried using NSDistributedNotificationCenter but this is too slow and not very reliable.

RMSharedPreferences by Realmac Software seems to be what I was looking for. It allows communicating between multiple apps and it is very easy to setup and seems to be way more reliable than NSDistributedNotificationCenter.

Related

UI Automation for AppleTV system using XCode

Is UI automation available for the main menu of the Apple TV and not a specific application? I already setup the whole UI testing thing using XCode and tried using the remote control but it is only available for the application that was defined using XCUIApplication.
So is it possible to control the whole system rather than a specific application? I was thinking of something similar to pyatv but using XCode since I might be able to get more information concerning the current focused apps and so on.
There is an API XCUIApplication(bundleIdentifier: ) to interact with not-AUT apps. You need to substitute the right identifier for this Springboard-like interface. Maybe it is a Headboard, but I'm not sure.
Bundle identifiers of tvOS apps https://github.com/rzakhar/XCTApps/blob/master/Sources/XCTApps/tvOS.swift

Pros and cons of splitting Cocoa utility app into helper binary + main app binary?

I'm modernizing and sandboxing an old Cocoa utility and considering approaches. The app lives in the menu bar and works in the background, but shows a Dock icon and a configuration window when the icon is clicked.
There are two approaches:
A. A single binary with LSUIElement=YES, using TransformProcessType to show and hide the dock icon as necessary.
B. A helper tool performs the actual app functionality, manages the menu icon and always runs in LSUIElement mode in background. The main app presents the configuration UI and is only launched when necessary.
The app currently does A. I've noticed that many long-running utility apps have separate helper binaries and basically do B. Examples on my Mac include Paste Helper, TimingHelper, Discord Helper, CCC Helper (for Carbon Copy Cloner), 1Password Extension Helper.
I understand that having a separate helper app is conceptually more pure and potentially allows for better separation of sandbox privileges, but it's also harder to implement, so I doubt that's the sole reason why all these apps opted to have a separate helper binary.
So:
What are the pros and cons of A and B, i.e. why do some choose B over A? Is it required to get some functionality these days?
Is it even possible to have a helper tool outlive the main app in a sandboxed Mac App Store app?
What API does one use to make such a helper? The old-style authorisation APIs seem deprecated, and XPC does not seem like it allows a helper app to launch at startup (and even outliving the main app may be hacky)?
I suspect the reason so many developers choose option B is because this arrangement is now baked into macOS via the "Login Items" facility.
In a nutshell, your main application embeds a second (helper) app and that app is configured as a "Login Item". macOS detects this and automatically adds your helper app to the user's login items. You can control this, programmatically, using SMLoginItemSetEnabled(...).
You end up with a regular app users are familiar with, and a helper app that automatically starts at login and can run in the background. I'm also pretty sure this includes a free XPC connection you can take advantage of.
Read all about it in the Adding Login Items section of the infamous Daemons and Services Programming Guide.
I've never done this myself (I currently install background apps as user agents, which I can do because I don't have a sandboxed app), but I did research it for another project and I know a lot of apps do this.
One disadvantage of option A (based on user feedback from my own apps) is that the main app won't act like a regular app. Using the A approach, your users either can't quit the app (because it will need to automatically restart) or you need a way to hide it in the dock, and then there's no (obvious) way to launch it again. It just gets confusing. If you do let your users quit the app, then the background functionality goes away, and that creates other problems.

Xamarin-iOS: host application will not run with share extension

My app setup is a basic new app with default viewController with the default classes for share extension on iOS 11.2.
The host AppDelegate class FinishedLaunching never gets called.
Just shows the launch screen and closes the app.
The sample Xamarin app provided also has the same issue.
Link to the sample app:
Share Extension sample
Any idea whats going wrong?
Do you want to open the app which you created with the share extension, when user clicks the share button to use this share extension? If so, this app should be called Containing App.
But unfortunately, there's no way to do this on iOS8.3+ except Today Extension. From this post we know that:
The intended approach for share extensions is that they handle all of
the necessary work themselves.
Also from the Apple documentation about extension:
An extension’s UI should be simple, restrained, and focused on
facilitating a single task.
Apple doesn't recommend us to open its containing app from extensions, actually it avoids that. If you want to retrieve data in containing app, you can set up an app group so that data can be shared between these two apps.

User preferences are not saved from XPC service

In my main app bundle I have supporting XPC service included. App is sandboxed and everything works quite fine, except that when I call [[NSUserDefaults standardUserDefault] setObject:forKey:] method and than - synchronize method from the XPC service app, preferences are not written and data cannot be retrieved next time I need it.
I didn't find anything related to this problem in Apple's documentation, except that the sandboxed app cannot access preferences of other apps. That's all right, I don't need it. XPC service has its own container in ~/Library/Containers, where it should be able to store its own data, I'd suppose. But obviously it's not the case for some reason.
I probably missed something, but cannot find what. Is there anything special which needs to be done (adding some entitlement or so) in order to make this work?
Thanks for any tips.
I believe you'll need to use Group Containers to share the preferences and I have achieved something similar (a non-UI LSUIElement app sharing preferences with its conventional Preferences app countpart) using RMSharedPreferences.

Launch at startup and Mac App Store

I've read lots of articles about creating helper tools as LSUIElement and then have them added to LoginItems using SMLoginItemSetEnabled.
What I want to know is, am I allowed to add the main app to LoginItems instead of creating a helper? (And the main app run as a LSUIElement shows in the status bar.)
Since the features were all in the helper and the main app is just a launcher, due to sandbox I can't really validate the receipt within the helper, so I can't prevent people from start the helper directly.
And if it's allowed (I have seem such app but not sure how they did it, such as "Flamingo"), how to add it to LoginItems without have it should down when toggle the settings? As SMLoginItemSetEnabled will terminate the app when pass false.
Thanks.

Resources