Menuapp in Swift 4 to Run on Login for High Sierra

MenuApp in Swift 4 to Run on Login for High Sierra?

I would suggest creating a launch agent. Login items are soooo 2010 ;).

There's really no API for creating a launch agent (or other launchd services). The steps are, basically:

  1. create and write the appropriate ~/Library/LaunchAgents/com.your.agent.plist file
  2. execute /bin/launchctl bootstrap gui/501 ~/Library/LaunchAgents/com.your.agent.plist

(where 501 and com.your.agent are the user's UID and your launchd identifier)

The second step is somewhat optional; the system will see your .plist file and start the agent automatically the next time the system restarts. So you can kick start it by just manually launching it the first time. But if you want it to be immediately registered with launchd (so it will automatically get restarted if quit, for example), then I know of no other way than to run launchctl once to register it. (Similarly, you'll need to run launchctl bootout ... to shut it down when it's time to uninstall it.[1])

The details of the .plist file can be found in man launchd.plist, but here's a simple example of a LSUIElement app called "Menu" that runs in the background whenever the user is logged into to a GUI session:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>Label</key>
<string>com.my.menu</string>
<key>LimitLoadToSessionType</key>
<string>Aqua</string>
<key>Program</key>
<string>/Applications/Menu.app/Contents/MacOS/Menu</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

To create the .plist, all you have to do is populate a property list dictionary with these values and call dictionary.write(to:atomically:) to write it where it belongs.

Launch agents are regular user processes so none of this requires any special privileges, although I'm not sure about writing to ~/Library/LaunchAgents from a sandboxed app.

Since the user doesn't normally fiddle with ~/Library/LaunchAgentsor launchctl your application will need to provide a UI for installing and uninstalling the agent. For a status menu item app, this is usually as simple as a preferences checkbox to "Show in Menubar".

[1] bootstrap and bootout were added in 10.11. If you have to support earlier versions of macOS there are workarounds.

Could not locate login item in the caller's bundle error when using SMLoginItemSetEnabled

OK, I found the problem but it took a long time since it was so sneaky: In the Copy File Build Phase section I entered "Contents/Library/LoginItem" as the subpath instead of "Contents/Library/LoginItems" (notice the 's' in the end - can't believe I missed it). So thank you @vadian! You were absolutely right.

How to launch a Cocoa app at login with ServiceManagement

I had the same issue when I was testing launch at log in and changing the Bundle Identifier of helper app did the trick.

Try it. It will work

macOS. Replace application in Shared folder with admin priveleges

I recommend to have a look at the Sparkle framework for updating applications.

Sparkle handles the checking if an update is available, downloading the update, asking for an administrator password if required, and cleaning up the downloaded files after the update.

For most application it is enough to just have the new version archived as zip archive.

But it is also possible to update application with helper applications or agents which are outside of the main application bundle.

This can be done with installer package *.pkg. If you are familiar with Sparkle, the "Automatic installation" referred here will only show the Sparkle UI. In the background it will use macOS’s built-in command line installer, /usr/sbin/installer.

In most cases it will make sense to have the same .pkg as user facing installer and update, it is not required.

If your application is sandbox, there are a couple of forks of the framework.

Model I/O – How to use `makeVerticesUniqueAndReturnError()` instance method?

Whenever you don't find docs on developer.apple.com or in the Xcode Documentation Viewer, check the framework headers or Swift interface — those often have code comments that can at least serve as a rough form of documentation.

In Xcode, use Open Quickly (⌘⇧O) and type the name of the header in question (MDLMesh.h) or one of the symbols inside it (MDLMesh, makeVerticesUnique, etc). Or ⌘-click one of those symbols in your source and choose Jump to Definition. (If at that point you end up in an Objective-C header and want to see the Swift version, choose Generated Interface from the related items menu at the top of the file.)

In this case, you'll see that both methods are equivalent in usage (but for the ability of the new method to throw errors):

/*!
@method makeVerticesUnique:
@abstract Deindexes the vertex array
@discussion If any vertices are shared on multiple faces, duplicate those
vertices so faces do not share vertices. The vertex buffer and index
buffers on submeshes may grow to accomadate any vertices added.
*/
@available(OSX, introduced: 10.11, deprecated: 10.13)
open func makeVerticesUnique()

/*!
@method makeVerticesUniqueAndReturnError:
@abstract Deindexes the vertex array
@discussion If any vertices are shared on multiple faces, duplicate those
vertices so faces do not share vertices. The vertex buffer and index
buffers on submeshes may grow to accomadate any vertices added.
*/
@available(OSX 10.13, *)
open func makeVerticesUniqueAndReturnError() throws

Presumably Apple determined that the original method wasn't handling failures gracefully (fatal-error halting? crashing? producing bad output? dunno) and decided it'd be better to let callers know when something goes wrong.

How to support the increase contrast option under the Accessibility Display

NSWorkspace.accessibilityDisplayOptionsDidChangeNotification fires when option changes. The only thing is, it fires in NSWorkspace's notification center. Not in the default one.

NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(accessibilityDisplayOptionsDidChange(_:)), name: NSWorkspace.accessibilityDisplayOptionsDidChangeNotification, object: NSWorkspace.shared)

Then you have to use NSWorkspace.shared.accessibilityDisplayShouldIncreaseContrast property in your code to alter the appearance of your UI when necessary.



Related Topics



Leave a reply



Submit