56 Commits

Author SHA1 Message Date
Christian Tietze 9a894d7992 Consistently use macOS 10.13 as deployment target for 'modern' Xcode (#103) 2024-06-25 02:03:32 +02:00
Sindre Sorhus f326e3d9be Change repo name 2024-05-28 18:38:05 +02:00
Sindre Sorhus 22923d3354 Meta tweaks 2024-03-25 02:35:28 +09:00
Sindre Sorhus 0615d2f292 Tweaks 2024-03-25 02:35:19 +09:00
Dave DeLong cf9770cd43 More robust ONLY_ACTIVE_ARCH comparison (#101) 2024-03-25 02:35:10 +09:00
UeharaYou d811817ce3 Update note for Xcode 15 (#97) 2023-10-07 11:13:34 +07:00
UeharaYou 8e28b5e5a9 Add Xcode 15 note (#96)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
2023-07-21 21:28:46 +02:00
Sindre Sorhus 7ad6331f9c Support SMAppService for macOS 13
Fixes #76
2022-11-13 23:48:46 +07:00
Sindre Sorhus d473e16953 Document Xcode 14 requirement
Fixes #81
2022-09-25 12:20:49 +07:00
Sindre Sorhus fe1c59e088 Drop support for macOS 10.12
It’s no longer supported by Xcode.
2022-09-22 23:51:24 +07:00
Sindre Sorhus 05168c04c9 Meta tweaks 2022-09-05 14:02:50 +07:00
Sindre Sorhus e8171b3e38 4.2.0 2021-10-09 16:33:34 +07:00
Ariel Elkin b35bfbde57 Silence SMCopyAllJobDictionaries deprecation warning (#66) 2021-10-09 16:32:27 +07:00
Ariel Elkin b5d8e006bd Add CI (#67)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
2021-10-07 21:14:43 +07:00
Sindre Sorhus c34d3c7171 Meta tweaks 2021-08-15 11:33:45 +02:00
Sindre Sorhus afaacda259 Add related package to readme 2021-05-01 18:40:27 +07:00
Sindre Sorhus 6b16bcdf7d 4.1.0 2021-03-20 18:42:16 +07:00
Sindre Sorhus f1cc3b8dd5 Add native Apple Silicon support to the helper app
Fixes #53
2021-03-20 17:36:24 +07:00
Sindre Sorhus b068272af8 Add ITSAppUsesNonExemptEncryption to the helper app
Fixes #55
2021-03-20 16:55:08 +07:00
Sindre Sorhus 389e09faf7 Minor tweaks
Fixes #49
Fixes #51
2021-03-20 16:55:07 +07:00
Zack Sheppard 2badfdd7df Fix notarization issues with build configs not named "Release" (#57)
Co-authored-by: Javi Ramírez <javi.rmrz@gmail.com>
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
2021-03-20 16:17:12 +07:00
Sindre Sorhus 0f39982b9d 4.0.0 2020-09-17 17:42:51 +02:00
Sindre Sorhus 7f469e4511 Minor tweaks 2020-09-17 17:30:57 +02:00
Sergey Kuryanov c16509926a Swift Package Manager support (#41)
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
2020-09-17 17:29:51 +02:00
Sindre Sorhus 3708ba7f4f Upgrade to Swift 5.3 2020-09-17 00:30:27 +02:00
Sindre Sorhus 08b9b397c8 Cleanup 2020-08-02 14:22:39 +02:00
Sergey Kuryanov f7b255bc96 Add KVO, Combine, and SwiftUI support (#42) 2020-08-02 13:59:03 +02:00
Sindre Sorhus 090e6e069b 3.0.2 2020-07-25 08:39:32 +02:00
Philippe Casgrain 0fe5eb50ff Fix building on Apple Silicon (#43) 2020-07-25 08:38:26 +02:00
Sindre Sorhus e7c842de54 Add FAQ for build error
Closes #34
2020-06-10 02:43:09 +08:00
Sindre Sorhus 1981985a88 3.0.1 2020-06-10 02:32:27 +08:00
Sindre Sorhus 210a771cd8 Don’t inherit entitlements from the app (#38) 2020-06-10 02:30:20 +08:00
Sindre Sorhus a464087da3 Add related project to the readme 2020-06-10 02:30:10 +08:00
Sindre Sorhus c9632dc425 Add FAQ item 2020-04-19 18:52:53 +08:00
Sindre Sorhus bf07cd1609 3.0.0 2020-01-21 18:24:08 +07:00
Christian Tietze ff900e8531 Set signing to local & "None" (#28) 2020-01-21 18:15:19 +07:00
Sindre Sorhus adefcd008d Add some FAQs
Closes #32
2020-01-21 17:58:54 +07:00
Sindre Sorhus 8b1f35e991 Readme improvements 2019-09-20 16:43:34 +07:00
Sindre Sorhus db82bf69ea Drop support for CocoaPods
Fixes #22
2019-09-20 16:43:32 +07:00
Sindre Sorhus aceb69c245 Add FAQ section to the readme 2019-09-20 13:35:46 +07:00
Sindre Sorhus 2702d941d1 Minor tweaks 2019-09-11 22:13:51 +07:00
Sindre Sorhus 55146c0847 Enable the repo Sponsor button 2019-05-23 21:41:07 +07:00
Sindre Sorhus a3e48661e3 Upgrade to Swift 5 2019-03-26 16:10:18 +07:00
Sindre Sorhus ee39e81729 2.5.0 2018-12-03 11:24:21 +07:00
Sindre Sorhus fdc097d040 Readme tweaks 2018-12-03 11:23:31 +07:00
Christian Tietze 9fe1f549a1 Support non-sandboxed apps (#19) 2018-12-03 11:19:45 +07:00
Christian Tietze c41dd52f06 Make script paths absolute (#18) 2018-12-03 11:05:03 +07:00
Sindre Sorhus ce339c2216 2.4.1 2018-11-19 22:06:19 +07:00
Boy van Amstel 5de05e5093 Retain hardened runtime when copying helper (#17) 2018-11-19 22:04:54 +07:00
Sindre Sorhus a22eb83047 2.4.0 2018-10-25 13:53:59 +07:00
Sindre Sorhus acae9779a4 Enable "Hardened Runtime" for the helper app 2018-10-25 13:52:10 +07:00
Sindre Sorhus 8cb7d331a0 Add related link to the readme 2018-10-11 01:32:02 +07:00
Sindre Sorhus 1afaf8428b 2.3.0 2018-10-10 10:32:53 +07:00
Sindre Sorhus 159c990131 Upgrade to Swift 4.2 2018-09-14 14:07:41 +07:00
Sindre Sorhus 1c796f0272 Meta tweaks 2018-07-21 05:02:48 +07:00
Nicolaj Egelund d31612c467 Update copy-helper script path for CocoaPods in Readme (#10) 2018-07-21 00:33:10 +07:00
25 changed files with 595 additions and 139 deletions
+1
View File
@@ -1,2 +1,3 @@
xcuserdata
project.xcworkspace
.build/
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
-14
View File
@@ -1,14 +0,0 @@
Pod::Spec.new do |s|
s.name = 'LaunchAtLogin'
s.version = '2.2.1'
s.summary = 'Add "Launch at Login" functionality to your sandboxed macOS app in seconds'
s.license = 'MIT'
s.homepage = 'https://github.com/sindresorhus/LaunchAtLogin'
s.social_media_url = 'https://twitter.com/sindresorhus'
s.authors = { 'Sindre Sorhus' => 'sindresorhus@gmail.com' }
s.source = { :git => 'https://github.com/sindresorhus/LaunchAtLogin.git', :tag => "v#{s.version}" }
s.source_files = 'LaunchAtLogin', 'LaunchAtLoginHelper'
s.resource = 'LaunchAtLogin/copy-helper.sh'
s.swift_version = '4.1'
s.platform = :macos, '10.12'
end
+77 -33
View File
@@ -3,15 +3,18 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 60;
objects = {
/* Begin PBXBuildFile section */
D92CFD2224C5D909005B91BE /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92CFD2124C5D909005B91BE /* Toggle.swift */; };
D9EF7E1D24BCF9E300A1E9AA /* copy-helper-swiftpm.sh in Resources */ = {isa = PBXBuildFile; fileRef = D9EF7E1C24BCF9E300A1E9AA /* copy-helper-swiftpm.sh */; };
E32E9B681EB87D7B000FEEE9 /* LaunchAtLogin.h in Headers */ = {isa = PBXBuildFile; fileRef = E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */; settings = {ATTRIBUTES = (Public, ); }; };
E32E9B6F1EB87DC5000FEEE9 /* LaunchAtLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */; };
E32E9B771EB87EA3000FEEE9 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32E9B761EB87EA3000FEEE9 /* main.swift */; };
E32E9B861EB8845E000FEEE9 /* LaunchAtLoginHelper.app in Resources */ = {isa = PBXBuildFile; fileRef = E32E9B741EB87EA3000FEEE9 /* LaunchAtLoginHelper.app */; };
E32E9B931EB889AE000FEEE9 /* copy-helper.sh in Resources */ = {isa = PBXBuildFile; fileRef = E32E9B921EB889AE000FEEE9 /* copy-helper.sh */; };
E3A6EB58249009C3004D7101 /* LaunchAtLogin.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = E3A6EB57249009C3004D7101 /* LaunchAtLogin.entitlements */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -25,6 +28,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
D92CFD2124C5D909005B91BE /* Toggle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Toggle.swift; sourceTree = "<group>"; usesTabs = 1; };
D9EF7E1C24BCF9E300A1E9AA /* copy-helper-swiftpm.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "copy-helper-swiftpm.sh"; sourceTree = "<group>"; };
E32E9B631EB87D7B000FEEE9 /* LaunchAtLogin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LaunchAtLogin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = LaunchAtLogin.h; sourceTree = "<group>"; usesTabs = 1; };
E32E9B671EB87D7B000FEEE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -33,6 +38,7 @@
E32E9B761EB87EA3000FEEE9 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = main.swift; sourceTree = "<group>"; usesTabs = 1; };
E32E9B7F1EB87EA3000FEEE9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E32E9B921EB889AE000FEEE9 /* copy-helper.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = "copy-helper.sh"; sourceTree = "<group>"; usesTabs = 1; };
E3A6EB57249009C3004D7101 /* LaunchAtLogin.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LaunchAtLogin.entitlements; sourceTree = "<group>"; };
E3B8C38A20C0003300272EC0 /* LaunchAtLoginHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LaunchAtLoginHelper.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -54,11 +60,19 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E32E9B591EB87D7B000FEEE9 = {
D9CFA59424C0FB5E005BC9E9 /* Sources */ = {
isa = PBXGroup;
children = (
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */,
E32E9B751EB87EA3000FEEE9 /* LaunchAtLoginHelper */,
);
path = Sources;
sourceTree = "<group>";
};
E32E9B591EB87D7B000FEEE9 = {
isa = PBXGroup;
children = (
D9CFA59424C0FB5E005BC9E9 /* Sources */,
E32E9B641EB87D7B000FEEE9 /* Products */,
);
sourceTree = "<group>";
@@ -76,10 +90,13 @@
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */ = {
isa = PBXGroup;
children = (
E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */,
E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */,
D9EF7E1C24BCF9E300A1E9AA /* copy-helper-swiftpm.sh */,
E32E9B921EB889AE000FEEE9 /* copy-helper.sh */,
E32E9B671EB87D7B000FEEE9 /* Info.plist */,
E3A6EB57249009C3004D7101 /* LaunchAtLogin.entitlements */,
E32E9B661EB87D7B000FEEE9 /* LaunchAtLogin.h */,
E32E9B6E1EB87DC5000FEEE9 /* LaunchAtLogin.swift */,
D92CFD2124C5D909005B91BE /* Toggle.swift */,
);
path = LaunchAtLogin;
sourceTree = "<group>";
@@ -150,18 +167,22 @@
E32E9B5A1EB87D7B000FEEE9 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0940;
LastUpgradeCheck = 1500;
ORGANIZATIONNAME = "Sindre Sorhus";
TargetAttributes = {
E32E9B621EB87D7B000FEEE9 = {
CreatedOnToolsVersion = 8.3.2;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
};
E32E9B731EB87EA3000FEEE9 = {
CreatedOnToolsVersion = 8.3.2;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
SystemCapabilities = {
com.apple.HardenedRuntime = {
enabled = 1;
};
com.apple.Sandbox = {
enabled = 1;
};
@@ -170,8 +191,8 @@
};
};
buildConfigurationList = E32E9B5D1EB87D7B000FEEE9 /* Build configuration list for PBXProject "LaunchAtLogin" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = English;
compatibilityVersion = "Xcode 15.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -195,6 +216,8 @@
files = (
E32E9B861EB8845E000FEEE9 /* LaunchAtLoginHelper.app in Resources */,
E32E9B931EB889AE000FEEE9 /* copy-helper.sh in Resources */,
D9EF7E1D24BCF9E300A1E9AA /* copy-helper-swiftpm.sh in Resources */,
E3A6EB58249009C3004D7101 /* LaunchAtLogin.entitlements in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -213,6 +236,7 @@
buildActionMask = 2147483647;
files = (
E32E9B6F1EB87DC5000FEEE9 /* LaunchAtLogin.swift in Sources */,
D92CFD2224C5D909005B91BE /* Toggle.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -239,6 +263,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@@ -260,6 +285,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -268,9 +294,11 @@
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -285,14 +313,14 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
VALID_ARCHS = x86_64;
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -302,6 +330,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
@@ -323,6 +352,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -331,9 +361,11 @@
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -342,12 +374,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALID_ARCHS = x86_64;
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
@@ -360,27 +392,30 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = YG56YK5RN5;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = LaunchAtLogin/Info.plist;
INFOPLIST_FILE = Sources/LaunchAtLogin/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 4.2.0;
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11";
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLogin;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = singlefile;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -391,69 +426,78 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = YG56YK5RN5;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_MODULE_VERIFIER = YES;
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = LaunchAtLogin/Info.plist;
INFOPLIST_FILE = Sources/LaunchAtLogin/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 4.2.0;
MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11";
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLogin;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
};
E32E9B811EB87EA3000FEEE9 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_ENTITLEMENTS = Sources/LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = YG56YK5RN5;
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
CURRENT_PROJECT_VERSION = 2;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/LaunchAtLoginHelper/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MARKETING_VERSION = 1.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLoginHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Debug;
};
E32E9B821EB87EA3000FEEE9 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
CODE_SIGN_ENTITLEMENTS = Sources/LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = YG56YK5RN5;
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
CURRENT_PROJECT_VERSION = 2;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = Sources/LaunchAtLoginHelper/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MARKETING_VERSION = 1.0.1;
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.LaunchAtLoginHelper;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -29,8 +29,6 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -51,8 +49,6 @@
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:LaunchAtLogin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
-19
View File
@@ -1,19 +0,0 @@
import Foundation
import ServiceManagement
public struct LaunchAtLogin {
private static let id = "\(Bundle.main.bundleIdentifier!)-LaunchAtLoginHelper"
public static var isEnabled: Bool {
get {
guard let jobs = (SMCopyAllJobDictionaries(kSMDomainUserLaunchd).takeRetainedValue() as? [[String: AnyObject]]) else {
return false
}
let job = jobs.first { $0["Label"] as! String == id }
return job?["OnDemand"] as? Bool ?? false
}
set {
SMLoginItemSetEnabled(id as CFString, newValue)
}
}
}
+30
View File
@@ -0,0 +1,30 @@
// swift-tools-version:5.9
import PackageDescription
let package = Package(
name: "LaunchAtLogin",
platforms: [
.macOS(.v10_13)
],
products: [
.library(
name: "LaunchAtLogin",
targets: ["LaunchAtLogin"]
)
],
targets: [
.target(
name: "LaunchAtLogin",
exclude: [
"Info.plist",
"copy-helper.sh"
],
resources: [
.copy("LaunchAtLogin.entitlements"),
.copy("copy-helper-swiftpm.sh"),
.copy("LaunchAtLoginHelper.zip"),
.copy("LaunchAtLoginHelper-with-runtime.zip")
]
)
]
)
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -15,12 +13,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.2.1</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
+155
View File
@@ -0,0 +1,155 @@
import Foundation
import ServiceManagement
import Combine
import os.log
private let hasMigratedKey = "LaunchAtLogin__hasMigrated"
public enum LaunchAtLogin {
@available(macOS 11, *)
private static let logger = Logger(subsystem: "com.sindresorhus.LaunchAtLogin", category: "main")
public static let kvo = KVO()
@available(macOS 10.15, *)
public static let observable = Observable()
@available(macOS 10.15, *)
private static let _publisher = CurrentValueSubject<Bool, Never>(isEnabled)
@available(macOS 10.15, *)
public static let publisher = _publisher.eraseToAnyPublisher()
private static let id = "\(Bundle.main.bundleIdentifier!)-LaunchAtLoginHelper"
private static var hasMigrated: Bool {
get { UserDefaults.standard.bool(forKey: hasMigratedKey) }
set {
UserDefaults.standard.set(true, forKey: hasMigratedKey)
}
}
public static func migrateIfNeeded() {
guard
#available(macOS 13, *),
!hasMigrated
else {
return
}
hasMigrated = true
if isEnabledLegacy {
isEnabledModern = true
}
unregisterLegacy()
}
public static var isEnabled: Bool {
get {
if #available(macOS 13, *) {
return isEnabledModern
} else {
return isEnabledLegacy
}
}
set {
if #available(macOS 10.15, *) {
observable.objectWillChange.send()
}
kvo.willChangeValue(for: \.isEnabled)
if #available(macOS 13, *) {
isEnabledModern = newValue
} else {
isEnabledLegacy = newValue
}
kvo.didChangeValue(for: \.isEnabled)
if #available(macOS 10.15, *) {
_publisher.send(newValue)
}
}
}
@available(macOS 13, *)
private static var isEnabledModern: Bool {
get { SMAppService.mainApp.status == .enabled }
set {
do {
if newValue {
if SMAppService.mainApp.status == .enabled {
try? SMAppService.mainApp.unregister()
}
try SMAppService.mainApp.register()
} else {
try SMAppService.mainApp.unregister()
}
} catch {
logger.error("Failed to \(newValue ? "enable" : "disable") launch at login: \(error.localizedDescription)")
}
}
}
private static var isEnabledLegacy: Bool {
get {
guard let jobs = (LaunchAtLogin.self as DeprecationWarningWorkaround.Type).jobsDict else {
return false
}
let job = jobs.first { ($0["Label"] as? String) == id }
return job?["OnDemand"] as? Bool ?? false
}
set {
SMLoginItemSetEnabled(id as CFString, newValue)
}
}
@available(macOS 13, *)
private static func unregisterLegacy() {
isEnabledLegacy = false
try? SMAppService.loginItem(identifier: id).unregister()
}
}
// MARK: - LaunchAtLoginObservable
extension LaunchAtLogin {
@available(macOS 10.15, *)
public final class Observable: ObservableObject {
public var isEnabled: Bool {
get { LaunchAtLogin.isEnabled }
set {
LaunchAtLogin.isEnabled = newValue
}
}
}
}
// MARK: - LaunchAtLoginKVO
extension LaunchAtLogin {
public final class KVO: NSObject {
@objc dynamic public var isEnabled: Bool {
get { LaunchAtLogin.isEnabled }
set {
LaunchAtLogin.isEnabled = newValue
}
}
}
}
private protocol DeprecationWarningWorkaround {
static var jobsDict: [[String: AnyObject]]? { get }
}
extension LaunchAtLogin: DeprecationWarningWorkaround {
// Workaround to silence "'SMCopyAllJobDictionaries' was deprecated in OS X 10.10" warning
// Radar: https://openradar.appspot.com/radar?id=5033815495933952
@available(*, deprecated)
static var jobsDict: [[String: AnyObject]]? {
SMCopyAllJobDictionaries(kSMDomainUserLaunchd)?.takeRetainedValue() as? [[String: AnyObject]]
}
}
Binary file not shown.
+80
View File
@@ -0,0 +1,80 @@
import SwiftUI
@available(macOS 10.15, *)
extension LaunchAtLogin {
/**
This package comes with a `LaunchAtLogin.Toggle` view which is like the built-in `Toggle` but with a predefined binding and label. Clicking the view toggles launch at login for your app.
```
struct ContentView: View {
var body: some View {
LaunchAtLogin.Toggle()
}
}
```
The default label is `"Launch at login"`, but it can be overridden for localization and other needs:
```
struct ContentView: View {
var body: some View {
LaunchAtLogin.Toggle {
Text("Launch at login")
}
}
}
```
*/
public struct Toggle<Label: View>: View {
@ObservedObject private var launchAtLogin = LaunchAtLogin.observable
private let label: Label
/**
Creates a toggle that displays a custom label.
- Parameters:
- label: A view that describes the purpose of the toggle.
*/
public init(@ViewBuilder label: () -> Label) {
self.label = label()
}
public var body: some View {
SwiftUI.Toggle(isOn: $launchAtLogin.isEnabled) { label }
}
}
}
@available(macOS 10.15, *)
extension LaunchAtLogin.Toggle<Text> {
/**
Creates a toggle that generates its label from a localized string key.
This initializer creates a ``Text`` view on your behalf with provided `titleKey`
- Parameters:
- titleKey: The key for the toggle's localized title, that describes the purpose of the toggle.
*/
public init(_ titleKey: LocalizedStringKey) {
label = Text(titleKey)
}
/**
Creates a toggle that generates its label from a string.
This initializer creates a `Text` view on your behalf with the provided `title`.
- Parameters:
- title: A string that describes the purpose of the toggle.
*/
public init(_ title: some StringProtocol) {
label = Text(title)
}
/**
Creates a toggle with the default title of `Launch at login`.
*/
public init() {
self.init("Launch at login")
}
}
+50
View File
@@ -0,0 +1,50 @@
#!/bin/bash
HELPER_CHECKSUM="0a3d09438fb595802d554ce0a7c4ba8e1d2d91d5170362adc965da82e70d74cb"
HELPER_CHECKSUM_RUNTIME="98ef556b490e02f4084a11d8a07c33a880177a9816b355885a11f58c95876d62"
verlte() {
[ "$1" = "`echo -e "$1\n$2" | sort -V | head -n1`" ]
}
if verlte "10.14.4" "$MACOSX_DEPLOYMENT_TARGET"; then
helper_name="LaunchAtLoginHelper"
checksum="$HELPER_CHECKSUM"
else
helper_name="LaunchAtLoginHelper-with-runtime"
checksum="$HELPER_CHECKSUM_RUNTIME"
fi
package_resources_path="$BUILT_PRODUCTS_DIR/LaunchAtLogin_LaunchAtLogin.bundle/Contents/Resources"
helper_path="$package_resources_path/$helper_name.zip"
contents_path="$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH"
login_items="$contents_path/Library/LoginItems"
login_helper_path="$login_items/LaunchAtLoginHelper.app"
rm -rf "$login_helper_path"
mkdir -p "$login_items"
# Verify SHA256 checksum of LaunchAtLoginHelper.
zip_checksum="$(shasum -a 256 "$helper_path" | awk '{print $1}')"
if [[ "$zip_checksum" != "$checksum" ]]; then
echo "Wrong checksum of LaunchAtLoginHelper"
exit 1
fi
unzip "$helper_path" -d "$login_items/"
defaults write "$login_helper_path/Contents/Info" CFBundleIdentifier -string "$PRODUCT_BUNDLE_IDENTIFIER-LaunchAtLoginHelper"
if [[ -n $CODE_SIGN_ENTITLEMENTS ]]; then
codesign --force --entitlements="$package_resources_path/LaunchAtLogin.entitlements" --deep --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$login_helper_path"
else
codesign --force --deep --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
fi
# If this is being built for multiple architectures, assume it is a release build and we should clean up.
if [[ $ONLY_ACTIVE_ARCH != "YES" ]]; then
rm -rf "$contents_path/Resources/LaunchAtLogin_LaunchAtLogin.bundle"
fi
@@ -9,9 +9,16 @@ mkdir -p "$helper_dir"
cp -rf "$origin_helper_path" "$helper_dir/"
defaults write "$helper_path/Contents/Info" CFBundleIdentifier -string "$PRODUCT_BUNDLE_IDENTIFIER-LaunchAtLoginHelper"
codesign --force --entitlements="$CODE_SIGN_ENTITLEMENTS" --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
if [[ $CONFIGURATION == "Release" ]]; then
if [[ -n $CODE_SIGN_ENTITLEMENTS ]]; then
codesign --force --entitlements="$(dirname "$origin_helper_path")/LaunchAtLogin.entitlements" --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
else
codesign --force --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
fi
# If this is being built for multiple architectures, assume it is a release build and we should clean up.
if [[ $ONLY_ACTIVE_ARCH != "YES" ]]; then
rm -rf "$origin_helper_path"
rm "$(dirname "$origin_helper_path")/copy-helper.sh"
rm "$(dirname "$origin_helper_path")/LaunchAtLogin.entitlements"
fi
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
@@ -13,17 +11,21 @@
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSBackgroundOnly</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
<string>MIT © Sindre Sorhus</string>
<key>LSBackgroundOnly</key>
<true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
@@ -0,0 +1,8 @@
<?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>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
@@ -1,13 +1,12 @@
import Cocoa
import AppKit
final class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
let bundleId = Bundle.main.bundleIdentifier!
// TODO: Make this more strict by only replacing at the end
let mainBundleId = bundleId.replacingOccurrences(of: "-LaunchAtLoginHelper", with: "")
let bundleIdentifier = Bundle.main.bundleIdentifier!
let mainBundleIdentifier = bundleIdentifier.replacingOccurrences(of: #"-LaunchAtLoginHelper$"#, with: "", options: .regularExpression)
// Ensure the app is not already running
guard NSRunningApplication.runningApplications(withBundleIdentifier: mainBundleId).isEmpty else {
// Ensures the app is not already running.
guard NSRunningApplication.runningApplications(withBundleIdentifier: mainBundleIdentifier).isEmpty else {
NSApp.terminate(nil)
return
}
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+9
View File
@@ -0,0 +1,9 @@
# Maintaining
## Rebuild helper binaries
1. If it's the non-`with-runtime` ZIP, set the target to macOS 10.14.4 first.
2. Set build configuration to “Release”.
3. Build the binary.
4. Find the binary in “Products” in the sidebar, ZIP it, and overwrite the existing ZIP file in the source directory.
5. Run `shasum -a 256 filename.zip` on the ZIP file and copy the hash into “copy-helper-swiftpm.sh”.
+149 -40
View File
@@ -1,57 +1,53 @@
# LaunchAtLogin
> Add "Launch at Login" functionality to your sandboxed macOS app in seconds
> Add Launch at Login functionality to your macOS app in seconds
It's usually quite a [convoluted and error-prone process](before-after.md) to add this. **No more!**
**If your app targets macOS 13 or later, check out [this modern version](https://github.com/sindresorhus/LaunchAtLogin-Modern) instead.**
It's App Store compatible and used in my [Lungo](https://blog.sindresorhus.com/lungo-b364a6c2745f) and [Battery Indicator](https://sindresorhus.com/battery-indicator) app.
It's usually quite a [convoluted and error-prone process](before-after.md) to add this (on macOS 12 and older). **No more!**
You might also find my [`create-dmg`](https://github.com/sindresorhus/create-dmg) project useful.
This package works with both sandboxed and non-sandboxed apps and it's App Store compatible and used in apps like [Plash](https://github.com/sindresorhus/Plash), [Dato](https://sindresorhus.com/dato), [Lungo](https://sindresorhus.com/lungo), and [Battery Indicator](https://sindresorhus.com/battery-indicator).
**This package uses the new [`SMAppService`](https://developer.apple.com/documentation/servicemanagement/smappservice/3945412-mainapp) on macOS 13+ and [`SMLoginItemSetEnabled`](https://developer.apple.com/documentation/servicemanagement/1501557-smloginitemsetenabled) on older macOS versions.**
### Why should I use this package now that [`SMAppService`](https://developer.apple.com/documentation/servicemanagement/smappservice/3945412-mainapp?changes=latest_minor) exists?
- Backwards compatibility with older macOS versions
- Nicer API
- Included SwiftUI component
## Requirements
- macOS 10.12+
- Xcode 9.3+
- Swift 4.1+
macOS 10.13+
## Install
#### Carthage
```
github "sindresorhus/LaunchAtLogin"
```
#### CocoaPods
```ruby
pod 'LaunchAtLogin'
```
<a href="https://www.patreon.com/sindresorhus">
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a>
Add `https://github.com/sindresorhus/LaunchAtLogin-Legacy` in the [“Swift Package Manager” tab in Xcode](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app).
## Usage
Add a new ["Run Script Phase"](http://stackoverflow.com/a/39633955/64949) below "Embed Frameworks" in "Build Phases" with the following:
**Skip this step if your app targets macOS 13 or later.**
Carthage:
Add a new [“Run Script Phase”](http://stackoverflow.com/a/39633955/64949) **below** (not into) “Copy Bundle Resources” in “Build Phases” with the following:
```sh
./Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh
"${BUILT_PRODUCTS_DIR}/LaunchAtLogin_LaunchAtLogin.bundle/Contents/Resources/copy-helper-swiftpm.sh"
```
CocoaPods:
And uncheck “Based on dependency analysis”.
```sh
./Pod/LaunchAtLogin/LaunchAtLogin/copy-helper.sh
```
The build phase cannot run with "User Script Sandboxing" enabled. With Xcode 15 or newer where it is enabled by default, disable "User Script Sandboxing" in build settings.
Use it in your app:
*(It needs some extra works to have our script to comply with the build phase sandbox.)*
*(I would name the run script `Copy “Launch at Login Helper”`)*
### Use it in your app
No need to store any state to UserDefaults.
*Note that the [Mac App Store guidelines](https://developer.apple.com/app-store/review/guidelines/) requires “launch at login” functionality to be enabled in response to a user action. This is usually solved by making it a preference that is disabled by default. Many apps also let the user activate it in a welcome screen.*
#### As static property
```swift
import LaunchAtLogin
@@ -65,21 +61,134 @@ print(LaunchAtLogin.isEnabled)
//=> true
```
*Note that the [Mac App Store guidelines](https://developer.apple.com/app-store/review/guidelines/) requires "launch at login" functionality to be enabled in response to a user action. This is usually solved by making it a preference that is disabled by default.*
#### SwiftUI
This package comes with a `LaunchAtLogin.Toggle` view which is like the built-in `Toggle` but with a predefined binding and label. Clicking the view toggles “launch at login” for your app.
```swift
struct ContentView: View {
var body: some View {
LaunchAtLogin.Toggle()
}
}
```
The default label is `"Launch at login"`, but it can be overridden for localization and other needs:
```swift
struct ContentView: View {
var body: some View {
LaunchAtLogin.Toggle {
Text("Launch at login")
}
}
}
```
Alternatively, you can use `LaunchAtLogin.observable` as a binding with `@ObservedObject`:
```swift
import SwiftUI
import LaunchAtLogin
struct ContentView: View {
@ObservedObject private var launchAtLogin = LaunchAtLogin.observable
var body: some View {
Toggle("Launch at login", isOn: $launchAtLogin.isEnabled)
}
}
```
#### Combine
Just subscribe to `LaunchAtLogin.publisher`:
```swift
import Combine
import LaunchAtLogin
final class ViewModel {
private var isLaunchAtLoginEnabled = LaunchAtLogin.isEnabled
private var cancellables = Set<AnyCancellable>()
func bind() {
LaunchAtLogin
.publisher
.assign(to: \.isLaunchAtLoginEnabled, on: self)
.store(in: &cancellables)
}
}
```
#### Swift Concurrency
Use [`LaunchAtLogin.publisher.values`](https://developer.apple.com/documentation/combine/publisher/values-1dm9r).
#### Storyboards
Bind the control to the `LaunchAtLogin.kvo` exposed property:
```swift
import Cocoa
import LaunchAtLogin
final class ViewController: NSViewController {
@objc dynamic var launchAtLogin = LaunchAtLogin.kvo
}
```
<img src="storyboard-binding.png" width="445">
## How does it work?
The framework bundles the helper app needed to launch your app and copies it into your app at build time.
On macOS 12 and earlier, the package bundles the helper app needed to launch your app and copies it into your app at build time. On macOS 13 and later, it calls the built-in API.
## FAQ
#### I'm getting a “No such file or directory” error when archiving my app
Please ensure that the LaunchAtLogin run script phase is still below the “Embed Frameworks” phase. The order could have been accidentally changed.
The build error usually presents itself as:
```
cp: […]/Resources/LaunchAtLoginHelper.app: No such file or directory
rm: […]/Resources/copy-helper.sh: No such file or directory
Command PhaseScriptExecution failed with a nonzero exit code
```
#### My app doesn't show up in “System Preferences Users & Groups Login Items”
[This is the expected behavior](https://stackoverflow.com/a/15104481/64949), unfortunately.
However, it will show there on macOS 13 and later.
#### My app doesn't launch at login when testing
This is usually caused by having one or more older builds of your app laying around somewhere on the system, and macOS picking one of those instead, which doesn't have the launch helper, and thus fails to start.
Some things you can try:
- Bump the version & build of your app so macOS is more likely to pick it.
- Delete the [`DerivedData` directory](https://mgrebenets.github.io/mobile%20ci/2015/02/01/xcode-derived-data).
- Ensure you don't have any other builds laying around somewhere.
Some helpful Stack Overflow answers:
- https://stackoverflow.com/a/43281810/64949
- https://stackoverflow.com/a/51683190/64949
- https://stackoverflow.com/a/53110832/64949
- https://stackoverflow.com/a/53110852/64949
#### I can't see the `LaunchAtLogin.bundle` in my debug build or I get a notarization error for developer ID distribution
As discussed [here](https://github.com/sindresorhus/LaunchAtLogin-Legacy/issues/50), this package tries to determine if you're making a release or debug build and clean up its install accordingly. If your debug build is missing the bundle or, conversely, your release build has the bundle and it causes a code signing error, that means this has failed.
The script's determination is based on the “Build Active Architecture Only” flag in build settings. If this is set to `YES`, then the script will package LaunchAtLogin for a debug build. You must set this flag to `NO` if you plan on distributing the build with codesigning.
## Related
- [Defaults](https://github.com/sindresorhus/Defaults) - Swifty and modern UserDefaults
- [Preferences](https://github.com/sindresorhus/Preferences) - Add a preferences window to your macOS app in minutes
- [KeyboardShortcuts](https://github.com/sindresorhus/KeyboardShortcuts) - Add user-customizable global keyboard shortcuts to your macOS app
- [DockProgress](https://github.com/sindresorhus/DockProgress) - Show progress in your app's Dock icon
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
- [create-dmg](https://github.com/sindresorhus/create-dmg) - Create a good-looking DMG for your macOS app in seconds
- [More…](https://github.com/search?q=user%3Asindresorhus+language%3Aswift+archived%3Afalse&type=repositories)
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB