🍁
Swift: macOS 13以降でのLaunch At Loginの実装
macOS 13からServiceManagement
が強化されSMAppService
が追加されたことで、ようやくヘルパーアプリに頼らずにログイン項目にアプリを登録できるようになりました。🎉(ヘルパーではなくアプリ本体がログイン項目に登録され、ログイン時に起動するようにできます。)しかも、実装方法もかなりシンプルでわかりやすいAPIとなっております。
実装例
import SwiftUI
import ServiceManagement
class ContentViewState: ObservableObject {
@Published var launchAtLogin: Bool
init() {
launchAtLogin = SMAppService.mainApp.status == .enabled
}
func toggleLaunchAtLogin(_ isOn: Bool) {
do {
if isOn {
try SMAppService.mainApp.register()
} else {
try SMAppService.mainApp.unregister()
}
} catch {
Swift.print(error.localizedDescription)
}
launchAtLogin = SMAppService.mainApp.status == .enabled
}
}
struct ContentView: View {
@StateObject var state = ContentViewState()
var body: some View {
VStack {
Toggle(isOn: Binding<Bool>(
get: { state.launchAtLogin },
set: { state.toggleLaunchAtLogin($0) }
)) {
Text(verbatim: "launch at login")
}
}
}
}
ポイント
-
SMAppService.mainApp.status
で現状ログイン項目に入っているのかどうかが判断できます。 -
SMAppService.mainApp.register()
でログイン項目に登録できます。(try
がついていますがXcodeでRunした時はnot permittedとなるようです。動作確認するにはリリースしないといけない?謎です。) -
SMAppService.mainApp.unregister()
でログイン項目から登録解除できます。環境設定から手動で登録解除しているのに、さらにその状態からunregister()
を叩くとError
がthrow
されます。 - ユーザーが状態を切り替えようとした際に失敗しうるAPIなので、UI側はプロパティと
Toggle
を直接Bindingするのではなく、Binding<Bool>(get:set:)
のsetでAPIのレスポンスに合わせてプロパティの値を更新するようにします。
参考
Discussion
macOS 12までのLaunch At Loginの実装(SwiftUI編)