diff --git a/KKPasscodeLock.podspec b/KKPasscodeLock.podspec new file mode 100644 index 0000000..5ddff98 --- /dev/null +++ b/KKPasscodeLock.podspec @@ -0,0 +1,14 @@ +Pod::Spec.new do |s| + s.name = 'KKPasscodeLock' + s.version = '0.1.5' + s.license = 'Apache 2.0' + s.summary = 'KKPasscodeLock is an iOS toolkit for adding a passcode view controller and passcode settings in ios apps' + s.homepage = 'https://github.com/aporat/KKPasscodeLock.git' + s.author = { 'Adar Porat' => 'adar.porat@gmail.com' } + s.source = { :git => 'https://github.com/aporat/KKPasscodeLock.git' } + s.platform = :ios + s.source_files = 'src/*.{h,m}' + s.resources = "src/KKPasscodeLock.bundle" + s.frameworks = 'QuartzCore', 'AudioToolbox', 'Security' + s.requires_arc = true +end diff --git a/README.mdown b/README.mdown index 223fca1..5c7b108 100644 --- a/README.mdown +++ b/README.mdown @@ -1,17 +1,33 @@

What is KKPasscodeLock?

+ +![](http://cocoapod-badges.herokuapp.com/v/KKPasscodeLock/badge.png)   ![](http://cocoapod-badges.herokuapp.com/p/KKPasscodeLock/badge.png) + + KKPasscodeLock is an iOS toolkit for adding a passcode view controller and passcode settings in ios apps. ![](https://github.com/aporat/KKPasscodeLock/raw/master/screenshots/iphone-1.png) +    ![](https://github.com/aporat/KKPasscodeLock/raw/master/screenshots/iphone-2.png) +    ![](https://github.com/aporat/KKPasscodeLock/raw/master/screenshots/ipad-1.png)

Main Features in KKPasscodeLock

-- Either a simple 4 digit passcode (using a numeric keyboard) or a free-text passcode +- Either a simple 4 digit passcode (using a numeric keyboard) or a free-text passcode (in development) - Supports universal apps (both iPhone and iPad) - Advanced passcode settings controller: set & change passcode, turn off/on passcode and passcode tries allowed - Passcode is saved securly in the device keychain + +

Using KKPasscodeLock

+ +Using this framework is really easy. + +- Add all the source files under the src folder, including KKPasscodeLock.bundle +- `#import "KKPasscodeLock.h"` where you need it. +- Add the `AudioToolbox.framework`, `Security.framework` and the `QuartzCore.framework` into your project +- See the usage of the passcode lock from the sample app +

Terms of Use

- Provided under the Apache 2.0 License diff --git a/example/Default-568h@2x.png b/example/Default-568h@2x.png new file mode 100644 index 0000000..0891b7a Binary files /dev/null and b/example/Default-568h@2x.png differ diff --git a/example/Default.png b/example/Default.png new file mode 100644 index 0000000..4c8ca6f Binary files /dev/null and b/example/Default.png differ diff --git a/example/Default@2x.png b/example/Default@2x.png new file mode 100644 index 0000000..35b84cf Binary files /dev/null and b/example/Default@2x.png differ diff --git a/example/KKPasscodeLock/AppDelegate.h b/example/KKPasscodeLock/AppDelegate.h index 235e555..d304cc1 100644 --- a/example/KKPasscodeLock/AppDelegate.h +++ b/example/KKPasscodeLock/AppDelegate.h @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,10 +16,11 @@ // #import +#import "KKPasscodeLock.h" -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; -@property (nonatomic, retain) IBOutlet UINavigationController *navigationController; +@property (nonatomic) IBOutlet UINavigationController *navigationController; @end diff --git a/example/KKPasscodeLock/AppDelegate.m b/example/KKPasscodeLock/AppDelegate.m index bed143f..13d992e 100644 --- a/example/KKPasscodeLock/AppDelegate.m +++ b/example/KKPasscodeLock/AppDelegate.m @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,36 +24,64 @@ @implementation AppDelegate @synthesize window = _window; @synthesize navigationController=_navigationController; -- (void)dealloc -{ - [_window release]; - [super dealloc]; -} - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - - [[KKPasscodeLock sharedLock] setDefaultSettings]; - - self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; - self.window.backgroundColor = [UIColor whiteColor]; - - RootViewController* vc = [[[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil] autorelease]; - - _navigationController = [[UINavigationController alloc] initWithRootViewController:vc]; - [self.window addSubview:_navigationController.view]; - - - [self.window makeKeyAndVisible]; - - - return YES; + + [[KKPasscodeLock sharedLock] setDefaultSettings]; + [KKPasscodeLock sharedLock].eraseOption = NO; + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + + RootViewController* vc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil]; + + _navigationController = [[UINavigationController alloc] initWithRootViewController:vc]; + [self.window setRootViewController:_navigationController]; + [self.window makeKeyAndVisible]; + + return YES; } - (void)applicationDidBecomeActive:(UIApplication *)application { - [[KKPasscodeLock sharedLock] showPasscodeController:self.navigationController]; + if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) { + KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil]; + vc.mode = KKPasscodeModeEnter; + vc.delegate = self; + + dispatch_async(dispatch_get_main_queue(),^ { + UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + nav.modalPresentationStyle = UIModalPresentationFormSheet; + nav.navigationBar.barStyle = UIBarStyleBlack; + nav.navigationBar.opaque = NO; + } else { + nav.navigationBar.tintColor = _navigationController.navigationBar.tintColor; + nav.navigationBar.translucent = _navigationController.navigationBar.translucent; + nav.navigationBar.opaque = _navigationController.navigationBar.opaque; + nav.navigationBar.barStyle = _navigationController.navigationBar.barStyle; + } + + [_navigationController presentModalViewController:nav animated:NO]; + }); + + } +} + +- (void)shouldEraseApplicationData:(KKPasscodeViewController*)viewController +{ + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"You have entered an incorrect passcode too many times. All account data in this app has been deleted." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alert show]; } +- (void)didPasscodeEnteredIncorrectly:(KKPasscodeViewController*)viewController +{ + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"You have entered an incorrect passcode too many times." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alert show]; +} + + @end diff --git a/example/KKPasscodeLock/KKPasscodeLock-Info.plist b/example/KKPasscodeLock/KKPasscodeLockDemo-Info.plist similarity index 94% rename from example/KKPasscodeLock/KKPasscodeLock-Info.plist rename to example/KKPasscodeLock/KKPasscodeLockDemo-Info.plist index 4c95cff..e476ef1 100644 --- a/example/KKPasscodeLock/KKPasscodeLock-Info.plist +++ b/example/KKPasscodeLock/KKPasscodeLockDemo-Info.plist @@ -11,7 +11,7 @@ CFBundleIconFiles CFBundleIdentifier - com.kosherpenguin.kosherkit.demo.${PRODUCT_NAME:rfc1034identifier} + com.kosherpenguin.passcode.demo.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/example/KKPasscodeLock/KKPasscodeLock-Prefix.pch b/example/KKPasscodeLock/KKPasscodeLockDemo-Prefix.pch similarity index 69% rename from example/KKPasscodeLock/KKPasscodeLock-Prefix.pch rename to example/KKPasscodeLock/KKPasscodeLockDemo-Prefix.pch index 26bc5cb..c2949e1 100644 --- a/example/KKPasscodeLock/KKPasscodeLock-Prefix.pch +++ b/example/KKPasscodeLock/KKPasscodeLockDemo-Prefix.pch @@ -1,5 +1,5 @@ // -// Prefix header for all source files of the 'APPasscodeLock' target in the 'APPasscodeLock' project +// Prefix header for all source files of the 'KKPasscodeLock' target in the 'KKPasscodeLock' project // #import diff --git a/example/KKPasscodeLock/RootViewController.h b/example/KKPasscodeLock/RootViewController.h index 567ba9e..08ca127 100755 --- a/example/KKPasscodeLock/RootViewController.h +++ b/example/KKPasscodeLock/RootViewController.h @@ -16,11 +16,9 @@ // #import +#import "KKPasscodeViewController.h" - -@interface RootViewController : UIViewController { - -} +@interface RootViewController : UIViewController - (IBAction)showPasscode:(id)sender; diff --git a/example/KKPasscodeLock/RootViewController.m b/example/KKPasscodeLock/RootViewController.m index 885486e..005771f 100755 --- a/example/KKPasscodeLock/RootViewController.m +++ b/example/KKPasscodeLock/RootViewController.m @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,19 +21,15 @@ @implementation RootViewController - (IBAction)showPasscode:(id)sender { - - SettingsViewController* settingsViewController = [[[SettingsViewController alloc] - initWithNibName:@"SettingsViewController" bundle:nil] autorelease]; - - UINavigationController* navController = [[[UINavigationController alloc] initWithRootViewController:settingsViewController] autorelease]; - - [self presentModalViewController:navController animated:YES]; - + + SettingsViewController* settingsViewController = [[SettingsViewController alloc] + initWithNibName:@"SettingsViewController" bundle:nil]; + + UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; + + [self presentModalViewController:navController animated:YES]; + } -- (void)dealloc -{ - [super dealloc]; -} @end diff --git a/example/KKPasscodeLock/RootViewController.xib b/example/KKPasscodeLock/RootViewController.xib index 114be7c..401cc80 100755 --- a/example/KKPasscodeLock/RootViewController.xib +++ b/example/KKPasscodeLock/RootViewController.xib @@ -1,21 +1,21 @@ - 1280 - 11C74 - 1938 - 1138.23 - 567.00 + 1536 + 12C3006 + 2844 + 1187.34 + 625.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 933 + 1930 YES + IBProxyObject IBUIButton - IBUIView IBUILabel - IBProxyObject + IBUIView YES @@ -46,14 +46,13 @@ {{53, 132}, {215, 37}} - NO IBCocoaTouchFramework 0 0 1 Show Settings Controller - + 3 MQA @@ -155,70 +154,14 @@ 14 16 + 280 {{0, 20}, {320, 460}} - - 10 - - 549453824 - {512, 1} - - YES - - YES - - - - TU0AKgAACAjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/wANAQAAAwAAAAECAAAAAQEAAwAAAAEAAQAAAQIAAwAAAAQAAAiqAQMAAwAA -AAEAAQAAAQYAAwAAAAEAAgAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEABAAAARYAAwAA -AAEAAQAAARcABAAAAAEAAAgAARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAQAAAiyAAAAAAAI -AAgACAAIAAEAAQABAAE - - - - - - - groupTableViewBackgroundColor - + IBCocoaTouchFramework @@ -307,7 +250,7 @@ AAgACAAIAAEAAQABAAE 8.IBPluginDependency 9.IBPluginDependency - + YES RootViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -361,7 +304,7 @@ AAgACAAIAAEAAQABAAE IBCocoaTouchFramework com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 @@ -369,6 +312,6 @@ AAgACAAIAAEAAQABAAE YES 3 - 933 + 1930 diff --git a/example/KKPasscodeLock/SettingsViewController.h b/example/KKPasscodeLock/SettingsViewController.h index d6db093..ce2bdbd 100755 --- a/example/KKPasscodeLock/SettingsViewController.h +++ b/example/KKPasscodeLock/SettingsViewController.h @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,7 +16,8 @@ // #import +#import "KKPasscodeSettingsViewController.h" -@interface SettingsViewController : UITableViewController +@interface SettingsViewController : UITableViewController @end diff --git a/example/KKPasscodeLock/SettingsViewController.m b/example/KKPasscodeLock/SettingsViewController.m index 36a6c86..87494eb 100755 --- a/example/KKPasscodeLock/SettingsViewController.m +++ b/example/KKPasscodeLock/SettingsViewController.m @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,69 +22,73 @@ @implementation SettingsViewController - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); } - (void)doneButtonPressed:(id)sender { - [self dismissModalViewControllerAnimated:YES]; + [self dismissModalViewControllerAnimated:YES]; } #pragma mark - View lifecycle - (void)viewDidLoad { - [super viewDidLoad]; - self.navigationItem.title = @"Settings"; - - - UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)]; - - self.navigationItem.rightBarButtonItem = doneButton; - [doneButton release]; + [super viewDidLoad]; + self.navigationItem.title = NSLocalizedString(@"Settings", nil); + + + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)]; + + self.navigationItem.rightBarButtonItem = doneButton; } #pragma mark - Table view data source - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { - return @""; + return @""; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 1; + return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - - static NSString *CellIdentifier = @"Cell"; - - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; - } - - if (indexPath.section == 0) { - cell.textLabel.text = @"Passcode Lock"; - if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) { - cell.detailTextLabel.text = @"On"; - } else { - cell.detailTextLabel.text = @"Off"; + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; } - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - return cell; + + if (indexPath.section == 0) { + cell.textLabel.text = NSLocalizedString(@"Passcode Lock", nil); + if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) { + cell.detailTextLabel.text = NSLocalizedString(@"On", nil); + } else { + cell.detailTextLabel.text = NSLocalizedString(@"Off", nil); + } + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } + return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == 0) { - KKPasscodeSettingsViewController *vc = [[KKPasscodeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - [self.navigationController pushViewController:vc animated:YES]; - [vc release]; - } + if (indexPath.section == 0) { + KKPasscodeSettingsViewController *vc = [[KKPasscodeSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; + vc.delegate = self; + [self.navigationController pushViewController:vc animated:YES]; + } +} + +- (void)didSettingsChanged:(KKPasscodeSettingsViewController*)viewController +{ + [self.tableView reloadData]; } @end diff --git a/example/KKPasscodeLock/de.lproj/InfoPlist.strings b/example/KKPasscodeLock/de.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/example/KKPasscodeLock/de.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/example/KKPasscodeLock/de.lproj/Localizable.strings b/example/KKPasscodeLock/de.lproj/Localizable.strings new file mode 100644 index 0000000..e1feb6e --- /dev/null +++ b/example/KKPasscodeLock/de.lproj/Localizable.strings @@ -0,0 +1,11 @@ +"Passcode Lock" = "Code-Sperre"; + +/* No comment provided by engineer. */ +"Off" = "Aus"; + +/* No comment provided by engineer. */ +"On" = "An"; + +/* No comment provided by engineer. */ +"Settings" = "Einstellungen"; + diff --git a/example/KKPasscodeLock/en.lproj/Localizable.strings b/example/KKPasscodeLock/en.lproj/Localizable.strings new file mode 100644 index 0000000..14fa401 --- /dev/null +++ b/example/KKPasscodeLock/en.lproj/Localizable.strings @@ -0,0 +1,11 @@ +"Passcode Lock" = "Passcode Lock"; + +/* No comment provided by engineer. */ +"Off" = "Off"; + +/* No comment provided by engineer. */ +"On" = "On"; + +/* No comment provided by engineer. */ +"Settings" = "Settings"; + diff --git a/example/KKPasscodeLock/he.lproj/InfoPlist.strings b/example/KKPasscodeLock/he.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/example/KKPasscodeLock/he.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/example/KKPasscodeLock/main.m b/example/KKPasscodeLock/main.m index fd8f9b4..6cfc991 100644 --- a/example/KKPasscodeLock/main.m +++ b/example/KKPasscodeLock/main.m @@ -1,9 +1,18 @@ // -// main.m -// APPasscodeLock +// Copyright 2011-2012 Kosher Penguin LLC +// Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // -// Created by Adar Porat on 1/16/12. -// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. // #import diff --git a/example/KKPasscodeLock/nl.lproj/InfoPlist.strings b/example/KKPasscodeLock/nl.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/example/KKPasscodeLock/nl.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/example/KKPasscodeLock.xcodeproj/project.pbxproj b/example/KKPasscodeLockDemo.xcodeproj/project.pbxproj similarity index 76% rename from example/KKPasscodeLock.xcodeproj/project.pbxproj rename to example/KKPasscodeLockDemo.xcodeproj/project.pbxproj index e7e3005..8362a85 100644 --- a/example/KKPasscodeLock.xcodeproj/project.pbxproj +++ b/example/KKPasscodeLockDemo.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 5303095F16611BF90004810F /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5303095E16611BF90004810F /* Default-568h@2x.png */; }; + 53DD2F8816A79FDB002582A0 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 53DD2F8616A79FDB002582A0 /* Default.png */; }; + 53DD2F8916A79FDB002582A0 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 53DD2F8716A79FDB002582A0 /* Default@2x.png */; }; 6D3E345214C4F54E0003B72B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D3E345114C4F54E0003B72B /* UIKit.framework */; }; 6D3E345414C4F54E0003B72B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D3E345314C4F54E0003B72B /* Foundation.framework */; }; 6D3E345614C4F54E0003B72B /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D3E345514C4F54E0003B72B /* CoreGraphics.framework */; }; @@ -23,21 +26,25 @@ 6DF13A6A14C6870B0069BBA5 /* KKPasscodeLock.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DF13A6014C6870B0069BBA5 /* KKPasscodeLock.m */; }; 6DF13A6B14C6870B0069BBA5 /* KKPasscodeSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DF13A6214C6870B0069BBA5 /* KKPasscodeSettingsViewController.m */; }; 6DF13A6C14C6870B0069BBA5 /* KKPasscodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DF13A6414C6870B0069BBA5 /* KKPasscodeViewController.m */; }; - 6DF13A6D14C6870B0069BBA5 /* passcode_square_empty.png in Resources */ = {isa = PBXBuildFile; fileRef = 6DF13A6514C6870B0069BBA5 /* passcode_square_empty.png */; }; - 6DF13A6E14C6870B0069BBA5 /* passcode_square_empty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6DF13A6614C6870B0069BBA5 /* passcode_square_empty@2x.png */; }; - 6DF13A6F14C6870B0069BBA5 /* passcode_square_filled.png in Resources */ = {isa = PBXBuildFile; fileRef = 6DF13A6714C6870B0069BBA5 /* passcode_square_filled.png */; }; - 6DF13A7014C6870B0069BBA5 /* passcode_square_filled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6DF13A6814C6870B0069BBA5 /* passcode_square_filled@2x.png */; }; + 6DFE33F714CF879E00E6EEA4 /* KKPasscodeLock.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6DFE33F614CF879E00E6EEA4 /* KKPasscodeLock.bundle */; }; + 6DFE344414CFBE8400E6EEA4 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6DFE344314CFBE8400E6EEA4 /* AudioToolbox.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 6D3E344D14C4F54E0003B72B /* KKPasscodeLock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KKPasscodeLock.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5303095E16611BF90004810F /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 5303097E16611F510004810F /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = ""; }; + 5303097F16611F580004810F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; + 5303098816612A310004810F /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/InfoPlist.strings; sourceTree = ""; }; + 53DD2F8616A79FDB002582A0 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 53DD2F8716A79FDB002582A0 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; + 6D3E344D14C4F54E0003B72B /* KKPasscodeLockDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KKPasscodeLockDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6D3E345114C4F54E0003B72B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 6D3E345314C4F54E0003B72B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6D3E345514C4F54E0003B72B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 6D3E345914C4F54E0003B72B /* KKPasscodeLock-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KKPasscodeLock-Info.plist"; sourceTree = ""; }; + 6D3E345914C4F54E0003B72B /* KKPasscodeLockDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KKPasscodeLockDemo-Info.plist"; sourceTree = ""; }; 6D3E345B14C4F54E0003B72B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 6D3E345D14C4F54E0003B72B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D3E345F14C4F54E0003B72B /* KKPasscodeLock-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KKPasscodeLock-Prefix.pch"; sourceTree = ""; }; + 6D3E345F14C4F54E0003B72B /* KKPasscodeLockDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KKPasscodeLockDemo-Prefix.pch"; sourceTree = ""; }; 6D3E346014C4F54E0003B72B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 6D3E346114C4F54E0003B72B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AppDelegate.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 6D3E34BA14C4F90B0003B72B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; @@ -51,15 +58,13 @@ 6DF13A5D14C6870B0069BBA5 /* KKKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKKeychain.h; path = ../../src/KKKeychain.h; sourceTree = ""; }; 6DF13A5E14C6870B0069BBA5 /* KKKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKKeychain.m; path = ../../src/KKKeychain.m; sourceTree = ""; }; 6DF13A5F14C6870B0069BBA5 /* KKPasscodeLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeLock.h; path = ../../src/KKPasscodeLock.h; sourceTree = ""; }; - 6DF13A6014C6870B0069BBA5 /* KKPasscodeLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeLock.m; path = ../../src/KKPasscodeLock.m; sourceTree = ""; }; + 6DF13A6014C6870B0069BBA5 /* KKPasscodeLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = KKPasscodeLock.m; path = ../../src/KKPasscodeLock.m; sourceTree = ""; }; 6DF13A6114C6870B0069BBA5 /* KKPasscodeSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeSettingsViewController.h; path = ../../src/KKPasscodeSettingsViewController.h; sourceTree = ""; }; - 6DF13A6214C6870B0069BBA5 /* KKPasscodeSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeSettingsViewController.m; path = ../../src/KKPasscodeSettingsViewController.m; sourceTree = ""; }; + 6DF13A6214C6870B0069BBA5 /* KKPasscodeSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = KKPasscodeSettingsViewController.m; path = ../../src/KKPasscodeSettingsViewController.m; sourceTree = ""; }; 6DF13A6314C6870B0069BBA5 /* KKPasscodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeViewController.h; path = ../../src/KKPasscodeViewController.h; sourceTree = ""; }; - 6DF13A6414C6870B0069BBA5 /* KKPasscodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeViewController.m; path = ../../src/KKPasscodeViewController.m; sourceTree = ""; }; - 6DF13A6514C6870B0069BBA5 /* passcode_square_empty.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = passcode_square_empty.png; path = ../../src/passcode_square_empty.png; sourceTree = ""; }; - 6DF13A6614C6870B0069BBA5 /* passcode_square_empty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "passcode_square_empty@2x.png"; path = "../../src/passcode_square_empty@2x.png"; sourceTree = ""; }; - 6DF13A6714C6870B0069BBA5 /* passcode_square_filled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = passcode_square_filled.png; path = ../../src/passcode_square_filled.png; sourceTree = ""; }; - 6DF13A6814C6870B0069BBA5 /* passcode_square_filled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "passcode_square_filled@2x.png"; path = "../../src/passcode_square_filled@2x.png"; sourceTree = ""; }; + 6DF13A6414C6870B0069BBA5 /* KKPasscodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = KKPasscodeViewController.m; path = ../../src/KKPasscodeViewController.m; sourceTree = ""; }; + 6DFE33F614CF879E00E6EEA4 /* KKPasscodeLock.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = KKPasscodeLock.bundle; path = ../../src/KKPasscodeLock.bundle; sourceTree = ""; }; + 6DFE344314CFBE8400E6EEA4 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -72,6 +77,7 @@ 6D3E345614C4F54E0003B72B /* CoreGraphics.framework in Frameworks */, 6D3E34BC14C4F90B0003B72B /* Security.framework in Frameworks */, 6D3E34BD14C4F90B0003B72B /* QuartzCore.framework in Frameworks */, + 6DFE344414CFBE8400E6EEA4 /* AudioToolbox.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -93,10 +99,10 @@ 6D2F0BD614C51D0300C1862D /* Supporting Files */ = { isa = PBXGroup; children = ( - 6D3E345914C4F54E0003B72B /* KKPasscodeLock-Info.plist */, + 6D3E345914C4F54E0003B72B /* KKPasscodeLockDemo-Info.plist */, 6D3E345A14C4F54E0003B72B /* InfoPlist.strings */, 6D3E345D14C4F54E0003B72B /* main.m */, - 6D3E345F14C4F54E0003B72B /* KKPasscodeLock-Prefix.pch */, + 6D3E345F14C4F54E0003B72B /* KKPasscodeLockDemo-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; @@ -104,6 +110,9 @@ 6D3E344214C4F54D0003B72B = { isa = PBXGroup; children = ( + 53DD2F8616A79FDB002582A0 /* Default.png */, + 53DD2F8716A79FDB002582A0 /* Default@2x.png */, + 5303095E16611BF90004810F /* Default-568h@2x.png */, 6D3E345714C4F54E0003B72B /* KKPasscodeLock */, 6D2F0BD414C51CCA00C1862D /* Demo App */, 6D3E345014C4F54E0003B72B /* Frameworks */, @@ -114,7 +123,7 @@ 6D3E344E14C4F54E0003B72B /* Products */ = { isa = PBXGroup; children = ( - 6D3E344D14C4F54E0003B72B /* KKPasscodeLock.app */, + 6D3E344D14C4F54E0003B72B /* KKPasscodeLockDemo.app */, ); name = Products; sourceTree = ""; @@ -122,6 +131,7 @@ 6D3E345014C4F54E0003B72B /* Frameworks */ = { isa = PBXGroup; children = ( + 6DFE344314CFBE8400E6EEA4 /* AudioToolbox.framework */, 6D3E34BA14C4F90B0003B72B /* Security.framework */, 6D3E34BB14C4F90B0003B72B /* QuartzCore.framework */, 6D3E345114C4F54E0003B72B /* UIKit.framework */, @@ -134,6 +144,7 @@ 6D3E345714C4F54E0003B72B /* KKPasscodeLock */ = { isa = PBXGroup; children = ( + 6DFE33F614CF879E00E6EEA4 /* KKPasscodeLock.bundle */, 6DF13A5D14C6870B0069BBA5 /* KKKeychain.h */, 6DF13A5E14C6870B0069BBA5 /* KKKeychain.m */, 6DF13A5F14C6870B0069BBA5 /* KKPasscodeLock.h */, @@ -142,10 +153,6 @@ 6DF13A6214C6870B0069BBA5 /* KKPasscodeSettingsViewController.m */, 6DF13A6314C6870B0069BBA5 /* KKPasscodeViewController.h */, 6DF13A6414C6870B0069BBA5 /* KKPasscodeViewController.m */, - 6DF13A6514C6870B0069BBA5 /* passcode_square_empty.png */, - 6DF13A6614C6870B0069BBA5 /* passcode_square_empty@2x.png */, - 6DF13A6714C6870B0069BBA5 /* passcode_square_filled.png */, - 6DF13A6814C6870B0069BBA5 /* passcode_square_filled@2x.png */, ); path = KKPasscodeLock; sourceTree = ""; @@ -182,9 +189,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 6D3E344C14C4F54D0003B72B /* KKPasscodeLock */ = { + 6D3E344C14C4F54D0003B72B /* KKPasscodeLockDemo */ = { isa = PBXNativeTarget; - buildConfigurationList = 6D3E346514C4F54E0003B72B /* Build configuration list for PBXNativeTarget "KKPasscodeLock" */; + buildConfigurationList = 6D3E346514C4F54E0003B72B /* Build configuration list for PBXNativeTarget "KKPasscodeLockDemo" */; buildPhases = ( 6D3E344914C4F54D0003B72B /* Sources */, 6D3E344A14C4F54D0003B72B /* Frameworks */, @@ -194,9 +201,9 @@ ); dependencies = ( ); - name = KKPasscodeLock; + name = KKPasscodeLockDemo; productName = KKPasscodeLock; - productReference = 6D3E344D14C4F54E0003B72B /* KKPasscodeLock.app */; + productReference = 6D3E344D14C4F54E0003B72B /* KKPasscodeLockDemo.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -205,21 +212,25 @@ 6D3E344414C4F54D0003B72B /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0430; + ORGANIZATIONNAME = "Kosher Penguin LLC"; }; - buildConfigurationList = 6D3E344714C4F54D0003B72B /* Build configuration list for PBXProject "KKPasscodeLock" */; + buildConfigurationList = 6D3E344714C4F54D0003B72B /* Build configuration list for PBXProject "KKPasscodeLockDemo" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, + nl, + de, + he, ); mainGroup = 6D3E344214C4F54D0003B72B; productRefGroup = 6D3E344E14C4F54E0003B72B /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 6D3E344C14C4F54D0003B72B /* KKPasscodeLock */, + 6D3E344C14C4F54D0003B72B /* KKPasscodeLockDemo */, ); }; /* End PBXProject section */ @@ -232,10 +243,10 @@ 6D3E345C14C4F54E0003B72B /* InfoPlist.strings in Resources */, 6D3E34D014C4F9910003B72B /* RootViewController.xib in Resources */, 6DF13A5C14C686FC0069BBA5 /* SettingsViewController.xib in Resources */, - 6DF13A6D14C6870B0069BBA5 /* passcode_square_empty.png in Resources */, - 6DF13A6E14C6870B0069BBA5 /* passcode_square_empty@2x.png in Resources */, - 6DF13A6F14C6870B0069BBA5 /* passcode_square_filled.png in Resources */, - 6DF13A7014C6870B0069BBA5 /* passcode_square_filled@2x.png in Resources */, + 6DFE33F714CF879E00E6EEA4 /* KKPasscodeLock.bundle in Resources */, + 5303095F16611BF90004810F /* Default-568h@2x.png in Resources */, + 53DD2F8816A79FDB002582A0 /* Default.png in Resources */, + 53DD2F8916A79FDB002582A0 /* Default@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -264,6 +275,9 @@ isa = PBXVariantGroup; children = ( 6D3E345B14C4F54E0003B72B /* en */, + 5303097E16611F510004810F /* nl */, + 5303097F16611F580004810F /* de */, + 5303098816612A310004810F /* he */, ); name = InfoPlist.strings; sourceTree = ""; @@ -319,11 +333,12 @@ 6D3E346614C4F54E0003B72B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLock-Prefix.pch"; - INFOPLIST_FILE = "KKPasscodeLock/KKPasscodeLock-Info.plist"; + GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLockDemo-Prefix.pch"; + INFOPLIST_FILE = "KKPasscodeLock/KKPasscodeLockDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 4.0; - PRODUCT_NAME = KKPasscodeLock; + PRODUCT_NAME = KKPasscodeLockDemo; WRAPPER_EXTENSION = app; }; name = Debug; @@ -331,11 +346,12 @@ 6D3E346714C4F54E0003B72B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLock-Prefix.pch"; - INFOPLIST_FILE = "KKPasscodeLock/KKPasscodeLock-Info.plist"; + GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLockDemo-Prefix.pch"; + INFOPLIST_FILE = "KKPasscodeLock/KKPasscodeLockDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 4.0; - PRODUCT_NAME = KKPasscodeLock; + PRODUCT_NAME = KKPasscodeLockDemo; WRAPPER_EXTENSION = app; }; name = Release; @@ -343,7 +359,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 6D3E344714C4F54D0003B72B /* Build configuration list for PBXProject "KKPasscodeLock" */ = { + 6D3E344714C4F54D0003B72B /* Build configuration list for PBXProject "KKPasscodeLockDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( 6D3E346314C4F54E0003B72B /* Debug */, @@ -352,7 +368,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6D3E346514C4F54E0003B72B /* Build configuration list for PBXNativeTarget "KKPasscodeLock" */ = { + 6D3E346514C4F54E0003B72B /* Build configuration list for PBXNativeTarget "KKPasscodeLockDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( 6D3E346614C4F54E0003B72B /* Debug */, diff --git a/src/KKKeychain.h b/src/KKKeychain.h index a3638b1..98fbdf7 100755 --- a/src/KKKeychain.h +++ b/src/KKKeychain.h @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,10 +17,10 @@ #import -@interface KKKeychain : NSObject { -} +@interface KKKeychain : NSObject + (BOOL)setString:(NSString*)string forKey:(NSString*)key; + + (NSString*)getStringForKey:(NSString*)key; @end diff --git a/src/KKKeychain.m b/src/KKKeychain.m index 15d2011..5d54618 100755 --- a/src/KKKeychain.m +++ b/src/KKKeychain.m @@ -1,5 +1,5 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,99 +18,86 @@ #import "KKKeychain.h" #import -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// @implementation KKKeychain - -/////////////////////////////////////////////////////////////////////////////////////////////////// -+ (NSString*)appName { ++ (NSString*)appName +{ NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSString *appName = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; if (!appName) { - appName = [bundle objectForInfoDictionaryKey:@"CFBundleName"]; + appName = [bundle objectForInfoDictionaryKey:@"CFBundleName"]; } - return appName; + return appName; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -+ (BOOL)setString:(NSString*)string forKey:(NSString*)key { ++ (BOOL)setString:(NSString*)string forKey:(NSString*)key +{ if (string == nil || key == nil) { return NO; } - - key = [NSString stringWithFormat:@"%@ - %@", [KKKeychain appName], key]; - - // First check if it already exists, by creating a search dictionary and requesting that - // nothing be returned, and performing the search anyway. + + key = [NSString stringWithFormat:@"%@ - %@", [KKKeychain appName], key]; + + // First check if it already exists, by creating a search dictionary and requesting that + // nothing be returned, and performing the search anyway. NSMutableDictionary *existsQueryDictionary = [NSMutableDictionary dictionary]; NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; - [existsQueryDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; + [existsQueryDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; // Add the keys to the search dict - [existsQueryDictionary setObject:@"service" forKey:(id)kSecAttrService]; - [existsQueryDictionary setObject:key forKey:(id)kSecAttrAccount]; - - OSStatus res = SecItemCopyMatching((CFDictionaryRef)existsQueryDictionary, NULL); + [existsQueryDictionary setObject:@"service" forKey:(__bridge id)kSecAttrService]; + [existsQueryDictionary setObject:key forKey:(__bridge id)kSecAttrAccount]; + + OSStatus res = SecItemCopyMatching((__bridge CFDictionaryRef) existsQueryDictionary, NULL); + if (res == errSecItemNotFound) { if (string != nil) { NSMutableDictionary *addDict = existsQueryDictionary; - [addDict setObject:data forKey:(id)kSecValueData]; - - res = SecItemAdd((CFDictionaryRef)addDict, NULL); - NSAssert1(res == errSecSuccess, @"Recieved %d from SecItemAdd!", res); + [addDict setObject:data forKey:(__bridge id)kSecValueData]; + + res = SecItemAdd((__bridge CFDictionaryRef)addDict, NULL); + NSAssert1(res == errSecSuccess, @"Recieved %ld from SecItemAdd!", (long) res); } } else if (res == errSecSuccess) { // Modify an existing one // Actually pull it now of the keychain at this point. - NSDictionary *attributeDict = [NSDictionary dictionaryWithObject:data forKey:(id)kSecValueData]; - - res = SecItemUpdate((CFDictionaryRef)existsQueryDictionary, (CFDictionaryRef)attributeDict); - NSAssert1(res == errSecSuccess, @"SecItemUpdated returned %d!", res); - + NSDictionary *attributeDict = [NSDictionary dictionaryWithObject:data forKey:(__bridge id)kSecValueData]; + res = SecItemUpdate((__bridge CFDictionaryRef)existsQueryDictionary, (__bridge CFDictionaryRef)attributeDict); + NSAssert1(res == errSecSuccess, @"SecItemUpdated returned %ld!", (long) res); } else { - NSAssert1(NO, @"Received %d from SecItemCopyMatching!", res); + NSAssert1(NO, @"Received %ld from SecItemCopyMatching!", (long) res); } - return YES; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -+ (NSString*)getStringForKey:(NSString*)key { - - key = [NSString stringWithFormat:@"%@ - %@", [KKKeychain appName], key]; - ++ (NSString*)getStringForKey:(NSString*)key +{ + key = [NSString stringWithFormat:@"%@ - %@", [KKKeychain appName], key]; NSMutableDictionary *existsQueryDictionary = [NSMutableDictionary dictionary]; - - [existsQueryDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; + [existsQueryDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; // Add the keys to the search dict - [existsQueryDictionary setObject:@"service" forKey:(id)kSecAttrService]; - [existsQueryDictionary setObject:key forKey:(id)kSecAttrAccount]; + [existsQueryDictionary setObject:@"service" forKey:(__bridge id)kSecAttrService]; + [existsQueryDictionary setObject:key forKey:(__bridge id)kSecAttrAccount]; // We want the data back! - NSData *data = nil; + CFTypeRef data = nil; - [existsQueryDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; - - OSStatus res = SecItemCopyMatching((CFDictionaryRef)existsQueryDictionary, (CFTypeRef *)&data); - [data autorelease]; + [existsQueryDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; + + OSStatus res = SecItemCopyMatching((__bridge CFDictionaryRef)existsQueryDictionary, &data); + if (res == errSecSuccess) { - NSString *string = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; + NSString *string = [[NSString alloc] initWithData:(__bridge NSData*)data encoding:NSUTF8StringEncoding]; return string; } else { - NSAssert1(res == errSecItemNotFound, @"SecItemCopyMatching returned %d!", res); - } + NSAssert1(res == errSecItemNotFound, @"SecItemCopyMatching returned %ld!", (long) res); + } return nil; } - @end diff --git a/src/KKPasscodeLock.bundle/box_empty.png b/src/KKPasscodeLock.bundle/box_empty.png new file mode 100644 index 0000000..09744d0 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_empty.png differ diff --git a/src/KKPasscodeLock.bundle/box_empty@2x.png b/src/KKPasscodeLock.bundle/box_empty@2x.png new file mode 100644 index 0000000..515072e Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_empty@2x.png differ diff --git a/src/KKPasscodeLock.bundle/box_empty_ios7.png b/src/KKPasscodeLock.bundle/box_empty_ios7.png new file mode 100644 index 0000000..5f927ec Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_empty_ios7.png differ diff --git a/src/KKPasscodeLock.bundle/box_empty_ios7@2x.png b/src/KKPasscodeLock.bundle/box_empty_ios7@2x.png new file mode 100644 index 0000000..ce79453 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_empty_ios7@2x.png differ diff --git a/src/KKPasscodeLock.bundle/box_filled.png b/src/KKPasscodeLock.bundle/box_filled.png new file mode 100644 index 0000000..e53fba4 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_filled.png differ diff --git a/src/KKPasscodeLock.bundle/box_filled@2x.png b/src/KKPasscodeLock.bundle/box_filled@2x.png new file mode 100644 index 0000000..dc0b683 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_filled@2x.png differ diff --git a/src/KKPasscodeLock.bundle/box_filled_ios7.png b/src/KKPasscodeLock.bundle/box_filled_ios7.png new file mode 100644 index 0000000..1ec3732 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_filled_ios7.png differ diff --git a/src/KKPasscodeLock.bundle/box_filled_ios7@2x.png b/src/KKPasscodeLock.bundle/box_filled_ios7@2x.png new file mode 100644 index 0000000..92b0732 Binary files /dev/null and b/src/KKPasscodeLock.bundle/box_filled_ios7@2x.png differ diff --git a/src/KKPasscodeLock.bundle/de.lproj/Localizable.strings b/src/KKPasscodeLock.bundle/de.lproj/Localizable.strings new file mode 100644 index 0000000..c9b03b2 Binary files /dev/null and b/src/KKPasscodeLock.bundle/de.lproj/Localizable.strings differ diff --git a/src/KKPasscodeLock.bundle/en.lproj/Localizable.strings b/src/KKPasscodeLock.bundle/en.lproj/Localizable.strings new file mode 100644 index 0000000..6d3ee10 Binary files /dev/null and b/src/KKPasscodeLock.bundle/en.lproj/Localizable.strings differ diff --git a/src/KKPasscodeLock.bundle/he.lproj/Localizable.strings b/src/KKPasscodeLock.bundle/he.lproj/Localizable.strings new file mode 100644 index 0000000..362f668 Binary files /dev/null and b/src/KKPasscodeLock.bundle/he.lproj/Localizable.strings differ diff --git a/src/KKPasscodeLock.bundle/nl.lproj/Localizable.strings b/src/KKPasscodeLock.bundle/nl.lproj/Localizable.strings new file mode 100644 index 0000000..712cea1 Binary files /dev/null and b/src/KKPasscodeLock.bundle/nl.lproj/Localizable.strings differ diff --git a/src/KKPasscodeLock.h b/src/KKPasscodeLock.h index 3c4397a..a14e0b8 100644 --- a/src/KKPasscodeLock.h +++ b/src/KKPasscodeLock.h @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -15,15 +15,66 @@ // limitations under the License. // +#define KKPasscodeLockLocalizedString(key, comment) [[KKPasscodeLock sharedLock] localizedStringForKey:(key) value:@""] + #import +#import "KKPasscodeViewController.h" + +extern CGFloat const kPasscodeBlockDisabled; -@interface KKPasscodeLock : NSObject +@interface KKPasscodeLock : NSObject { + + // whatever the erase option is enabled in the passcode settings + BOOL _eraseOption; + + // how many attemepts is user is allowed to have before the screen is locked + NSUInteger _attemptsAllowed; + + // the minimum time interval (in seconds) that has to pass before isPasscodeBlocked return FALSE again + NSTimeInterval _passcodeBlockInterval; +} +/** + * a shared object which can change the passcode settings and perform generic actions + */ + (KKPasscodeLock*)sharedLock; +/** + * checks if a passcode has to be displayed + */ +- (BOOL)isPasscodeRequired; + +/** + * checks if the passcode has been blocked due to too many failed attempts + */ +- (BOOL)isPasscodeBlocked; + +/** + * return an interval <= 0 if the passcode is not blocked or a value > 0 indicating the time remaining until the passcode can be unlocked + */ +- (NSTimeInterval)passcodeBlockedRemainingTime; + +/** + * returns a localized string from the framework's bundle + */ +- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value NS_FORMAT_ARGUMENT(1); +/** + * set the initial settings of the passcode settings + */ - (void)setDefaultSettings; -- (BOOL)isPasscodeRequired; -- (void)showPasscodeController:(UINavigationController*)navController; + +/** + * reset the passcode settings + */ +- (void)resetSettings; + +@property (nonatomic,assign) BOOL eraseOption; + +@property (nonatomic,assign) NSUInteger attemptsAllowed; + +@property (nonatomic,assign) NSTimeInterval passcodeBlockInterval; + +@property (nonatomic, strong, readonly) NSDateFormatter *dateFormatter; @end diff --git a/src/KKPasscodeLock.m b/src/KKPasscodeLock.m index 376d4ea..40e3dcc 100644 --- a/src/KKPasscodeLock.m +++ b/src/KKPasscodeLock.m @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -19,122 +19,121 @@ #import "KKKeychain.h" #import "KKPasscodeViewController.h" +CGFloat const kPasscodeBlockDisabled = MAXFLOAT; + static KKPasscodeLock *sharedLock = nil; +@interface KKPasscodeLock () + +@property (nonatomic, strong, readwrite) NSDateFormatter *dateFormatter; + +@end -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// @implementation KKPasscodeLock +@synthesize eraseOption = _eraseOption; +@synthesize attemptsAllowed = _attemptsAllowed; +@synthesize passcodeBlockInterval = _passcodeBlockInterval; -/////////////////////////////////////////////////////////////////////////////////////////////////// + (KKPasscodeLock*)sharedLock { - @synchronized(self) { - if (sharedLock == nil) { - sharedLock = [[self alloc] init]; - } - } - return sharedLock; + @synchronized(self) { + if (sharedLock == nil) { + sharedLock = [[self alloc] init]; + sharedLock.eraseOption = YES; + sharedLock.attemptsAllowed = 5; + sharedLock.passcodeBlockInterval = 600.0f; // 10 minutes default, kPasscodeBlockDisabled means disabled + } + } + return sharedLock; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)setDefaultSettings +- (void)setPasscodeBlockInterval:(NSTimeInterval)passcodeBlockInterval { - if (![KKKeychain getStringForKey:@"passcode_lock_passcode_on"]) { - [KKKeychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]; - } - - if (![KKKeychain getStringForKey:@"passcode_lock_simple_passcode_on"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_simple_passcode_on"]; - } - - if (![KKKeychain getStringForKey:@"passcode_lock_erase_data_on"]) { - [KKKeychain setString:@"NO" forKey:@"passcode_lock_erase_data_on"]; - } + _passcodeBlockInterval = passcodeBlockInterval; + if (_passcodeBlockInterval == kPasscodeBlockDisabled) { + [KKKeychain setString:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:0]] forKey:@"incorrect_passcode_datetime"]; + } } +- (NSDateFormatter *)dateFormatter +{ + if (!_dateFormatter) { + _dateFormatter = [[NSDateFormatter alloc] init]; + _dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'Z'"; + _dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + _dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + } + return _dateFormatter; +} -/////////////////////////////////////////////////////////////////////////////////////////////////// - (BOOL)isPasscodeRequired { - return [[KKKeychain getStringForKey:@"passcode_lock_passcode_on"] isEqualToString:@"YES"]; + return [[KKKeychain getStringForKey:@"passcode_on"] isEqualToString:@"YES"]; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)presentAndRelease:(NSTimer *)timer +- (BOOL)isPasscodeBlocked { - UIViewController *vc = [timer.userInfo objectForKey:@"vc"]; - UINavigationController *navController = [timer.userInfo objectForKey:@"nav"]; - - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - nav.modalPresentationStyle = UIModalPresentationFormSheet; - nav.navigationBar.barStyle = UIBarStyleBlack; - nav.navigationBar.opaque = NO; - } else { - nav.navigationBar.tintColor = navController.navigationBar.tintColor; - nav.navigationBar.translucent = navController.navigationBar.translucent; - nav.navigationBar.opaque = navController.navigationBar.opaque; - nav.navigationBar.barStyle = navController.navigationBar.barStyle; - } - - [navController presentModalViewController:nav animated:YES]; - [nav release]; - - - [vc release]; + return [self passcodeBlockedRemainingTime] > 0.0f; } +- (NSTimeInterval)passcodeBlockedRemainingTime +{ + if (self.passcodeBlockInterval == kPasscodeBlockDisabled) { + return 0.0f; // Disabled, we don't need to check + } else { + NSString *lastPasscodeLock = [KKKeychain getStringForKey:@"incorrect_passcode_datetime"]; + + NSDate *lastPasscodeLockDate = lastPasscodeLock.length ? [self.dateFormatter dateFromString:lastPasscodeLock] : nil; + + if (lastPasscodeLockDate) { + return self.passcodeBlockInterval - [[NSDate date] timeIntervalSinceDate:lastPasscodeLockDate]; + } else { + return 0.0f; // Passcode is not blocked + } + } +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)showPasscodeController:(UINavigationController*)navController +- (void)setDefaultSettings { - if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) { - KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil]; - vc.mode = KKPasscodeModeEnter; - //vc.rootViewController = self; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - vc.modalPresentationStyle = UIModalPresentationFullScreen; - } + if (![KKKeychain getStringForKey:@"passcode_on"]) { + [KKKeychain setString:@"NO" forKey:@"passcode_on"]; + } + + if (![KKKeychain getStringForKey:@"erase_data_on"]) { + [KKKeychain setString:@"NO" forKey:@"erase_data_on"]; + } - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - for (UIViewController *svc in navController.viewControllers) { - svc.view.alpha = 0.0; - } - - NSDictionary* userinfo = [NSDictionary dictionaryWithObjectsAndKeys: - @"vc", vc, - @"nav", navController, nil]; - - [NSTimer scheduledTimerWithTimeInterval:0.3 target:self - selector:@selector(presentAndRelease:) userInfo: - userinfo repeats:NO]; - - } else { - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - nav.modalPresentationStyle = UIModalPresentationFormSheet; - nav.navigationBar.barStyle = UIBarStyleBlack; - nav.navigationBar.opaque = NO; - } else { - nav.navigationBar.tintColor = navController.navigationBar.tintColor; - nav.navigationBar.translucent = navController.navigationBar.translucent; - nav.navigationBar.opaque = navController.navigationBar.opaque; - nav.navigationBar.barStyle = navController.navigationBar.barStyle; - } - - [navController presentModalViewController:nav animated:NO]; - [nav release]; - [vc release]; + if (![KKKeychain getStringForKey:@"failedAttemptsCount"]) { + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + } + + if (![KKKeychain getStringForKey:@"incorrect_passcode_datetime"]) { + [KKKeychain setString:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:0]] forKey:@"incorrect_passcode_datetime"]; + } +} + +- (void)resetSettings +{ + [KKKeychain setString:@"NO" forKey:@"passcode_on"]; + [KKKeychain setString:@"NO" forKey:@"erase_data_on"]; + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + [KKKeychain setString:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:0]] forKey:@"incorrect_passcode_datetime"]; +} + +- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value +{ + static NSBundle *bundle = nil; + if (bundle == nil) + { + NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"KKPasscodeLock" ofType:@"bundle"]; + bundle = [NSBundle bundleWithPath:bundlePath] ?: [NSBundle mainBundle]; } - } + + value = [bundle localizedStringForKey:key value:value table:nil]; + return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil]; } + @end diff --git a/src/KKPasscodeSettingsViewController.h b/src/KKPasscodeSettingsViewController.h index 684760d..8677acb 100755 --- a/src/KKPasscodeSettingsViewController.h +++ b/src/KKPasscodeSettingsViewController.h @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -16,14 +16,38 @@ // #import +#import "KKPasscodeViewController.h" -@interface KKPasscodeSettingsViewController : UITableViewController { - UISwitch* _simplePasscodeSwitch; - UISwitch* _eraseDataSwitch; - - BOOL _passcodeLockOn; - BOOL _simplePasscodeOn; - BOOL _eraseDataOn; +@class KKPasscodeSettingsViewController; + +@protocol KKPasscodeSettingsViewControllerDelegate + +@optional + +/** + * called when the passcode settings (either turned on/off) is changed + */ +- (void)didSettingsChanged:(KKPasscodeSettingsViewController*)viewController; + +@end + +@interface KKPasscodeSettingsViewController : UITableViewController { + + // delegate which notified then the passcode is turned on/off + id __unsafe_unretained _delegate; + + // the erase content switch. + UISwitch* _eraseDataSwitch; + + // whatever the passcode lock is turned on or off + BOOL _passcodeLockOn; + + // whatever the erase data option is turned on or off + BOOL _eraseDataOn; } +@property (nonatomic) Class passcodeViewControllerClass; + +@property (nonatomic, unsafe_unretained) id delegate; +@property (nonatomic, unsafe_unretained) id passcodeViewControllerDelegate; @end diff --git a/src/KKPasscodeSettingsViewController.m b/src/KKPasscodeSettingsViewController.m index c7a7912..9eb6fa1 100755 --- a/src/KKPasscodeSettingsViewController.m +++ b/src/KKPasscodeSettingsViewController.m @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -18,287 +18,359 @@ #import "KKPasscodeSettingsViewController.h" #import "KKKeychain.h" #import "KKPasscodeViewController.h" -#import "SettingsViewController.h" +#import "KKPasscodeLock.h" -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// @implementation KKPasscodeSettingsViewController +@synthesize delegate = _delegate; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark UIViewController +#pragma mark Properties - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)viewDidLoad +- (void)setPasscodeViewControllerClass:(Class)passcodeViewControllerClass { - [super viewDidLoad]; - self.navigationItem.title = @"Passcode Lock"; - - _simplePasscodeSwitch = [[UISwitch alloc] init]; - [_simplePasscodeSwitch addTarget:self action:@selector(simplePasscodeSwitchChanged:) forControlEvents:UIControlEventValueChanged]; - - _eraseDataSwitch = [[UISwitch alloc] init]; - [_eraseDataSwitch addTarget:self action:@selector(eraseDataSwitchChanged:) forControlEvents:UIControlEventValueChanged]; + if ([passcodeViewControllerClass isSubclassOfClass:[KKPasscodeViewController class]]) { + _passcodeViewControllerClass = passcodeViewControllerClass; + } } +#pragma mark - +#pragma mark Initialization -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)viewWillAppear:(BOOL)animated +- (id)init { - [super viewWillAppear:animated]; - _passcodeLockOn = [[KKKeychain getStringForKey:@"passcode_lock_passcode_on"] isEqualToString:@"YES"]; - _simplePasscodeOn = [[KKKeychain getStringForKey:@"passcode_lock_simple_passcode_on"] isEqualToString:@"YES"]; - _eraseDataOn = [[KKKeychain getStringForKey:@"passcode_lock_erase_data_on"] isEqualToString:@"YES"]; - _simplePasscodeSwitch.on = _simplePasscodeOn; - _eraseDataSwitch.on = _eraseDataOn; + if (self = [super init]) { + self.passcodeViewControllerClass = [KKPasscodeViewController class]; + } + return self; } +- (id)initWithStyle:(UITableViewStyle)style +{ + if (self = [super initWithStyle:style]) { + self.passcodeViewControllerClass = [KKPasscodeViewController class]; + } + return self; +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); + if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { + self.passcodeViewControllerClass = [KKPasscodeViewController class]; + } + return self; } +- (id)initWithCoder:(NSCoder *)aDecoder +{ + if (self = [super initWithCoder:aDecoder]) { + self.passcodeViewControllerClass = [KKPasscodeViewController class]; + } + return self; +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark UISwitch +#pragma mark UIViewController methods -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)simplePasscodeSwitchChanged:(id)sender +- (void)viewDidLoad { - _simplePasscodeOn = _simplePasscodeSwitch.on; - if (_simplePasscodeOn) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_simple_passcode_on"]; - } else { - [KKKeychain setString:@"NO" forKey:@"passcode_lock_simple_passcode_on"]; - } + [super viewDidLoad]; + self.navigationItem.title = KKPasscodeLockLocalizedString(@"Passcode Lock", @""); + + _eraseDataSwitch = [[UISwitch alloc] init]; + [_eraseDataSwitch addTarget:self action:@selector(eraseDataSwitchChanged:) forControlEvents:UIControlEventValueChanged]; } +- (void)viewDidUnload +{ + _eraseDataSwitch = nil; + + [super viewDidUnload]; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + _passcodeLockOn = [[KKKeychain getStringForKey:@"passcode_on"] isEqualToString:@"YES"]; + _eraseDataOn = [[KKKeychain getStringForKey:@"erase_data_on"] isEqualToString:@"YES"]; + _eraseDataSwitch.on = _eraseDataOn; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +{ + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark UIActionSheetDelegate +#pragma mark UIActionSheetDelegate methods +- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if (buttonIndex == 0) { + [self enableEraseDataHandler]; + } else { + [self disableEraseDataHandler]; + } +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex +- (void)eraseDataSwitchChanged:(id)sender { - if (buttonIndex == 0) { - _eraseDataOn = YES; - [KKKeychain setString:@"YES" forKey:@"passcode_lock_erase_data_on"]; - } else { - _eraseDataOn = NO; - [KKKeychain setString:@"NO" forKey:@"passcode_lock_erase_data_on"]; - } - [_eraseDataSwitch setOn:_eraseDataOn animated:YES]; + if (_eraseDataSwitch.on) { + NSString* title = [NSString stringWithFormat:KKPasscodeLockLocalizedString(@"All data in this app will be erased after %d failed passcode attempts.", @""), [[KKPasscodeLock sharedLock] attemptsAllowed]]; + + if ((floor(NSFoundationVersionNumber) <= 1047.25)) { + UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:KKPasscodeLockLocalizedString(@"Cancel", @"") destructiveButtonTitle:KKPasscodeLockLocalizedString(@"Enable", @"") otherButtonTitles:nil]; + [sheet showInView:self.view]; + } else { + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:nil + preferredStyle:UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? UIAlertControllerStyleAlert : UIAlertControllerStyleActionSheet]; + + [alertController addAction:[UIAlertAction actionWithTitle:KKPasscodeLockLocalizedString(@"Enable", @"") style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { + [self enableEraseDataHandler]; + }]]; + + [alertController addAction:[UIAlertAction actionWithTitle:KKPasscodeLockLocalizedString(@"Cancel", @"") style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { + [self disableEraseDataHandler]; + }]]; + + [self presentViewController:alertController animated:YES completion:nil]; + } + + } else { + _eraseDataOn = NO; + [KKKeychain setString:@"NO" forKey:@"erase_data_on"]; + } } +- (void)enableEraseDataHandler +{ + _eraseDataOn = YES; + [KKKeychain setString:@"YES" forKey:@"erase_data_on"]; + [_eraseDataSwitch setOn:_eraseDataOn animated:YES]; +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)eraseDataSwitchChanged:(id)sender { - if (_eraseDataSwitch.on) { - UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"All data in this app will be erased after 10 failed passcode attempts." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Enable" otherButtonTitles:nil]; - [sheet showInView:self.view]; - [sheet release]; - } else { +- (void)disableEraseDataHandler +{ _eraseDataOn = NO; - [KKKeychain setString:@"NO" forKey:@"passcode_lock_erase_data_on"]; - } + [KKKeychain setString:@"NO" forKey:@"erase_data_on"]; + [_eraseDataSwitch setOn:_eraseDataOn animated:YES]; } - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark Table view data source - +#pragma mark UITableViewDataSource methods -/////////////////////////////////////////////////////////////////////////////////////////////////// - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 4; + if ([[KKPasscodeLock sharedLock] eraseOption]) { + return 2; + } + + return 1; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 1; + if (section==0) { + return 2; + } + + return 1; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { - if (section == 2) { - return @"A simple passcode is a 4 digit number."; - } else if (section == 3) { - return @"Erase all data in this app after 10 failed passcode attempts."; - } else { - return @""; - } + if (section == 1) { + return [NSString stringWithFormat:KKPasscodeLockLocalizedString(@"Erase all content in the app after %d failed passcode attempts.", @""), [[KKPasscodeLock sharedLock] attemptsAllowed]];; + } else { + return @""; + } } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (UITableViewCell *)tableView:(UITableView *)tableView - cellForRowAtIndexPath:(NSIndexPath *)indexPath +- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { - - static NSString *CellIdentifier = @"Cell"; - - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; - } - - if (indexPath.section == 0) { - if (_passcodeLockOn) { - cell.textLabel.text = @"Turn Passcode Off"; - } else { - cell.textLabel.text = @"Turn Passcode On"; - } - cell.textLabel.textColor = [UIColor blackColor]; - cell.textLabel.textAlignment = UITextAlignmentCenter; + static NSString *CellIdentifier = @"KKPasscodeSettingsCell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + } + cell.accessoryView = nil; cell.selectionStyle = UITableViewCellSelectionStyleBlue; - } else if (indexPath.section == 1) { - cell.textLabel.text = @"Change Passcode"; - if (_passcodeLockOn) { - cell.textLabel.textColor = [UIColor blackColor]; - cell.selectionStyle = UITableViewCellSelectionStyleBlue; - } else { - cell.textLabel.textColor = [UIColor grayColor]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - } - cell.textLabel.textAlignment = UITextAlignmentCenter; - cell.accessoryView = nil; - } else if (indexPath.section == 2) { - cell.textLabel.text = @"Simple Passcode"; - cell.textLabel.textColor = [UIColor blackColor]; - cell.textLabel.textAlignment = UITextAlignmentLeft; - cell.accessoryView = _simplePasscodeSwitch; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - if (_passcodeLockOn) { - cell.textLabel.textColor = [UIColor grayColor]; - _simplePasscodeSwitch.enabled = NO; - } else { - cell.textLabel.textColor = [UIColor blackColor]; - _simplePasscodeSwitch.enabled = YES; - } - } else if (indexPath.section == 3) { - cell.textLabel.text = @"Erase Data"; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 cell.textLabel.textAlignment = UITextAlignmentLeft; - cell.accessoryView = _eraseDataSwitch; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - if (_passcodeLockOn) { - cell.textLabel.textColor = [UIColor blackColor]; - _eraseDataSwitch.enabled = YES; - } else { - cell.textLabel.textColor = [UIColor grayColor]; - _eraseDataSwitch.enabled = NO; - } - } - - return cell; +#else + cell.textLabel.textAlignment = NSTextAlignmentLeft; +#endif + + cell.textLabel.textColor = [UIColor blackColor]; + + + if (indexPath.section == 0) { + + if (indexPath.row == 0) { + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + cell.textLabel.textAlignment = UITextAlignmentCenter; +#else + cell.textLabel.textAlignment = NSTextAlignmentCenter; +#endif + + if (_passcodeLockOn) { + cell.textLabel.text = KKPasscodeLockLocalizedString(@"Turn Passcode Off", @""); + } else { + cell.textLabel.text = KKPasscodeLockLocalizedString(@"Turn Passcode On", @""); + } + } else { + cell.textLabel.text = KKPasscodeLockLocalizedString(@"Change Passcode", @""); + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + cell.textLabel.textAlignment = UITextAlignmentCenter; +#else + cell.textLabel.textAlignment = NSTextAlignmentCenter; +#endif + + if (!_passcodeLockOn) { + cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.textLabel.textColor = [UIColor grayColor]; + } + + } + } else if (indexPath.section == 1) { + cell.textLabel.text = KKPasscodeLockLocalizedString(@"Erase Data", @""); + cell.accessoryView = _eraseDataSwitch; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + if (_passcodeLockOn) { + cell.textLabel.textColor = [UIColor blackColor]; + _eraseDataSwitch.enabled = YES; + } else { + cell.textLabel.textColor = [UIColor grayColor]; + _eraseDataSwitch.enabled = NO; + } + } + + return cell; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark Table view delegate - +#pragma mark UITableViewDelegate methods -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath { - if (indexPath.section == 0) { - KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil - bundle:nil]; - if (_passcodeLockOn) { - vc.mode = KKPasscodeModeDisabled; - } else { - vc.mode = KKPasscodeModeSet; - } - vc.passcodeLockViewController = self; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - vc.modalPresentationStyle = UIModalPresentationFormSheet; - } - - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - + if (indexPath.section == 0 && indexPath.row == 0) { + KKPasscodeViewController* vc = [[self.passcodeViewControllerClass alloc] initWithNibName:nil + bundle:nil]; + vc.delegate = self; + + if (_passcodeLockOn) { + vc.mode = KKPasscodeModeDisabled; + } else { + vc.mode = KKPasscodeModeSet; + } + + UINavigationController *nav = [[UINavigationController alloc] + initWithNavigationBarClass:[self.navigationController.navigationBar class] + toolbarClass:[self.navigationController.toolbar class]]; + nav.viewControllers = @[vc]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + nav.modalPresentationStyle = UIModalPresentationFormSheet; + nav.navigationBar.barStyle = UIBarStyleBlack; + nav.navigationBar.opaque = NO; + } else { + nav.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; + nav.navigationBar.translucent = self.navigationController.navigationBar.translucent; + nav.navigationBar.opaque = self.navigationController.navigationBar.opaque; + nav.navigationBar.barStyle = self.navigationController.navigationBar.barStyle; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self.navigationController presentModalViewController:nav animated:YES]; +#else + [self.navigationController presentViewController:nav animated:YES completion:nil]; +#endif + + } else if (indexPath.section == 0 && indexPath.row == 1 && _passcodeLockOn) { + KKPasscodeViewController *vc = [[self.passcodeViewControllerClass alloc] initWithNibName:nil bundle:nil]; + vc.delegate = self; + + vc.mode = KKPasscodeModeChange; + + UINavigationController *nav = [[UINavigationController alloc] + initWithNavigationBarClass:[self.navigationController.navigationBar class] + toolbarClass:[self.navigationController.toolbar class]]; + nav.viewControllers = @[vc]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + nav.modalPresentationStyle = UIModalPresentationFormSheet; + nav.navigationBar.barStyle = UIBarStyleBlack; + nav.navigationBar.opaque = NO; + } else { + nav.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; + nav.navigationBar.translucent = self.navigationController.navigationBar.translucent; + nav.navigationBar.opaque = self.navigationController.navigationBar.opaque; + nav.navigationBar.barStyle = self.navigationController.navigationBar.barStyle; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self.navigationController presentModalViewController:nav animated:YES]; +#else + [self.navigationController presentViewController:nav animated:YES completion:nil]; +#endif + } - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - nav.modalPresentationStyle = UIModalPresentationFormSheet; - nav.navigationBar.barStyle = UIBarStyleBlack; - nav.navigationBar.opaque = NO; - } else { - nav.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; - nav.navigationBar.translucent = self.navigationController.navigationBar.translucent; - nav.navigationBar.opaque = self.navigationController.navigationBar.opaque; - nav.navigationBar.barStyle = self.navigationController.navigationBar.barStyle; - } - - [self.navigationController presentModalViewController:nav animated:YES]; - [nav release]; - - - [vc release]; - } else if (indexPath.section == 1 && _passcodeLockOn) { - KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:@"KKPasscodeViewController" bundle:nil]; - vc.mode = KKPasscodeModeChange; - vc.passcodeLockViewController = self; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - vc.modalPresentationStyle = UIModalPresentationFormSheet; - } - - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - nav.modalPresentationStyle = UIModalPresentationFormSheet; - nav.navigationBar.barStyle = UIBarStyleBlack; - nav.navigationBar.opaque = NO; - } else { - nav.navigationBar.tintColor = self.navigationController.navigationBar.tintColor; - nav.navigationBar.translucent = self.navigationController.navigationBar.translucent; - nav.navigationBar.opaque = self.navigationController.navigationBar.opaque; - nav.navigationBar.barStyle = self.navigationController.navigationBar.barStyle; - } - - [self.navigationController presentModalViewController:nav animated:YES]; - [nav release]; - - [vc release]; - } + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } +- (void)didPasscodeEnteredCorrectly:(KKPasscodeViewController*)viewController +{ + if ([_passcodeViewControllerDelegate respondsToSelector:@selector(didPasscodeEnteredCorrectly:)]) { + [_passcodeViewControllerDelegate performSelector:@selector(didPasscodeEnteredCorrectly:) withObject:viewController]; + } +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -#pragma mark Memory management +- (void)didPasscodeEnteredIncorrectly:(KKPasscodeViewController*)viewController +{ + if ([_passcodeViewControllerDelegate respondsToSelector:@selector(didPasscodeEnteredIncorrectly:)]) { + [_passcodeViewControllerDelegate performSelector:@selector(didPasscodeEnteredIncorrectly:) withObject:viewController]; + } +} +- (void)shouldLockApplication:(KKPasscodeViewController*)viewController +{ + if ([_passcodeViewControllerDelegate respondsToSelector:@selector(shouldLockApplication:)]) { + [_passcodeViewControllerDelegate performSelector:@selector(shouldLockApplication:) withObject:viewController]; + } +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)dealloc +- (void)shouldEraseApplicationData:(KKPasscodeViewController*)viewController { - [_simplePasscodeSwitch release]; - [_eraseDataSwitch release]; + if ([_passcodeViewControllerDelegate respondsToSelector:@selector(shouldEraseApplicationData:)]) { + [_passcodeViewControllerDelegate performSelector:@selector(shouldEraseApplicationData:) withObject:viewController]; + } +} - [super dealloc]; +- (void)didSettingsChanged:(KKPasscodeViewController*)viewController +{ + _passcodeLockOn = [[KKKeychain getStringForKey:@"passcode_on"] isEqualToString:@"YES"]; + _eraseDataOn = [[KKKeychain getStringForKey:@"erase_data_on"] isEqualToString:@"YES"]; + _eraseDataSwitch.on = _eraseDataOn; + + [self.tableView reloadData]; + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + + if ([_passcodeViewControllerDelegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_passcodeViewControllerDelegate performSelector:@selector(didSettingsChanged:) withObject:viewController]; + } } diff --git a/src/KKPasscodeViewController.h b/src/KKPasscodeViewController.h index 3788bb9..1c36f97 100755 --- a/src/KKPasscodeViewController.h +++ b/src/KKPasscodeViewController.h @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -18,60 +18,101 @@ #import +#define kPasscodeBoxesCount 4 + +#define kPasscodeBoxWidth 61.0 +#define kPasscodeBoxHeight 53.0 + + +// The mode which controls the passcode view behavior enum { - KKPasscodeModeEnter = 0, - KKPasscodeModeSet = 1, - KKPasscodeModeDisabled = 2, - KKPasscodeModeChange = 3 + /** + * Displays the passcode enter view, which the user has to enter the correct passcode + */ + KKPasscodeModeEnter = 0, + + /** + * Creates a new passcode. This allows the user to enter a new passcode then + * imediately verify it. + */ + KKPasscodeModeSet = 1, + + /** + * Disables an existing passcode. This allows the user to disable the passcode lock by + * entering the passcode + */ + KKPasscodeModeDisabled = 2, + + /** + * Changes an existing passcode. This allows the user to change the passcode by + * entering the existing passcode, followed by a new passcode + */ + KKPasscodeModeChange = 3 }; typedef NSUInteger KKPasscodeMode; -@class KKPasscodeSettingsViewController; - -@interface KKPasscodeViewController : UIViewController { - - KKPasscodeSettingsViewController* _passcodeLockViewController; - - UILabel* _passcodeConfirmationWarningLabel; - UIView* _failedAttemptsView; - UILabel* _failedAttemptsLabel; - NSInteger _failedAttemptsCount; - - NSUInteger _tableIndex; - NSMutableArray* _tableViews; - NSMutableArray* _textFields; - NSMutableArray* _squares; - - UITableView* _enterPasscodeTableView; - UITextField* _enterPasscodeTextField; - NSArray* _enterPasscodeSquareImageViews; - - UITableView* _setPasscodeTableView; - UITextField* _setPasscodeTextField; - NSArray* _setPasscodeSquareImageViews; - - UITableView* _confirmPasscodeTableView; - UITextField* _confirmPasscodeTextField; - NSArray* _confirmPasscodeSquareImageViews; - - KKPasscodeMode _mode; - - BOOL _simplePasscodeOn; - BOOL _passcodeLockOn; - BOOL _eraseData; - - CGFloat _viewWidth; -} +@class KKPasscodeViewController; -@property (nonatomic, assign) KKPasscodeMode mode; -@property (nonatomic, retain) KKPasscodeSettingsViewController* passcodeLockViewController; +@protocol KKPasscodeViewControllerDelegate +@optional +- (void)didPasscodeEnteredCorrectly:(KKPasscodeViewController*)viewController; +- (void)didPasscodeEnteredIncorrectly:(KKPasscodeViewController*)viewController; +- (void)shouldLockApplication:(KKPasscodeViewController*)viewController; +- (void)shouldEraseApplicationData:(KKPasscodeViewController*)viewController; +- (void)didSettingsChanged:(KKPasscodeViewController*)viewController; @end +@interface KKPasscodeViewController : UIViewController { + + // delegate which called when major events happens + id __unsafe_unretained _delegate; + + UILabel* _passcodeConfirmationWarningLabel; + UIView* _failedAttemptsView; + UILabel* _failedAttemptsLabel; + + // the current panel that being displayed + NSUInteger _currentPanel; + + // used to transition between table views + NSMutableArray* _tableViews; + + // array of passcode entry text fields + NSMutableArray* _textFields; + + NSMutableArray* _boxes; + + UITableView* _enterPasscodeTableView; + UITextField* _enterPasscodeTextField; + + UITableView* _setPasscodeTableView; + UITextField* _setPasscodeTextField; + + UITableView* _confirmPasscodeTableView; + UITextField* _confirmPasscodeTextField; + + // readwrite override for passlock mode + KKPasscodeMode _mode; + + // whatever the passcode lock is turned on or off + BOOL _passcodeLockOn; + + // whatever the erase data option is turned on or off + BOOL _eraseData; + + // Used to make sure we do not release the keyboard when on iPad + BOOL _shouldReleaseFirstResponser; + +} + +@property (nonatomic, unsafe_unretained) id delegate; +@property (nonatomic, assign) KKPasscodeMode mode; + + +@end diff --git a/src/KKPasscodeViewController.m b/src/KKPasscodeViewController.m index 781969b..c92ad68 100755 --- a/src/KKPasscodeViewController.m +++ b/src/KKPasscodeViewController.m @@ -1,12 +1,12 @@ // -// Copyright 2011-2012 Kosher Penguin LLC +// Copyright 2011-2012 Kosher Penguin LLC // Created by Adar Porat (https://github.com/aporat) on 1/16/2012. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -18,811 +18,834 @@ #import "KKPasscodeViewController.h" #import "KKKeychain.h" #import "KKPasscodeSettingsViewController.h" +#import "KKPasscodeLock.h" + #import +#import + +@interface KKPasscodeViewController () + +@property(nonatomic,assign) BOOL isSmallLandscape; +@property(nonatomic,strong) UIView *dimView; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -@interface KKPasscodeViewController(Private) +@end + +@interface KKPasscodeViewController (Private) -- (UITextField*)allocAndInitPasscodeTextField; -- (NSArray*)squares; -- (UIView*)passwordHeaderViewForTextField:(UITextField*)textField; -- (void)addNextButton; -- (void)addDoneButton; +- (UITextField*)passcodeTextField; +- (NSArray*)boxes; +- (UIView*)headerViewForTextField:(UITextField*)textField; - (void)moveToNextTableView; - (void)moveToPreviousTableView; +- (void)incrementFailedAttemptsLabel; @end -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// @implementation KKPasscodeViewController -@synthesize mode, passcodeLockViewController; - +@synthesize delegate = _delegate; +@synthesize mode = _mode; +@synthesize isSmallLandscape; -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark UIViewController +- (id)init +{ + if (self = [super init]) { + self.modalPresentationStyle = UIModalPresentationFormSheet; + } + return self; +} -/////////////////////////////////////////////////////////////////////////////////////////////////// - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - if (self == [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { - _enterPasscodeTableView = [[UITableView alloc] initWithFrame:self.view.bounds]; - _enterPasscodeTableView.delegate = self; - _enterPasscodeTableView.dataSource = self; - _enterPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _enterPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; - [self.view addSubview:_enterPasscodeTableView]; - - _setPasscodeTableView = [[UITableView alloc] initWithFrame:self.view.bounds]; - _setPasscodeTableView.delegate = self; - _setPasscodeTableView.dataSource = self; - _setPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _setPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; - [self.view addSubview:_setPasscodeTableView]; - - _confirmPasscodeTableView = [[UITableView alloc] initWithFrame:self.view.bounds]; - _confirmPasscodeTableView.delegate = self; - _confirmPasscodeTableView.dataSource = self; - _confirmPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _confirmPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; - [self.view addSubview:_confirmPasscodeTableView]; - } - - return self; + if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { + self.modalPresentationStyle = UIModalPresentationFormSheet; + } + return self; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +- (id)initWithCoder:(NSCoder *)aDecoder { - return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); + if (self = [super initWithCoder:aDecoder]) { + self.modalPresentationStyle = UIModalPresentationFormSheet; + } + return self; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)viewDidLoad +- (void)loadView { - [super viewDidLoad]; - - _simplePasscodeOn = [[KKKeychain getStringForKey:@"passcode_lock_simple_passcode_on"] isEqualToString:@"YES"]; - _passcodeLockOn = [[KKKeychain getStringForKey:@"passcode_lock_passcode_on"] isEqualToString:@"YES"]; - _eraseData = [[KKKeychain getStringForKey:@"passcode_lock_erase_data_on"] isEqualToString:@"YES"]; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - _viewWidth = 540.0f; - } else { - _viewWidth = 320.0f; - } + [super loadView]; + + self.view.backgroundColor = [UIColor whiteColor]; + + CGRect tableViewFrame = self.view.bounds; + if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad && [[UIScreen mainScreen] bounds].size.height > 480) { + // is running on device with 4" screen so add background tableView + UITableView *backgroundTableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStyleGrouped]; + [self.view addSubview:backgroundTableView]; + + //and move other tableViews down so boxes are vertically centered + tableViewFrame.origin.y += 44.0; + } + + _enterPasscodeTableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStyleGrouped]; + _enterPasscodeTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _enterPasscodeTableView.delegate = self; + _enterPasscodeTableView.dataSource = self; + _enterPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _enterPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; + [self.view addSubview:_enterPasscodeTableView]; + + _setPasscodeTableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStyleGrouped]; + _setPasscodeTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _setPasscodeTableView.delegate = self; + _setPasscodeTableView.dataSource = self; + _setPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _setPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; + [self.view addSubview:_setPasscodeTableView]; + + _confirmPasscodeTableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStyleGrouped]; + _confirmPasscodeTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _confirmPasscodeTableView.delegate = self; + _confirmPasscodeTableView.dataSource = self; + _confirmPasscodeTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _confirmPasscodeTableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; + [self.view addSubview:_confirmPasscodeTableView]; + + _shouldReleaseFirstResponser = NO; + } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - _enterPasscodeTextField = [self allocAndInitPasscodeTextField]; - _setPasscodeTextField = [self allocAndInitPasscodeTextField]; - _confirmPasscodeTextField = [self allocAndInitPasscodeTextField]; - - _tableViews = [[NSMutableArray alloc] init]; - _textFields = [[NSMutableArray alloc] init]; - _squares = [[NSMutableArray alloc] init]; - - if (mode == KKPasscodeModeSet || mode == KKPasscodeModeChange) { - if (_passcodeLockOn) { - _enterPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:_enterPasscodeTextField]; - [_tableViews addObject:_enterPasscodeTableView]; - [_textFields addObject:_enterPasscodeTextField]; - if (_simplePasscodeOn) { - [_squares addObject:[self squares]]; - for (int i = 0; i < [[_squares lastObject] count]; i++) { - [_enterPasscodeTableView.tableHeaderView addSubview:[[_squares lastObject] objectAtIndex:i]]; - } - } - } +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; - _setPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:_setPasscodeTextField]; - [_tableViews addObject:_setPasscodeTableView]; - [_textFields addObject:_setPasscodeTextField]; - if (_simplePasscodeOn) { - [_squares addObject:[self squares]]; - for (int i = 0; i < [[_squares lastObject] count]; i++) { - [_setPasscodeTableView.tableHeaderView addSubview:[[_squares lastObject] objectAtIndex:i]]; - } - } - _confirmPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:_confirmPasscodeTextField]; - [_tableViews addObject:_confirmPasscodeTableView]; - [_textFields addObject:_confirmPasscodeTextField]; - if (_simplePasscodeOn) { - [_squares addObject:[self squares]]; - for (int i = 0; i < [[_squares lastObject] count]; i++) { - [_confirmPasscodeTableView.tableHeaderView addSubview:[[_squares lastObject] objectAtIndex:i]]; - } - } - } else { - _enterPasscodeTableView.tableHeaderView = [self passwordHeaderViewForTextField:_enterPasscodeTextField]; - [_tableViews addObject:_enterPasscodeTableView]; - [_textFields addObject:_enterPasscodeTextField]; - if (_simplePasscodeOn) { - [_squares addObject:[self squares]]; - for (int i = 0; i < [[_squares lastObject] count]; i++) { - [_enterPasscodeTableView.tableHeaderView addSubview:[[_squares lastObject] objectAtIndex:i]]; - } - } - } - - [self.view addSubview:[_tableViews objectAtIndex:0]]; - - // shift any extra table views away - for (int i = 1; i < [_tableViews count]; i++) { - UITableView *tableView = [_tableViews objectAtIndex:i]; - tableView.frame = CGRectMake(tableView.frame.origin.x + _viewWidth, tableView.frame.origin.y, tableView.frame.size.width, tableView.frame.size.height); - [self.view addSubview:tableView]; - } - - if (_tableIndex == [_tableViews count] - 1) { - [self addDoneButton]; - } else { - [self addNextButton]; - } - - [[_textFields objectAtIndex:0] becomeFirstResponder]; - [[_tableViews objectAtIndex:0] reloadData]; - [[_textFields objectAtIndex:[_tableViews count] - 1] setReturnKeyType:UIReturnKeyDone]; - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - if ([_tableViews count] > 1) { - [self moveToNextTableView]; - [self moveToPreviousTableView]; + _passcodeLockOn = [[KKKeychain getStringForKey:@"passcode_on"] isEqualToString:@"YES"]; + _eraseData = [[KKPasscodeLock sharedLock] eraseOption] && [[KKKeychain getStringForKey:@"erase_data_on"] isEqualToString:@"YES"]; + + _enterPasscodeTextField = [[UITextField alloc] init]; + _enterPasscodeTextField.delegate = self; + _enterPasscodeTextField.keyboardType = UIKeyboardTypeNumberPad; + _enterPasscodeTextField.hidden = YES; + + _setPasscodeTextField = [[UITextField alloc] init]; + _setPasscodeTextField.delegate = self; + _setPasscodeTextField.keyboardType = UIKeyboardTypeNumberPad; + _setPasscodeTextField.hidden = YES; + + _confirmPasscodeTextField = [[UITextField alloc] init]; + _confirmPasscodeTextField.delegate = self; + _confirmPasscodeTextField.keyboardType = UIKeyboardTypeNumberPad; + _confirmPasscodeTextField.hidden = YES; + + _tableViews = [[NSMutableArray alloc] init]; + _textFields = [[NSMutableArray alloc] init]; + _boxes = [[NSMutableArray alloc] init]; + + // Need to make sure everything is visible in landscape mode on small devices. + self.isSmallLandscape = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && UIInterfaceOrientationIsLandscape(self.interfaceOrientation)); + + if (_mode == KKPasscodeModeSet) { + self.navigationItem.title = KKPasscodeLockLocalizedString(@"Set Passcode", @""); + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancelButtonPressed:)]; + } else if (_mode == KKPasscodeModeChange) { + self.navigationItem.title = KKPasscodeLockLocalizedString(@"Change Passcode", @""); + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancelButtonPressed:)]; + + } else if (_mode == KKPasscodeModeDisabled) { + self.navigationItem.title = KKPasscodeLockLocalizedString(@"Turn off Passcode", @""); + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(cancelButtonPressed:)]; + } else { - UITableView *tv = [_tableViews objectAtIndex:0]; - tv.frame = CGRectMake(tv.frame.origin.x, tv.frame.origin.y, 768.0, 960.0); + self.navigationItem.title = KKPasscodeLockLocalizedString(@"Enter Passcode", @""); } - } + + CGFloat totalBoxesWidth = (71.0 * kPasscodeBoxesCount) - 10.0; + + if (_mode == KKPasscodeModeSet || _mode == KKPasscodeModeChange) { + if (_passcodeLockOn) { + _enterPasscodeTableView.tableHeaderView = [self headerViewForTextField:_enterPasscodeTextField]; + [_tableViews addObject:_enterPasscodeTableView]; + [_textFields addObject:_enterPasscodeTextField]; + [_boxes addObject:[self boxes]]; + UIView *boxesView = [[UIView alloc] initWithFrame:CGRectMake((self.view.bounds.size.width - totalBoxesWidth) * 0.5, 0, totalBoxesWidth, kPasscodeBoxHeight)]; + boxesView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + for (int i = 0; i < [[_boxes lastObject] count]; i++) { + [boxesView addSubview:[[_boxes lastObject] objectAtIndex:i]]; + } + [_enterPasscodeTableView.tableHeaderView addSubview:boxesView]; + } + + _setPasscodeTableView.tableHeaderView = [self headerViewForTextField:_setPasscodeTextField]; + + [_tableViews addObject:_setPasscodeTableView]; + [_textFields addObject:_setPasscodeTextField]; + [_boxes addObject:[self boxes]]; + UIView *boxesView = [[UIView alloc] initWithFrame:CGRectMake((self.view.bounds.size.width - totalBoxesWidth) * 0.5, 0, totalBoxesWidth, kPasscodeBoxHeight)]; + boxesView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + for (int i = 0; i < [[_boxes lastObject] count]; i++) { + [boxesView addSubview:[[_boxes lastObject] objectAtIndex:i]]; + } + [_setPasscodeTableView.tableHeaderView addSubview:boxesView]; + + _confirmPasscodeTableView.tableHeaderView = [self headerViewForTextField:_confirmPasscodeTextField]; + [_tableViews addObject:_confirmPasscodeTableView]; + [_textFields addObject:_confirmPasscodeTextField]; + [_boxes addObject:[self boxes]]; + UIView *boxesConfirmView = [[UIView alloc] initWithFrame:CGRectMake((self.view.bounds.size.width - totalBoxesWidth) * 0.5, 0, totalBoxesWidth, kPasscodeBoxHeight)]; + boxesConfirmView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + for (int i = 0; i < [[_boxes lastObject] count]; i++) { + [boxesConfirmView addSubview:[[_boxes lastObject] objectAtIndex:i]]; + } + [_confirmPasscodeTableView.tableHeaderView addSubview:boxesConfirmView]; + } else { + _enterPasscodeTableView.tableHeaderView = [self headerViewForTextField:_enterPasscodeTextField]; + [_tableViews addObject:_enterPasscodeTableView]; + [_textFields addObject:_enterPasscodeTextField]; + [_boxes addObject:[self boxes]]; + UIView *boxesView = [[UIView alloc] initWithFrame:CGRectMake((self.view.bounds.size.width - totalBoxesWidth) * 0.5, 0, totalBoxesWidth, kPasscodeBoxHeight)]; + boxesView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + for (int i = 0; i < [[_boxes lastObject] count]; i++) { + [boxesView addSubview:[[_boxes lastObject] objectAtIndex:i]]; + } + [_enterPasscodeTableView.tableHeaderView addSubview:boxesView]; + } + + [self.view addSubview:[_tableViews objectAtIndex:0]]; + + for (int i = 1; i < [_tableViews count]; i++) { + UITableView *tableView = [_tableViews objectAtIndex:i]; + tableView.frame = CGRectMake(tableView.frame.origin.x + self.view.bounds.size.width, + tableView.frame.origin.y, + tableView.frame.size.width, + tableView.frame.size.height); + [self.view addSubview:tableView]; + } + + [[_textFields objectAtIndex:0] becomeFirstResponder]; + [[_tableViews objectAtIndex:0] reloadData]; + [[_textFields objectAtIndex:[_tableViews count] - 1] setReturnKeyType:UIReturnKeyDone]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + if ([_tableViews count] > 1) { + [self moveToNextTableView]; + [self moveToPreviousTableView]; + } else { + UITableView *tableView = [_tableViews objectAtIndex:0]; + tableView.frame = CGRectMake(tableView.frame.origin.x, + tableView.frame.origin.y, + self.view.bounds.size.width, + self.view.bounds.size.height); + } + + if (!self.dimView) { + id appDelegate = [[UIApplication sharedApplication] delegate]; + self.dimView = [[UIView alloc] initWithFrame:appDelegate.window.rootViewController.view.bounds]; + self.dimView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + self.dimView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor]; + self.dimView.alpha = 0.0f; + [appDelegate.window.rootViewController.view addSubview:self.dimView]; + [UIView animateWithDuration:0.3f animations:^{ + self.dimView.alpha = 1.0f; + }]; + } + } } -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -#pragma mark Private - +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + _shouldReleaseFirstResponser = YES; + [_enterPasscodeTextField resignFirstResponder]; + [_setPasscodeTextField resignFirstResponder]; + [_confirmPasscodeTextField resignFirstResponder]; + + if (self.dimView) { + [UIView animateWithDuration:0.3f + animations:^{ + self.dimView.alpha = 0.0f; + } + completion:^(BOOL finished) { + [self.dimView removeFromSuperview]; + self.dimView = nil; + }]; + } +} -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (UITextField*)allocAndInitPasscodeTextField +- (void)viewDidLayoutSubviews { - UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(29.0, 13.0, 271.0, 24.0)]; - textField.text = @""; - textField.textColor = [UIColor colorWithRed:0.220 green:0.329 blue:0.529 alpha:1.0]; - textField.secureTextEntry = YES; - textField.delegate = self; - - textField.keyboardAppearance = UIKeyboardAppearanceAlert; - - return textField; + [super viewDidLayoutSubviews]; + + CGRect frame = _passcodeConfirmationWarningLabel.frame; + frame.origin.x = 10.0f; + frame.size.width = self.view.frame.size.width - 10.0f*2; + + _passcodeConfirmationWarningLabel.frame = frame; } +#pragma mark - +#pragma mark Private methods -/////////////////////////////////////////////////////////////////////////////////////////////////// --(void)cancelButtonPressed:(id)sender +- (UIImage *)boxEmpty { - [self dismissModalViewControllerAnimated:YES]; + if (floor(NSFoundationVersionNumber) > 993.00) { + return [UIImage imageNamed:@"KKPasscodeLock.bundle/box_empty_ios7"]; + } else { + return [UIImage imageNamed:@"KKPasscodeLock.bundle/box_empty"]; + } } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)addNextButton +- (UIImage *)boxFilled { - if (!_simplePasscodeOn) { - UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextButtonPressed:)]; - self.navigationItem.rightBarButtonItem = nextButton; - [nextButton release]; - } + if (floor(NSFoundationVersionNumber) > 993.00) { + return [UIImage imageNamed:@"KKPasscodeLock.bundle/box_filled_ios7"]; + } else { + return [UIImage imageNamed:@"KKPasscodeLock.bundle/box_filled"]; + } } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)addDoneButton +- (void)cancelButtonPressed:(id)sender { - if (!_simplePasscodeOn) { - UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(doneButtonPressed:)]; - self.navigationItem.rightBarButtonItem = doneButton; - [doneButton release]; - } +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)incrementAndShowFailedAttemptsLabel +- (void)incrementFailedAttemptsLabel { - _enterPasscodeTextField.text = @""; - if (_simplePasscodeOn) { - for (int i = 0; i < 4; i++) { - [[[_squares objectAtIndex:_tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]]; - } - } - - _failedAttemptsCount += 1; - if (_failedAttemptsCount == 1) { - _failedAttemptsLabel.text = @"1 Failed Passcode Attempt"; - } else { - _failedAttemptsLabel.text = [NSString stringWithFormat:@"%i Failed Passcode Attempts", _failedAttemptsCount]; - } - CGSize size = [_failedAttemptsLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:14.0]]; - _failedAttemptsView.frame = CGRectMake((_viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0); - _failedAttemptsLabel.frame = CGRectMake((_viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0); - - CAGradientLayer *gradient = [CAGradientLayer layer]; - gradient.frame = _failedAttemptsView.bounds; - gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.714 green:0.043 blue:0.043 alpha:1.0] CGColor], - (id)[[UIColor colorWithRed:0.761 green:0.192 blue:0.192 alpha:1.0] CGColor], nil]; - [_failedAttemptsView.layer insertSublayer:gradient atIndex:0]; - _failedAttemptsView.layer.masksToBounds = YES; - - _failedAttemptsLabel.hidden = NO; - _failedAttemptsView.hidden = NO; - - if (_failedAttemptsCount == 10 && _eraseData) { - if ([KKKeychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) { - [KKKeychain setString:@"" forKey:@"passcode_lock_passcode"]; - } - [self dismissModalViewControllerAnimated:YES]; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - [UIView beginAnimations:@"fadeIn" context:nil]; - [UIView setAnimationDelay:0.25]; - [UIView setAnimationDuration:0.5]; - - [UIView commitAnimations]; - } + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + + _enterPasscodeTextField.text = @""; + for (int i = 0; i < kPasscodeBoxesCount; i++) { + [[[_boxes objectAtIndex:_currentPanel] objectAtIndex:i] setImage:[self boxEmpty]]; + } + + NSInteger _failedAttemptsCount = [[KKKeychain getStringForKey:@"failedAttemptsCount"] integerValue]; + + _failedAttemptsCount++; - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"You have entered an incorrect passcode too many times. All account data in this app has been deleted." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alert show]; - [alert release]; - } - + [KKKeychain setString:[NSString stringWithFormat:@"%ld", (long)_failedAttemptsCount] forKey:@"failedAttemptsCount"]; + + if (_failedAttemptsCount == 1) { + _failedAttemptsLabel.text = KKPasscodeLockLocalizedString(@"1 Failed Passcode Attempt", @""); + } else { + _failedAttemptsLabel.text = [NSString stringWithFormat:KKPasscodeLockLocalizedString(@"%i Failed Passcode Attempts", @""), _failedAttemptsCount]; + } + CGSize size = [_failedAttemptsLabel.text sizeWithFont:[UIFont boldSystemFontOfSize:self.isSmallLandscape ? 10.0f : 14.0f]]; + _failedAttemptsLabel.frame = _failedAttemptsView.frame = CGRectMake((self.view.bounds.size.width - (size.width + (self.isSmallLandscape ? 20.0f : 40.0f))) / 2, self.isSmallLandscape ? 75.0f : 150.0f, size.width + (self.isSmallLandscape ? 20.0f : 40.0f), size.height + (self.isSmallLandscape ? 5.0f : 10.0f)); + + CAGradientLayer *gradient = [CAGradientLayer layer]; + gradient.frame = _failedAttemptsView.bounds; + gradient.colors = [NSArray arrayWithObjects: + (id)[[UIColor colorWithRed:0.7 green:0.05 blue:0.05 alpha:1.0] CGColor], + (id)[[UIColor colorWithRed:0.8 green:0.2 blue:0.2 alpha:1.0] CGColor], nil]; + [_failedAttemptsView.layer insertSublayer:gradient atIndex:0]; + _failedAttemptsView.layer.masksToBounds = YES; + + _failedAttemptsLabel.hidden = NO; + _failedAttemptsView.hidden = NO; + + if (_failedAttemptsCount == [[KKPasscodeLock sharedLock] attemptsAllowed]) { + + _enterPasscodeTextField.delegate = nil; + + if (_eraseData) { + if ([_delegate respondsToSelector:@selector(shouldEraseApplicationData:)]) { + [_delegate shouldEraseApplicationData:self]; + } + } else { + if ([_delegate respondsToSelector:@selector(didPasscodeEnteredIncorrectly:)]) { + [_delegate didPasscodeEnteredIncorrectly:self]; + } + + [KKKeychain setString:[[KKPasscodeLock sharedLock].dateFormatter stringFromDate:[NSDate date]] forKey:@"incorrect_passcode_datetime"]; + + if ([_delegate respondsToSelector:@selector(shouldLockApplication:)]) { + [_delegate shouldLockApplication:self]; + } + } + + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + } + } - -/////////////////////////////////////////////////////////////////////////////////////////////////// - (void)moveToNextTableView { - _tableIndex += 1; - UITableView *oldTableView = [_tableViews objectAtIndex:_tableIndex - 1]; - UITableView *newTableView = [_tableViews objectAtIndex:_tableIndex]; - newTableView.frame = CGRectMake(oldTableView.frame.origin.x + _viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); - - if (_simplePasscodeOn) { - for (int i = 0; i < 4; i++) { - [[[_squares objectAtIndex:_tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]]; - } - } - - [UIView beginAnimations:@"" context:nil]; - [UIView setAnimationDuration:0.25]; - oldTableView.frame = CGRectMake(oldTableView.frame.origin.x - _viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); - newTableView.frame = self.view.frame; - [UIView commitAnimations]; - - if (_tableIndex == [_tableViews count] - 1) { - [self addDoneButton]; - } else { - [self addNextButton]; - } - - [[_textFields objectAtIndex:_tableIndex - 1] resignFirstResponder]; - [[_textFields objectAtIndex:_tableIndex] becomeFirstResponder]; + _currentPanel += 1; + + UITableView *oldTableView = [_tableViews objectAtIndex:_currentPanel - 1]; + UITableView *newTableView = [_tableViews objectAtIndex:_currentPanel]; + + newTableView.frame = CGRectMake(oldTableView.frame.origin.x + self.view.bounds.size.width, + oldTableView.frame.origin.y, + oldTableView.frame.size.width, + oldTableView.frame.size.height); + + for (int i = 0; i < kPasscodeBoxesCount; i++) { + [[[_boxes objectAtIndex:_currentPanel] objectAtIndex:i] setImage:[self boxEmpty]]; + } + + [UIView beginAnimations:@"" context:nil]; + [UIView setAnimationDuration:0.25]; + newTableView.frame = oldTableView.frame; + oldTableView.frame = CGRectMake(oldTableView.frame.origin.x - self.view.bounds.size.width, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); + [UIView commitAnimations]; + + _shouldReleaseFirstResponser = YES; + [[_textFields objectAtIndex:_currentPanel - 1] resignFirstResponder]; + _shouldReleaseFirstResponser = NO; + [[_textFields objectAtIndex:_currentPanel] becomeFirstResponder]; } -/////////////////////////////////////////////////////////////////////////////////////////////////// - (void)moveToPreviousTableView { - _tableIndex -= 1; - UITableView *oldTableView = [_tableViews objectAtIndex:_tableIndex + 1]; - UITableView *newTableView = [_tableViews objectAtIndex:_tableIndex]; - newTableView.frame = CGRectMake(oldTableView.frame.origin.x - _viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); - - if (_simplePasscodeOn) { - for (int i = 0; i < 4; i++) { - [[[_squares objectAtIndex:_tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]]; - } - } - - [UIView beginAnimations:@"" context:nil]; - [UIView setAnimationDuration:0.25]; - oldTableView.frame = CGRectMake(oldTableView.frame.origin.x + _viewWidth, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); - newTableView.frame = self.view.frame; - [UIView commitAnimations]; - - if (_tableIndex == [_tableViews count] - 1) { - [self addDoneButton]; - } else { - [self addNextButton]; - } - - [[_textFields objectAtIndex:_tableIndex + 1] resignFirstResponder]; - [[_textFields objectAtIndex:_tableIndex] becomeFirstResponder]; + _currentPanel -= 1; + + UITableView *oldTableView = [_tableViews objectAtIndex:_currentPanel + 1]; + UITableView *newTableView = [_tableViews objectAtIndex:_currentPanel]; + newTableView.frame = CGRectMake(oldTableView.frame.origin.x - self.view.bounds.size.width, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); + + for (int i = 0; i < kPasscodeBoxesCount; i++) { + [[[_boxes objectAtIndex:_currentPanel] objectAtIndex:i] setImage:[self boxEmpty]]; + } + + [UIView beginAnimations:@"" context:nil]; + [UIView setAnimationDuration:0.25]; + newTableView.frame = oldTableView.frame; + oldTableView.frame = CGRectMake(oldTableView.frame.origin.x + self.view.bounds.size.width, oldTableView.frame.origin.y, oldTableView.frame.size.width, oldTableView.frame.size.height); + [UIView commitAnimations]; + + _shouldReleaseFirstResponser = YES; + [[_textFields objectAtIndex:_currentPanel + 1] resignFirstResponder]; + _shouldReleaseFirstResponser = NO; + [[_textFields objectAtIndex:_currentPanel] becomeFirstResponder]; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)nextButtonPressed:(id)sender +- (void)nextDigitPressed { - - UITextField *textField = [_textFields objectAtIndex:_tableIndex]; - - if (![textField.text isEqualToString:@""]) { - - if (mode == KKPasscodeModeSet) { - if ([textField isEqual:_setPasscodeTextField]) { - [self moveToNextTableView]; - } else if ([textField isEqual:_confirmPasscodeTextField]) { - if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; + UITextField* textField = [_textFields objectAtIndex:_currentPanel]; + + if (![textField.text isEqualToString:@""]) { + + if (_mode == KKPasscodeModeSet) { + if ([textField isEqual:_setPasscodeTextField]) { + [self moveToNextTableView]; + } else if ([textField isEqual:_confirmPasscodeTextField]) { + if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { + _confirmPasscodeTextField.text = @""; + _setPasscodeTextField.text = @""; + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Passcodes did not match. Try again.", @""); + [self moveToPreviousTableView]; + } else { + if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode"]) { + [KKKeychain setString:@"YES" forKey:@"passcode_on"]; + } + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif + } + } + } else if (_mode == KKPasscodeModeChange) { + NSString* passcode = [KKKeychain getStringForKey:@"passcode"]; + if ([textField isEqual:_enterPasscodeTextField]) { + if ([passcode isEqualToString:_enterPasscodeTextField.text]) { + [self moveToNextTableView]; + } else { + [self incrementFailedAttemptsLabel]; + } + } else if ([textField isEqual:_setPasscodeTextField]) { + if ([passcode isEqualToString:_setPasscodeTextField.text]) { + _setPasscodeTextField.text = @""; + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Enter a different passcode. You cannot re-use the same passcode.", @""); + _passcodeConfirmationWarningLabel.frame = CGRectMake(10.0, 132.0, self.view.bounds.size.width - 10.0*2, 60.0); + } else { + _passcodeConfirmationWarningLabel.text = @""; + _passcodeConfirmationWarningLabel.frame = CGRectMake(10.0, 146.0, self.view.bounds.size.width - 10.0*2, 30.0); + [self moveToNextTableView]; + } + } else if ([textField isEqual:_confirmPasscodeTextField]) { + if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { + _confirmPasscodeTextField.text = @""; + _setPasscodeTextField.text = @""; + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Passcodes did not match. Try again.", ""); + [self moveToPreviousTableView]; + } else { + if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode"]) { + [KKKeychain setString:@"YES" forKey:@"passcode_on"]; + } + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif + } + } + } + } +} + +- (void)vaildatePasscode:(UITextField*)textField +{ + if (_mode == KKPasscodeModeDisabled) { + NSString *passcode = [KKKeychain getStringForKey:@"passcode"]; + if ([_enterPasscodeTextField.text isEqualToString:passcode]) { + if ([KKKeychain setString:@"NO" forKey:@"passcode_on"]) { + [KKKeychain setString:@"" forKey:@"passcode"]; + } + + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; + [self incrementFailedAttemptsLabel]; } - } - } else if (mode == KKPasscodeModeChange) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([textField isEqual:_enterPasscodeTextField]) { - if ([passcode isEqualToString:_enterPasscodeTextField.text]) { - [self moveToNextTableView]; + } else if (_mode == KKPasscodeModeEnter) { + NSString *passcode = [KKKeychain getStringForKey:@"passcode"]; + if ([_enterPasscodeTextField.text isEqualToString:passcode]) { + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + [UIView beginAnimations:@"fadeIn" context:nil]; + [UIView setAnimationDelay:0.25]; + [UIView setAnimationDuration:0.5]; + + [UIView commitAnimations]; + } + if ([_delegate respondsToSelector:@selector(didPasscodeEnteredCorrectly:)]) { + [_delegate performSelector:@selector(didPasscodeEnteredCorrectly:) withObject:self]; + } + + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif } else { - [self incrementAndShowFailedAttemptsLabel]; + [self incrementFailedAttemptsLabel]; } - } else if ([textField isEqual:_setPasscodeTextField]) { - if ([passcode isEqualToString:_setPasscodeTextField.text]) { - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode."; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, _viewWidth, 60.0); - } else { - _passcodeConfirmationWarningLabel.text = @""; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, _viewWidth, 30.0); - [self moveToNextTableView]; + } else if (_mode == KKPasscodeModeChange) { + NSString *passcode = [KKKeychain getStringForKey:@"passcode"]; + if ([textField isEqual:_enterPasscodeTextField]) { + if ([passcode isEqualToString:_enterPasscodeTextField.text]) { + [KKKeychain setString:@"0" forKey:@"failedAttemptsCount"]; + [self moveToNextTableView]; + } else { + [self incrementFailedAttemptsLabel]; + } + } else if ([textField isEqual:_setPasscodeTextField]) { + if ([passcode isEqualToString:_setPasscodeTextField.text]) { + _setPasscodeTextField.text = @""; + for (int i = 0; i < kPasscodeBoxesCount; i++) { + [[[_boxes objectAtIndex:_currentPanel] objectAtIndex:i] setImage:[self boxEmpty]]; + } + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Enter a different passcode. You cannot re-use the same passcode.", @""); + _passcodeConfirmationWarningLabel.frame = CGRectMake(10.0, 132.0, self.view.bounds.size.width - 10.0*2, 60.0); + } else { + _passcodeConfirmationWarningLabel.text = @""; + _passcodeConfirmationWarningLabel.frame = CGRectMake(10.0, 146.0, self.view.bounds.size.width - 10.0*2, 30.0); + [self moveToNextTableView]; + } + } else if ([textField isEqual:_confirmPasscodeTextField]) { + if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { + _confirmPasscodeTextField.text = @""; + _setPasscodeTextField.text = @""; + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Passcodes did not match. Try again.", @""); + [self moveToPreviousTableView]; + } else { + if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode"]) { + [KKKeychain setString:@"YES" forKey:@"passcode_on"]; + } + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif + } } - } else if ([textField isEqual:_confirmPasscodeTextField]) { + } else if ([textField isEqual:_setPasscodeTextField]) { + [self moveToNextTableView]; + } else if ([textField isEqual:_confirmPasscodeTextField]) { if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; + _confirmPasscodeTextField.text = @""; + _setPasscodeTextField.text = @""; + _passcodeConfirmationWarningLabel.text = KKPasscodeLockLocalizedString(@"Passcodes did not match. Try again.", @""); + [self moveToPreviousTableView]; } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; + if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode"]) { + [KKKeychain setString:@"YES" forKey:@"passcode_on"]; + } + + if ([_delegate respondsToSelector:@selector(didSettingsChanged:)]) { + [_delegate performSelector:@selector(didSettingsChanged:) withObject:self]; + } + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + [self dismissModalViewControllerAnimated:YES]; +#else + [self dismissViewControllerAnimated:YES completion:nil]; +#endif } - } } - } } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)doneButtonPressed:(id)sender +- (void)doneButtonPressed { - - UITextField *textField = [_textFields objectAtIndex:_tableIndex]; - - if (mode == KKPasscodeModeEnter) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([_enterPasscodeTextField.text isEqualToString:passcode]) { - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - [UIView beginAnimations:@"fadeIn" context:nil]; - [UIView setAnimationDelay:0.25]; - [UIView setAnimationDuration:0.5]; - - [UIView commitAnimations]; - } - [self dismissModalViewControllerAnimated:YES]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } else if (mode == KKPasscodeModeSet) { - if ([textField isEqual:_setPasscodeTextField]) { - [self moveToNextTableView]; - } else if ([textField isEqual:_confirmPasscodeTextField]) { - if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; - } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; - } - } - } else if (mode == KKPasscodeModeChange) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([textField isEqual:_enterPasscodeTextField]) { - if ([passcode isEqualToString:_enterPasscodeTextField.text]) { - [self moveToNextTableView]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } else if ([textField isEqual:_setPasscodeTextField]) { - if ([passcode isEqualToString:_setPasscodeTextField.text]) { - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode."; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, _viewWidth, 60.0); - } else { - _passcodeConfirmationWarningLabel.text = @""; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, _viewWidth, 30.0); - [self moveToNextTableView]; - } - } else if ([textField isEqual:_confirmPasscodeTextField]) { - if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; - } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; - } - } - } else if (mode == KKPasscodeModeDisabled) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([_enterPasscodeTextField.text isEqualToString:passcode]) { - if ([KKKeychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) { - [KKKeychain setString:@"" forKey:@"passcode_lock_passcode"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } + UITextField *textField = [_textFields objectAtIndex:_currentPanel]; + [self vaildatePasscode:textField]; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (UIView*)passwordHeaderViewForTextField:(UITextField*)textField +- (UIView*)headerViewForTextField:(UITextField*)textField { - - if (_simplePasscodeOn) { - textField.keyboardType = UIKeyboardTypeNumberPad; - - textField.hidden = YES; [self.view addSubview:textField]; - } else { - textField.keyboardType = UIKeyboardTypeDefault; - textField.returnKeyType = UIReturnKeyNext; - } - - UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, _viewWidth, 70.0)] autorelease]; - UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 27.5, _viewWidth, 30.0)]; - headerLabel.textColor = [UIColor colorWithRed:0.298 green:0.337 blue:0.424 alpha:1.0]; - headerLabel.backgroundColor = [UIColor clearColor]; - headerLabel.textAlignment = UITextAlignmentCenter; - headerLabel.font = [UIFont boldSystemFontOfSize:17.0]; - headerLabel.shadowOffset = CGSizeMake(0, 1.0); - headerLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; - - if ([textField isEqual:_setPasscodeTextField]) { - _passcodeConfirmationWarningLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 146.5, _viewWidth, 30.0)]; - _passcodeConfirmationWarningLabel.textColor = [UIColor colorWithRed:0.298 green:0.337 blue:0.424 alpha:1.0]; - _passcodeConfirmationWarningLabel.backgroundColor = [UIColor clearColor]; - _passcodeConfirmationWarningLabel.textAlignment = UITextAlignmentCenter; - _passcodeConfirmationWarningLabel.font = [UIFont systemFontOfSize:14.0]; - _passcodeConfirmationWarningLabel.shadowOffset = CGSizeMake(0, 1.0); - _passcodeConfirmationWarningLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; - _passcodeConfirmationWarningLabel.text = @""; - _passcodeConfirmationWarningLabel.numberOfLines = 0; - _passcodeConfirmationWarningLabel.lineBreakMode = UILineBreakModeWordWrap; - [headerView addSubview:_passcodeConfirmationWarningLabel]; - } - - if ([textField isEqual:_enterPasscodeTextField]) { - - NSString *text = @"1 Failed Passcode Attempt"; - CGSize size = [text sizeWithFont:[UIFont boldSystemFontOfSize:14.0]]; - _failedAttemptsView = [[UIView alloc] initWithFrame:CGRectMake((_viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0)]; - _failedAttemptsLabel = [[UILabel alloc] initWithFrame:CGRectMake((_viewWidth - (size.width + 36.0)) / 2, 147.5, size.width + 36.0, size.height + 10.0)]; - _failedAttemptsLabel.backgroundColor = [UIColor clearColor]; - _failedAttemptsLabel.textColor = [UIColor whiteColor]; - _failedAttemptsLabel.text = text; - _failedAttemptsLabel.font = [UIFont boldSystemFontOfSize:14.0]; - _failedAttemptsLabel.textAlignment = UITextAlignmentCenter; - _failedAttemptsLabel.shadowOffset = CGSizeMake(0, -1.0); - _failedAttemptsLabel.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0]; - _failedAttemptsView.layer.cornerRadius = 14; - _failedAttemptsView.layer.borderWidth = 1.0; - _failedAttemptsView.layer.borderColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.25] CGColor]; + UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.view.bounds.size.width, 70.0)]; + UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0, self.isSmallLandscape ? 2.0f : 28.0f, self.view.bounds.size.width, 30.0)]; + headerLabel.textColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.4 alpha:1.0]; + headerLabel.backgroundColor = [UIColor clearColor]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + headerLabel.textAlignment = UITextAlignmentCenter; +#else + headerLabel.textAlignment = NSTextAlignmentCenter; +#endif - _failedAttemptsLabel.hidden = YES; - _failedAttemptsView.hidden = YES; - - CAGradientLayer *gradient = [CAGradientLayer layer]; - gradient.frame = _failedAttemptsView.bounds; - gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.714 green:0.043 blue:0.043 alpha:1.0] CGColor], - (id)[[UIColor colorWithRed:0.761 green:0.192 blue:0.192 alpha:1.0] CGColor], nil]; - [_failedAttemptsView.layer insertSublayer:gradient atIndex:1]; - _failedAttemptsView.layer.masksToBounds = YES; - - [headerView addSubview:_failedAttemptsView]; - [headerView addSubview:_failedAttemptsLabel]; - - [_failedAttemptsView release]; - [_failedAttemptsLabel release]; - } - - if (mode == KKPasscodeModeSet) { - self.navigationItem.title = @"Set Passcode"; - UIBarButtonItem *cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)]; - self.navigationItem.leftBarButtonItem = cancel; - [cancel release]; - - - if ([textField isEqual:_enterPasscodeTextField]) { - headerLabel.text = @"Enter your passcode"; - } else if ([textField isEqual:_setPasscodeTextField]) { - headerLabel.text = @"Enter a passcode"; - UIBarButtonItem *cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)]; - self.navigationItem.leftBarButtonItem = cancel; - [cancel release]; - - } else if ([textField isEqual:_confirmPasscodeTextField]) { - headerLabel.text = @"Re-enter your passcode"; + headerLabel.font = [UIFont boldSystemFontOfSize:self.isSmallLandscape ? 12.0f : 17.0f]; + + if ((floor(NSFoundationVersionNumber) <= 993.00)) { + headerLabel.shadowOffset = CGSizeMake(0, 1.0); + headerLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; } - } else if (mode == KKPasscodeModeDisabled) { - self.navigationItem.title = @"Turn off Passcode"; - UIBarButtonItem *cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)]; - self.navigationItem.leftBarButtonItem = cancel; - [cancel release]; - - headerLabel.text = @"Enter your passcode"; - } else if (mode == KKPasscodeModeChange) { - self.navigationItem.title = @"Change Passcode"; - UIBarButtonItem *cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelButtonPressed:)]; - self.navigationItem.leftBarButtonItem = cancel; - [cancel release]; - - if ([textField isEqual:_enterPasscodeTextField]) { - headerLabel.text = @"Enter your old passcode"; - } else if ([textField isEqual:_setPasscodeTextField]) { - headerLabel.text = @"Enter your new passcode"; + + if ([textField isEqual:_setPasscodeTextField]) { + _passcodeConfirmationWarningLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0, self.isSmallLandscape ? 73.0f : 146.0, self.view.frame.size.width - 10.0*2, 30.0)]; + _passcodeConfirmationWarningLabel.textColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.4 alpha:1.0]; + _passcodeConfirmationWarningLabel.backgroundColor = [UIColor clearColor]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + _passcodeConfirmationWarningLabel.textAlignment = UITextAlignmentCenter; +#else + _passcodeConfirmationWarningLabel.textAlignment = NSTextAlignmentCenter; +#endif + + _passcodeConfirmationWarningLabel.font = [UIFont systemFontOfSize:14.0]; + if ((floor(NSFoundationVersionNumber) <= 993.00)) { + _passcodeConfirmationWarningLabel.shadowOffset = CGSizeMake(0, 1.0); + _passcodeConfirmationWarningLabel.shadowColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]; + } + _passcodeConfirmationWarningLabel.text = @""; + _passcodeConfirmationWarningLabel.numberOfLines = 0; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + _passcodeConfirmationWarningLabel.lineBreakMode = UILineBreakModeWordWrap; +#else + _passcodeConfirmationWarningLabel.lineBreakMode = NSLineBreakByWordWrapping; +#endif + + [headerView addSubview:_passcodeConfirmationWarningLabel]; + } + + if ([textField isEqual:_enterPasscodeTextField]) { + _failedAttemptsView = [[UIView alloc] init]; + _failedAttemptsLabel = [[UILabel alloc] init]; + _failedAttemptsLabel.backgroundColor = [UIColor clearColor]; + _failedAttemptsLabel.textColor = [UIColor whiteColor]; + _failedAttemptsLabel.text = @""; + _failedAttemptsLabel.font = [UIFont boldSystemFontOfSize:self.isSmallLandscape ? 10.0f : 14.0f]; + +#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 + _failedAttemptsLabel.textAlignment = UITextAlignmentCenter; +#else + _failedAttemptsLabel.textAlignment = NSTextAlignmentCenter; +#endif + if ((floor(NSFoundationVersionNumber) <= 993.00)) { + _failedAttemptsLabel.shadowOffset = CGSizeMake(0, -1.0); + _failedAttemptsLabel.shadowColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0]; + } + _failedAttemptsView.layer.cornerRadius = self.isSmallLandscape ? 7.0f : 14.0f; + _failedAttemptsView.layer.borderWidth = 1.0; + _failedAttemptsView.layer.borderColor = [[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.25] CGColor]; + + _failedAttemptsLabel.hidden = YES; + _failedAttemptsView.hidden = YES; + + _failedAttemptsView.layer.masksToBounds = YES; + + [headerView addSubview:_failedAttemptsView]; + [headerView addSubview:_failedAttemptsLabel]; + } + + if (_mode == KKPasscodeModeSet) { + if ([textField isEqual:_enterPasscodeTextField]) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter your passcode", @""); + } else if ([textField isEqual:_setPasscodeTextField]) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter a passcode", @""); + } else if ([textField isEqual:_confirmPasscodeTextField]) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Re-enter your passcode", @""); + } + } else if (_mode == KKPasscodeModeDisabled) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter your passcode", @""); + } else if (_mode == KKPasscodeModeChange) { + if ([textField isEqual:_enterPasscodeTextField]) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter your old passcode", @""); + } else if ([textField isEqual:_setPasscodeTextField]) { + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter your new passcode", @""); + } else { + headerLabel.text = KKPasscodeLockLocalizedString(@"Re-enter your new passcode", @""); + } } else { - headerLabel.text = @"Re-enter your new passcode"; + headerLabel.text = KKPasscodeLockLocalizedString(@"Enter your passcode", @""); } - } else { - self.navigationItem.title = @"Enter Passcode"; - headerLabel.text = @"Enter your passcode"; - } - - [headerView addSubview:headerLabel]; - [headerLabel release]; - - return headerView; + + headerLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; + [headerView addSubview:headerLabel]; + + return headerView; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSArray*)squares +- (NSArray*)boxes { - NSMutableArray *squareViews = [[NSMutableArray alloc] initWithCapacity:4]; - NSInteger squareX = 23.0; - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - squareX = 133.0; - } - - for (int i = 0; i < 4; i++) { - UIImageView *square = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"passcode_square_empty.png"]]; - square.frame = CGRectMake(squareX, 74.0, 61.0, 53.0); - [squareViews addObject:square]; - [square release]; - squareX += 71.0; - } - return [[NSArray alloc] initWithArray:squareViews]; + NSMutableArray* squareViews = [NSMutableArray array]; + + CGFloat squareX = self.isSmallLandscape ? 60.0f : 0.0f; + + CGFloat width = self.isSmallLandscape ? kPasscodeBoxWidth * 0.6f : kPasscodeBoxWidth; + CGFloat height = self.isSmallLandscape ? kPasscodeBoxHeight * 0.6f : kPasscodeBoxHeight; + + for (int i = 0; i < kPasscodeBoxesCount; i++) { + UIImageView *square = [[UIImageView alloc] initWithImage:[self boxEmpty]]; + square.frame = CGRectMake(squareX, self.isSmallLandscape ? 32.0f : 74.0, width, height); + [squareViews addObject:square]; + squareX += self.isSmallLandscape ? 42.0f : 71.0; + } + return [NSArray arrayWithArray:squareViews]; } - - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark Table view data source - +#pragma mark UITableViewDataSource methods -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return _simplePasscodeOn ? 0 : 1; +- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView +{ + return 0; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 1; +- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section +{ + return 1; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - - static NSString *CellIdentifier = @"Cell"; - - UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - } - - //cell.accessoryView = enterPasscodeTextField; //[textFields objectAtIndex:tableIndex]; - if ([aTableView isEqual:_enterPasscodeTableView]) { - cell.accessoryView = _enterPasscodeTextField; - } else if ([aTableView isEqual:_setPasscodeTableView]) { - cell.accessoryView = _setPasscodeTextField; - } else if ([aTableView isEqual:_confirmPasscodeTableView]) { - cell.accessoryView = _confirmPasscodeTextField; - } - - return cell; +- (UITableViewCell*)tableView:(UITableView*)aTableView cellForRowAtIndexPath:(NSIndexPath*)indexPath +{ + static NSString* CellIdentifier = @"KKPasscodeViewControllerCell"; + + UITableViewCell* cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + } + + if ([aTableView isEqual:_enterPasscodeTableView]) { + cell.accessoryView = _enterPasscodeTextField; + } else if ([aTableView isEqual:_setPasscodeTableView]) { + cell.accessoryView = _setPasscodeTextField; + } else if ([aTableView isEqual:_confirmPasscodeTableView]) { + cell.accessoryView = _confirmPasscodeTextField; + } + + return cell; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark UITextFieldDelegate - +#pragma mark UITextFieldDelegate methods -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (BOOL)textFieldShouldReturn:(UITextField *)textField { - if ([textField isEqual:[_textFields lastObject]]) { - [self doneButtonPressed:nil]; - } else { - [self nextButtonPressed:nil]; - } - return NO; +- (BOOL)textFieldShouldReturn:(UITextField*)textField +{ + if ([textField isEqual:[_textFields lastObject]]) { + [self doneButtonPressed]; + } else { + [self nextDigitPressed]; + } + return NO; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - - if (_simplePasscodeOn) { + + + +- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string +{ NSString *result = [textField.text stringByReplacingCharactersInRange:range withString:string]; - textField.text = result; - for (int i = 0; i < 4; i++) { - UIImageView *square = [[_squares objectAtIndex:_tableIndex] objectAtIndex:i]; - if (i < [result length]) { - square.image = [UIImage imageNamed:@"passcode_square_filled.png"]; - } else { - square.image = [UIImage imageNamed:@"passcode_square_empty.png"]; - } - } - - if ([result length] == 4) { - - if (mode == KKPasscodeModeDisabled) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([_enterPasscodeTextField.text isEqualToString:passcode]) { - if ([KKKeychain setString:@"NO" forKey:@"passcode_lock_passcode_on"]) { - [KKKeychain setString:@"" forKey:@"passcode_lock_passcode"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } else if (mode == KKPasscodeModeEnter) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([_enterPasscodeTextField.text isEqualToString:passcode]) { - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - [UIView beginAnimations:@"fadeIn" context:nil]; - [UIView setAnimationDelay:0.25]; - [UIView setAnimationDuration:0.5]; - - [UIView commitAnimations]; - } - [self dismissModalViewControllerAnimated:YES]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } else if (mode == KKPasscodeModeChange) { - NSString *passcode = [KKKeychain getStringForKey:@"passcode_lock_passcode"]; - if ([textField isEqual:_enterPasscodeTextField]) { - if ([passcode isEqualToString:_enterPasscodeTextField.text]) { - [self moveToNextTableView]; - } else { - [self incrementAndShowFailedAttemptsLabel]; - } - } else if ([textField isEqual:_setPasscodeTextField]) { - if ([passcode isEqualToString:_setPasscodeTextField.text]) { - _setPasscodeTextField.text = @""; - for (int i = 0; i < 4; i++) { - [[[_squares objectAtIndex:_tableIndex] objectAtIndex:i] setImage:[UIImage imageNamed:@"passcode_square_empty.png"]]; - } - _passcodeConfirmationWarningLabel.text = @"Enter a different passcode. Cannot re-use the same passcode."; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 131.5, _viewWidth, 60.0); - } else { - _passcodeConfirmationWarningLabel.text = @""; - _passcodeConfirmationWarningLabel.frame = CGRectMake(0.0, 146.5, _viewWidth, 30.0); - [self moveToNextTableView]; - } - } else if ([textField isEqual:_confirmPasscodeTextField]) { - if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; - } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; - } - } - } else if ([textField isEqual:_setPasscodeTextField]) { - [self moveToNextTableView]; - } else if ([textField isEqual:_confirmPasscodeTextField]) { - if (![_confirmPasscodeTextField.text isEqualToString:_setPasscodeTextField.text]) { - _confirmPasscodeTextField.text = @""; - _setPasscodeTextField.text = @""; - _passcodeConfirmationWarningLabel.text = @"Passcodes did not match. Try again."; - [self moveToPreviousTableView]; + for (int i = 0; i < kPasscodeBoxesCount; i++) { + UIImageView *square = [[_boxes objectAtIndex:_currentPanel] objectAtIndex:i]; + if (i < [result length]) { + square.image = [self boxFilled]; } else { - if ([KKKeychain setString:_setPasscodeTextField.text forKey:@"passcode_lock_passcode"]) { - [KKKeychain setString:@"YES" forKey:@"passcode_lock_passcode_on"]; - } - [self.passcodeLockViewController.tableView reloadData]; - [self dismissModalViewControllerAnimated:YES]; + square.image = [self boxEmpty]; } - } + } + + if ([result length] == kPasscodeBoxesCount) { + [self vaildatePasscode:textField]; } return NO; - } - - return YES; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -#pragma mark - -#pragma mark Memory management - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)dealloc { - - [_enterPasscodeTextField release]; - [_setPasscodeTextField release]; - [_confirmPasscodeTextField release]; - [_tableViews release]; - [_textFields release]; - [_squares release]; - [_passcodeLockViewController release]; - - [super dealloc]; +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + return _shouldReleaseFirstResponser; } +#pragma mark - +#pragma mark Memory management + @end diff --git a/src/passcode_square_empty.png b/src/passcode_square_empty.png deleted file mode 100755 index 3c5c529..0000000 Binary files a/src/passcode_square_empty.png and /dev/null differ diff --git a/src/passcode_square_empty@2x.png b/src/passcode_square_empty@2x.png deleted file mode 100755 index 2a6e74f..0000000 Binary files a/src/passcode_square_empty@2x.png and /dev/null differ diff --git a/src/passcode_square_filled.png b/src/passcode_square_filled.png deleted file mode 100755 index d29c5c3..0000000 Binary files a/src/passcode_square_filled.png and /dev/null differ diff --git a/src/passcode_square_filled@2x.png b/src/passcode_square_filled@2x.png deleted file mode 100755 index d266578..0000000 Binary files a/src/passcode_square_filled@2x.png and /dev/null differ diff --git a/tests/KKPasscodeLock/KKPasscodeLock-Prefix.pch b/tests/KKPasscodeLock/KKPasscodeLock-Prefix.pch new file mode 100644 index 0000000..7c5cd99 --- /dev/null +++ b/tests/KKPasscodeLock/KKPasscodeLock-Prefix.pch @@ -0,0 +1,7 @@ +// +// Prefix header for all source files of the 'KKPasscodeLock' target in the 'KKPasscodeLock' project +// + +#ifdef __OBJC__ + #import +#endif diff --git a/tests/KKPasscodeLockTests.xcodeproj/project.pbxproj b/tests/KKPasscodeLockTests.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6966be1 --- /dev/null +++ b/tests/KKPasscodeLockTests.xcodeproj/project.pbxproj @@ -0,0 +1,345 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5303097416611E650004810F /* KKPasscodeSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5303096916611E650004810F /* KKPasscodeSettingsViewController.m */; }; + 5303097516611E650004810F /* KKPasscodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5303096A16611E650004810F /* KKPasscodeViewController.m */; }; + 5303097716611E650004810F /* KKPasscodeLock.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5303096D16611E650004810F /* KKPasscodeLock.bundle */; }; + 5303097816611E650004810F /* KKKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 5303096F16611E650004810F /* KKKeychain.m */; }; + 5303097916611E650004810F /* KKPasscodeLock.m in Sources */ = {isa = PBXBuildFile; fileRef = 5303097016611E650004810F /* KKPasscodeLock.m */; }; + 6D2394C81548CA89004DF3B7 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394C71548CA89004DF3B7 /* SenTestingKit.framework */; }; + 6D2394CA1548CA89004DF3B7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394C91548CA89004DF3B7 /* UIKit.framework */; }; + 6D2394CB1548CA89004DF3B7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394B91548CA89004DF3B7 /* Foundation.framework */; }; + 6D2394D41548CA89004DF3B7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6D2394D21548CA89004DF3B7 /* InfoPlist.strings */; }; + 6D2394D71548CA89004DF3B7 /* KKPasscodeLockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2394D61548CA89004DF3B7 /* KKPasscodeLockTests.m */; }; + 6D2394F81548CBAA004DF3B7 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394F61548CBAA004DF3B7 /* AudioToolbox.framework */; }; + 6D2394F91548CBAA004DF3B7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394F71548CBAA004DF3B7 /* CoreGraphics.framework */; }; + 6D2394FB1548CBAE004DF3B7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394FA1548CBAE004DF3B7 /* Security.framework */; }; + 6D2394FD1548CBC5004DF3B7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2394FC1548CBC5004DF3B7 /* QuartzCore.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 5303096916611E650004810F /* KKPasscodeSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeSettingsViewController.m; path = ../../src/KKPasscodeSettingsViewController.m; sourceTree = ""; }; + 5303096A16611E650004810F /* KKPasscodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeViewController.m; path = ../../src/KKPasscodeViewController.m; sourceTree = ""; }; + 5303096D16611E650004810F /* KKPasscodeLock.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = KKPasscodeLock.bundle; path = ../../src/KKPasscodeLock.bundle; sourceTree = ""; }; + 5303096E16611E650004810F /* KKPasscodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeViewController.h; path = ../../src/KKPasscodeViewController.h; sourceTree = ""; }; + 5303096F16611E650004810F /* KKKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKKeychain.m; path = ../../src/KKKeychain.m; sourceTree = ""; }; + 5303097016611E650004810F /* KKPasscodeLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KKPasscodeLock.m; path = ../../src/KKPasscodeLock.m; sourceTree = ""; }; + 5303097116611E650004810F /* KKPasscodeLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeLock.h; path = ../../src/KKPasscodeLock.h; sourceTree = ""; }; + 5303097216611E650004810F /* KKKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKKeychain.h; path = ../../src/KKKeychain.h; sourceTree = ""; }; + 5303097316611E650004810F /* KKPasscodeSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KKPasscodeSettingsViewController.h; path = ../../src/KKPasscodeSettingsViewController.h; sourceTree = ""; }; + 6D2394B91548CA89004DF3B7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 6D2394BD1548CA89004DF3B7 /* KKPasscodeLock-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KKPasscodeLock-Prefix.pch"; sourceTree = ""; }; + 6D2394C61548CA89004DF3B7 /* KKPasscodeLock.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KKPasscodeLock.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2394C71548CA89004DF3B7 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; + 6D2394C91548CA89004DF3B7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 6D2394D11548CA89004DF3B7 /* KKPasscodeLock-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KKPasscodeLock-Info.plist"; sourceTree = ""; }; + 6D2394D31548CA89004DF3B7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 6D2394D51548CA89004DF3B7 /* KKPasscodeLockTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KKPasscodeLockTests.h; sourceTree = ""; }; + 6D2394D61548CA89004DF3B7 /* KKPasscodeLockTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KKPasscodeLockTests.m; sourceTree = ""; }; + 6D2394F61548CBAA004DF3B7 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 6D2394F71548CBAA004DF3B7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 6D2394FA1548CBAE004DF3B7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 6D2394FC1548CBC5004DF3B7 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6D2394C21548CA89004DF3B7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2394FD1548CBC5004DF3B7 /* QuartzCore.framework in Frameworks */, + 6D2394FB1548CBAE004DF3B7 /* Security.framework in Frameworks */, + 6D2394F81548CBAA004DF3B7 /* AudioToolbox.framework in Frameworks */, + 6D2394F91548CBAA004DF3B7 /* CoreGraphics.framework in Frameworks */, + 6D2394C81548CA89004DF3B7 /* SenTestingKit.framework in Frameworks */, + 6D2394CA1548CA89004DF3B7 /* UIKit.framework in Frameworks */, + 6D2394CB1548CA89004DF3B7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6D2394AB1548CA89004DF3B7 = { + isa = PBXGroup; + children = ( + 6D2394BB1548CA89004DF3B7 /* KKPasscodeLock */, + 6D2394CF1548CA89004DF3B7 /* KKPasscodeLockTests */, + 6D2394B81548CA89004DF3B7 /* Frameworks */, + 6D2394B71548CA89004DF3B7 /* Products */, + ); + sourceTree = ""; + }; + 6D2394B71548CA89004DF3B7 /* Products */ = { + isa = PBXGroup; + children = ( + 6D2394C61548CA89004DF3B7 /* KKPasscodeLock.octest */, + ); + name = Products; + sourceTree = ""; + }; + 6D2394B81548CA89004DF3B7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6D2394FC1548CBC5004DF3B7 /* QuartzCore.framework */, + 6D2394FA1548CBAE004DF3B7 /* Security.framework */, + 6D2394F61548CBAA004DF3B7 /* AudioToolbox.framework */, + 6D2394F71548CBAA004DF3B7 /* CoreGraphics.framework */, + 6D2394B91548CA89004DF3B7 /* Foundation.framework */, + 6D2394C71548CA89004DF3B7 /* SenTestingKit.framework */, + 6D2394C91548CA89004DF3B7 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6D2394BB1548CA89004DF3B7 /* KKPasscodeLock */ = { + isa = PBXGroup; + children = ( + 5303096916611E650004810F /* KKPasscodeSettingsViewController.m */, + 5303096A16611E650004810F /* KKPasscodeViewController.m */, + 5303096D16611E650004810F /* KKPasscodeLock.bundle */, + 5303096E16611E650004810F /* KKPasscodeViewController.h */, + 5303096F16611E650004810F /* KKKeychain.m */, + 5303097116611E650004810F /* KKPasscodeLock.h */, + 5303097016611E650004810F /* KKPasscodeLock.m */, + 5303097216611E650004810F /* KKKeychain.h */, + 5303097316611E650004810F /* KKPasscodeSettingsViewController.h */, + 6D2394BC1548CA89004DF3B7 /* Supporting Files */, + ); + path = KKPasscodeLock; + sourceTree = ""; + }; + 6D2394BC1548CA89004DF3B7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2394BD1548CA89004DF3B7 /* KKPasscodeLock-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2394CF1548CA89004DF3B7 /* KKPasscodeLockTests */ = { + isa = PBXGroup; + children = ( + 6D2394D51548CA89004DF3B7 /* KKPasscodeLockTests.h */, + 6D2394D61548CA89004DF3B7 /* KKPasscodeLockTests.m */, + 6D2394D01548CA89004DF3B7 /* Supporting Files */, + ); + path = KKPasscodeLockTests; + sourceTree = ""; + }; + 6D2394D01548CA89004DF3B7 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2394D11548CA89004DF3B7 /* KKPasscodeLock-Info.plist */, + 6D2394D21548CA89004DF3B7 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 6D2394C51548CA89004DF3B7 /* KKPasscodeLockTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2394DD1548CA89004DF3B7 /* Build configuration list for PBXNativeTarget "KKPasscodeLockTests" */; + buildPhases = ( + 6D2394C11548CA89004DF3B7 /* Sources */, + 6D2394C21548CA89004DF3B7 /* Frameworks */, + 6D2394C31548CA89004DF3B7 /* Resources */, + 6D2394C41548CA89004DF3B7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = KKPasscodeLockTests; + productName = KKPasscodeLockTests; + productReference = 6D2394C61548CA89004DF3B7 /* KKPasscodeLock.octest */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2394AD1548CA89004DF3B7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0430; + ORGANIZATIONNAME = "Kosher Penguin LLC"; + }; + buildConfigurationList = 6D2394B01548CA89004DF3B7 /* Build configuration list for PBXProject "KKPasscodeLockTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 6D2394AB1548CA89004DF3B7; + productRefGroup = 6D2394B71548CA89004DF3B7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2394C51548CA89004DF3B7 /* KKPasscodeLockTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6D2394C31548CA89004DF3B7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2394D41548CA89004DF3B7 /* InfoPlist.strings in Resources */, + 5303097716611E650004810F /* KKPasscodeLock.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 6D2394C41548CA89004DF3B7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6D2394C11548CA89004DF3B7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2394D71548CA89004DF3B7 /* KKPasscodeLockTests.m in Sources */, + 5303097416611E650004810F /* KKPasscodeSettingsViewController.m in Sources */, + 5303097516611E650004810F /* KKPasscodeViewController.m in Sources */, + 5303097816611E650004810F /* KKKeychain.m in Sources */, + 5303097916611E650004810F /* KKPasscodeLock.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2394D21548CA89004DF3B7 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 6D2394D31548CA89004DF3B7 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 6D2394D81548CA89004DF3B7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 6D2394D91548CA89004DF3B7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 5.1; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2394DE1548CA89004DF3B7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(DEVELOPER_LIBRARY_DIR)/Frameworks", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLock-Prefix.pch"; + INFOPLIST_FILE = "KKPasscodeLockTests/KKPasscodeLock-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PRODUCT_NAME = KKPasscodeLock; + WRAPPER_EXTENSION = octest; + }; + name = Debug; + }; + 6D2394DF1548CA89004DF3B7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(DEVELOPER_LIBRARY_DIR)/Frameworks", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "KKPasscodeLock/KKPasscodeLock-Prefix.pch"; + INFOPLIST_FILE = "KKPasscodeLockTests/KKPasscodeLock-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; + PRODUCT_NAME = KKPasscodeLock; + WRAPPER_EXTENSION = octest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6D2394B01548CA89004DF3B7 /* Build configuration list for PBXProject "KKPasscodeLockTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2394D81548CA89004DF3B7 /* Debug */, + 6D2394D91548CA89004DF3B7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2394DD1548CA89004DF3B7 /* Build configuration list for PBXNativeTarget "KKPasscodeLockTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2394DE1548CA89004DF3B7 /* Debug */, + 6D2394DF1548CA89004DF3B7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2394AD1548CA89004DF3B7 /* Project object */; +} diff --git a/tests/KKPasscodeLockTests/KKPasscodeLock-Info.plist b/tests/KKPasscodeLockTests/KKPasscodeLock-Info.plist new file mode 100644 index 0000000..0a33f6c --- /dev/null +++ b/tests/KKPasscodeLockTests/KKPasscodeLock-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.kosherpenguin.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/tests/KKPasscodeLockTests/KKPasscodeLockTests.h b/tests/KKPasscodeLockTests/KKPasscodeLockTests.h new file mode 100644 index 0000000..6f02f46 --- /dev/null +++ b/tests/KKPasscodeLockTests/KKPasscodeLockTests.h @@ -0,0 +1,22 @@ +// +// Copyright 2011-2012 Kosher Penguin LLC +// Created by Adar Porat (https://github.com/aporat) on 1/16/2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface KKPasscodeLockTests : SenTestCase + +@end diff --git a/tests/KKPasscodeLockTests/KKPasscodeLockTests.m b/tests/KKPasscodeLockTests/KKPasscodeLockTests.m new file mode 100644 index 0000000..665587f --- /dev/null +++ b/tests/KKPasscodeLockTests/KKPasscodeLockTests.m @@ -0,0 +1,47 @@ +// +// Copyright 2011-2012 Kosher Penguin LLC +// Created by Adar Porat (https://github.com/aporat) on 1/16/2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "KKPasscodeLockTests.h" +#import "KKPasscodeLock.h" + +@implementation KKPasscodeLockTests + +- (void)setUp +{ + [super setUp]; + + // Set-up code here. +} + +- (void)tearDown +{ + // Tear-down code here. + + [super tearDown]; +} + +- (void)testDefaultSettings +{ + KKPasscodeLock* sharedLock = [KKPasscodeLock sharedLock]; + + STAssertEquals(sharedLock.eraseOption, YES, @"Erase option is default to YES"); + STAssertEquals(sharedLock.attemptsAllowed, (NSUInteger)5, @"attemptsAllowed default to 5 tries"); + + +} + +@end diff --git a/tests/KKPasscodeLockTests/en.lproj/InfoPlist.strings b/tests/KKPasscodeLockTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/tests/KKPasscodeLockTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ +