Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #7 from HBehrens/master

compatible with IB plus some improvements in readme
  • Loading branch information...
commit 89a1626d806781622a7803d09897be43b383fdac 2 parents 04d1a25 + 50d4e3b
@alexzielenski authored
Showing with 55 additions and 36 deletions.
  1. +42 −14 README.md
  2. +1 −3 StartAtLoginController.h
  3. +12 −19 StartAtLoginController.m
View
56 README.md
@@ -1,12 +1,16 @@
# StartAtLoginController
-Easy to use controller that makes uses of the new ServiceManagement APIs. This is the required way to do login items for sandboxed Applications and soon Apple will make sandboxing required for all Mac App Store Apps so you should update early! (Works in non-sandboxed applications as well)
+Easy to use controller that makes use of the [Cocoa ServiceManagement APIs][SM]. This is the required way to do login items for sandboxed applications (required for all Mac App Store apps) and works in non-sandboxed applications as well.
-I have tested it on 10.7 and it supports removing login dictionaries. Also, entries set by this class do not appear to be showing up in the Accounts Panel of System Preferences.
+It's been tested on 10.7 and 10.8 (and should work on 10.6.6+). Entries set by this class do not appear in the Accounts Panel of System Preferences.
## HOW-TO
-You must create an instance of the controller and set the bundle for it to use to your helper bundle. (It must point to a helper bundle that has LSBackgroundOnly or LSUIElement set to YES in its Info.plist and put this bundle in Contents/Library/LoginItems).
+### Helper Bundle
+
+You must create an instance of the controller and set its bundle identifier to use to your helper bundle. (It must point to a helper bundle that has LSBackgroundOnly or LSUIElement set to YES in its Info.plist and put this bundle in Contents/Library/LoginItems).
+
+For sandboxed apps, sign it with the same entitlements and developer id. Also, your can only be launched at login if it has been copied to `/Applications`.
Here is an example of a helper bundle:
@@ -18,26 +22,47 @@ Here is an example of a helper bundle:
[NSApp terminate:nil];
}
-Then in your application you can set the bundle (identifier/path) of your helper app:
+You can find a decent tutorial about this at [Tim Schröder's blog post "The Launch At Login Sandbox Project"][Tutorial].
+
+### Main Application
+
+Then in your application
+
+ * add the framework `ServiceManagement` and
+ * add the files `StartAtLoginController.{h,m}`
+
+to your main app's target. You can use the controller either in code or with the interface builder.
+
+#### Programmatically
- StartAtLoginController loginController = [[StartAtLoginController alloc] init];
- [loginController setBundle:[NSBundle bundleWithPath:[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Contents/Library/LoginItems/AppHelper.app"]]];
+When using in code, create an instance of `StartAtLoginController` by providing the helper app's bundle identifier:
+
+ StartAtLoginController loginController = [[StartAtLoginController alloc] initWithIdentifier:@"your.app.helpers.bundle.id"];
-And now you can manipulate the Services Entry:
+Now, you can manipulate the Services Entry:
- [loginController setStartAtLogin: YES]; // adds the entry into LaunchServices and activates it
- //
- //
- [loginController remove]; // removes the entire entry from the services list
+ loginController.startAtLogin = YES; // adds the entry into LaunchServices and activates it
//
+ loginController.enabled = NO; // disables the entry on the services list
//
BOOL startsAtLogin = [loginController startAtLogin]; // gets the current enabled state
-Unfortunately you cannot use interface builder to bind your checkbox to this object since you need to set the bundle of your helper app. But you can make a property accessor for you helper app in your prefs controller and bind it through there.
+#### Interface Builder
+
+If you want to use the interface builder
+
+ * Place a NSObject (the blue box) into the nib window
+ * From the Inspector - **Identity Tab**
+ * Set the Class to `StartAtLoginController`
+ * Add the user defined runtime attribute `identifier` of type `String` and set it to your helper app's bundle identifier
+ * Place a Checkbox on your Window/View
+ * From the Inspector - **Bindings Tab**
+ * Unroll the > Value item
+ * Bind to `StartAtLoginController` with the Model Key Path `startAtLogin`
## REQUIREMENTS
-Works only on 10.6.6 and up
+Works only on 10.6.6 or later.
## LICENSE
@@ -63,4 +88,7 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+[SM]: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLoginItems.html
+[Tutorial]: http://blog.timschroeder.net/2012/07/03/the-launch-at-login-sandbox-project/
View
4 StartAtLoginController.h
@@ -31,9 +31,7 @@
@property (assign, nonatomic, readwrite) BOOL startAtLogin;
@property (assign, nonatomic, readwrite) BOOL enabled;
@property (copy, nonatomic, readwrite) NSString *identifier;
-@property (copy, nonatomic, readwrite) NSURL *url;
-- (id)initWithBundle:(NSBundle*)bndl;
-- (void)setBundle:(NSBundle*)bndl;
+-(id)initWithIdentifier:(NSString*)identifier;
@end
View
31 StartAtLoginController.m
@@ -26,12 +26,10 @@
@implementation StartAtLoginController
@synthesize identifier = _identifier;
-@synthesize url = _url;
#if !__has_feature(objc_arc)
- (void)dealloc {
self.identifier = nil;
- self.url = nil;
[super dealloc];
}
#endif
@@ -50,26 +48,21 @@ + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {
return automatic;
}
--(id)initWithBundle:(NSBundle*)bndl
-{
- self = [super init];
- if (self) {
- _enabled = NO;
- [self setBundle:bndl];
-
- // this method call initializes _enabled to the correct value as a side effect.
- [self startAtLogin];
-#if !defined(NDEBUG)
- NSLog(@"Launcher '%@' %@ configured to start at login",
- self.identifier, (_enabled ? @"is" : @"is not"));
-#endif
+-(id)initWithIdentifier:(NSString*)identifier {
+ self = [self init];
+ if(self) {
+ self.identifier = identifier;
}
return self;
}
-- (void)setBundle:(NSBundle*)bndl {
- self.identifier = [bndl bundleIdentifier];
- self.url = [bndl bundleURL];
+-(void)setIdentifier:(NSString *)identifier {
+ _identifier = identifier;
+ [self startAtLogin];
+#if !defined(NDEBUG)
+ NSLog(@"Launcher '%@' %@ configured to start at login",
+ self.identifier, (_enabled ? @"is" : @"is not"));
+#endif
}
- (BOOL)startAtLogin {
@@ -101,7 +94,7 @@ - (BOOL)startAtLogin {
}
- (void)setStartAtLogin:(BOOL)flag {
- if (!_identifier||!_url)
+ if (!_identifier)
return;
[self willChangeValueForKey:@"startAtLogin"];
Please sign in to comment.
Something went wrong with that request. Please try again.