Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a894d7992 | |||
| f326e3d9be | |||
| 22923d3354 | |||
| 0615d2f292 | |||
| cf9770cd43 | |||
| d811817ce3 | |||
| 8e28b5e5a9 | |||
| 7ad6331f9c | |||
| d473e16953 | |||
| fe1c59e088 | |||
| 05168c04c9 | |||
| e8171b3e38 | |||
| b35bfbde57 | |||
| b5d8e006bd | |||
| c34d3c7171 | |||
| afaacda259 | |||
| 6b16bcdf7d | |||
| f1cc3b8dd5 | |||
| b068272af8 | |||
| 389e09faf7 | |||
| 2badfdd7df | |||
| 0f39982b9d | |||
| 7f469e4511 | |||
| c16509926a | |||
| 3708ba7f4f | |||
| 08b9b397c8 | |||
| f7b255bc96 | |||
| 090e6e069b | |||
| 0fe5eb50ff | |||
| e7c842de54 |
@@ -1,4 +0,0 @@
|
||||
github: sindresorhus
|
||||
open_collective: sindresorhus
|
||||
patreon: sindresorhus
|
||||
custom: https://sindresorhus.com/donate
|
||||
@@ -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>
|
||||
@@ -3,10 +3,12 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 52;
|
||||
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 */; };
|
||||
@@ -26,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>"; };
|
||||
@@ -34,7 +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; name = LaunchAtLogin.entitlements; path = LaunchAtLogin/LaunchAtLogin.entitlements; sourceTree = "<group>"; };
|
||||
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 */
|
||||
|
||||
@@ -56,12 +60,19 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
D9CFA59424C0FB5E005BC9E9 /* Sources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */,
|
||||
E32E9B751EB87EA3000FEEE9 /* LaunchAtLoginHelper */,
|
||||
);
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E32E9B591EB87D7B000FEEE9 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E3A6EB57249009C3004D7101 /* LaunchAtLogin.entitlements */,
|
||||
E32E9B651EB87D7B000FEEE9 /* LaunchAtLogin */,
|
||||
E32E9B751EB87EA3000FEEE9 /* LaunchAtLoginHelper */,
|
||||
D9CFA59424C0FB5E005BC9E9 /* Sources */,
|
||||
E32E9B641EB87D7B000FEEE9 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@@ -79,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>";
|
||||
@@ -153,8 +167,9 @@
|
||||
E32E9B5A1EB87D7B000FEEE9 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 1020;
|
||||
LastUpgradeCheck = 1500;
|
||||
ORGANIZATIONNAME = "Sindre Sorhus";
|
||||
TargetAttributes = {
|
||||
E32E9B621EB87D7B000FEEE9 = {
|
||||
@@ -176,7 +191,7 @@
|
||||
};
|
||||
};
|
||||
buildConfigurationList = E32E9B5D1EB87D7B000FEEE9 /* Build configuration list for PBXProject "LaunchAtLogin" */;
|
||||
compatibilityVersion = "Xcode 11.0";
|
||||
compatibilityVersion = "Xcode 15.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
@@ -201,6 +216,7 @@
|
||||
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;
|
||||
@@ -220,6 +236,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E32E9B6F1EB87DC5000FEEE9 /* LaunchAtLogin.swift in Sources */,
|
||||
D92CFD2224C5D909005B91BE /* Toggle.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -246,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";
|
||||
@@ -267,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;
|
||||
@@ -275,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;
|
||||
@@ -292,7 +313,7 @@
|
||||
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;
|
||||
@@ -300,7 +321,6 @@
|
||||
SWIFT_COMPILATION_MODE = singlefile;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = x86_64;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
@@ -310,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";
|
||||
@@ -331,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;
|
||||
@@ -339,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;
|
||||
@@ -350,13 +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";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VALID_ARCHS = x86_64;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
@@ -369,20 +392,24 @@
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
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 = 3.0.1;
|
||||
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 = "";
|
||||
@@ -399,20 +426,24 @@
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
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 = 3.0.1;
|
||||
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 = "";
|
||||
@@ -423,17 +454,21 @@
|
||||
E32E9B811EB87EA3000FEEE9 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
|
||||
CODE_SIGN_ENTITLEMENTS = Sources/LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
|
||||
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 = "";
|
||||
@@ -444,17 +479,21 @@
|
||||
E32E9B821EB87EA3000FEEE9 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_ENTITLEMENTS = LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
|
||||
CODE_SIGN_ENTITLEMENTS = Sources/LaunchAtLoginHelper/LaunchAtLoginHelper.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = LaunchAtLoginHelper/Info.plist;
|
||||
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 = "";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1020"
|
||||
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 = "1020"
|
||||
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"
|
||||
|
||||
@@ -1,21 +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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -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.
Binary file not shown.
@@ -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")
|
||||
}
|
||||
}
|
||||
Executable
+50
@@ -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
|
||||
@@ -16,7 +16,8 @@ else
|
||||
codesign --force --options=runtime --sign="$EXPANDED_CODE_SIGN_IDENTITY_NAME" "$helper_path"
|
||||
fi
|
||||
|
||||
if [[ $CONFIGURATION == "Release" ]]; then
|
||||
# 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"
|
||||
@@ -11,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>
|
||||
@@ -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,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:
|
||||
|
||||
|
||||
@@ -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”.
|
||||
@@ -2,33 +2,52 @@
|
||||
|
||||
> 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 usually quite a [convoluted and error-prone process](before-after.md) to add this (on macOS 12 and older). **No more!**
|
||||
|
||||
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 11+
|
||||
- Swift 5+
|
||||
macOS 10.13+
|
||||
|
||||
## Install
|
||||
|
||||
#### Carthage
|
||||
|
||||
```
|
||||
github "sindresorhus/LaunchAtLogin"
|
||||
```
|
||||
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.**
|
||||
|
||||
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
|
||||
"${PROJECT_DIR}/Carthage/Build/Mac/LaunchAtLogin.framework/Resources/copy-helper.sh"
|
||||
"${BUILT_PRODUCTS_DIR}/LaunchAtLogin_LaunchAtLogin.bundle/Contents/Resources/copy-helper-swiftpm.sh"
|
||||
```
|
||||
|
||||
Use it in your app:
|
||||
And uncheck “Based on dependency analysis”.
|
||||
|
||||
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.
|
||||
|
||||
*(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
|
||||
@@ -42,24 +61,109 @@ print(LaunchAtLogin.isEnabled)
|
||||
//=> true
|
||||
```
|
||||
|
||||
No need to store any state to UserDefaults.
|
||||
#### SwiftUI
|
||||
|
||||
*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.*
|
||||
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
|
||||
|
||||
#### The size of my app increased after adding `LaunchAtLogin`
|
||||
#### I'm getting a “No such file or directory” error when archiving my app
|
||||
|
||||
The bundled launcher app is written in Swift and hence needs to embed the Swift runtime libraries. If your project targets macOS 10.14.4 or later, you can avoid embedding the Swift runtime libraries. First, open `./Carthage/Checkouts/LaunchAtLogin/LaunchAtLogin.xcodeproj` and set the deployment target to the same as your app, and then run `$ carthage build`. You'll have to do this each time you update `LaunchAtLogin`.
|
||||
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.
|
||||
@@ -75,19 +179,16 @@ Some helpful Stack Overflow answers:
|
||||
- https://stackoverflow.com/a/53110832/64949
|
||||
- https://stackoverflow.com/a/53110852/64949
|
||||
|
||||
#### Can you support CocoaPods?
|
||||
#### I can't see the `LaunchAtLogin.bundle` in my debug build or I get a notarization error for developer ID distribution
|
||||
|
||||
CocoaPods used to be supported, but [it did not work well](https://github.com/sindresorhus/LaunchAtLogin/issues/22) and there was no easy way to fix it, so support was dropped. Even though you mainly use CocoaPods, you can still use Carthage just for this package without any problems.
|
||||
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.
|
||||
|
||||
#### I'm getting a `'SMCopyAllJobDictionaries' was deprecated in OS X 10.10` warning
|
||||
|
||||
Apple deprecated that API without providing an alternative. Apple engineers have [stated that it's still the preferred API to use](https://github.com/alexzielenski/StartAtLoginController/issues/12#issuecomment-307525807). I plan to use it as long as it's available. There are workarounds I can implement if Apple ever removes the API, so rest assured, this module will be made to work even then. If you want to see this resolved, submit a [Feedback Assistant](https://feedbackassistant.apple.com) report with [the following text](https://github.com/feedback-assistant/reports/issues/16). There's unfortunately still [no way to suppress warnings in Swift](https://stackoverflow.com/a/32861678/64949).
|
||||
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
|
||||
- [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)
|
||||
- [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 |
Reference in New Issue
Block a user