├── AppTime.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── zc.xcuserdatad │ │ ├── UserInterfaceState(冲突_zc的Mac_2014-02-22 01-59-01).xcuserstate │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ └── zczc.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── zc.xcuserdatad │ ├── xcdebugger │ │ ├── Breakpoints_v2(冲突_zc的Mac_2014-02-22 02-04-08).xcbkptlist │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ ├── AppTime.xcscheme │ │ └── xcschememanagement.plist │ └── zczc.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── AppTime.xcscheme │ └── xcschememanagement.plist ├── AppTime ├── AppDelegate.h ├── AppDelegate.m ├── AppTime-Info.plist ├── AppTime-Prefix.pch ├── Base.lproj │ └── Main.storyboard ├── Control │ ├── AppTimeAccess.h │ ├── AppTimeAccess.m │ ├── DBManager.h │ └── DBManager.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Lib │ ├── FMDB │ │ ├── .svn │ │ │ ├── all-wcprops │ │ │ ├── entries │ │ │ ├── prop-base │ │ │ │ ├── FMDatabase.h.svn-base │ │ │ │ ├── FMDatabase.m.svn-base │ │ │ │ ├── FMDatabaseAdditions.h.svn-base │ │ │ │ ├── FMDatabaseAdditions.m.svn-base │ │ │ │ ├── FMDatabasePool.h.svn-base │ │ │ │ ├── FMDatabasePool.m.svn-base │ │ │ │ ├── FMDatabaseQueue.h.svn-base │ │ │ │ ├── FMDatabaseQueue.m.svn-base │ │ │ │ ├── FMResultSet.h.svn-base │ │ │ │ ├── FMResultSet.m.svn-base │ │ │ │ └── fmdb.m.svn-base │ │ │ └── text-base │ │ │ │ ├── FMDatabase.h.svn-base │ │ │ │ ├── FMDatabase.m.svn-base │ │ │ │ ├── FMDatabaseAdditions.h.svn-base │ │ │ │ ├── FMDatabaseAdditions.m.svn-base │ │ │ │ ├── FMDatabasePool.h.svn-base │ │ │ │ ├── FMDatabasePool.m.svn-base │ │ │ │ ├── FMDatabaseQueue.h.svn-base │ │ │ │ ├── FMDatabaseQueue.m.svn-base │ │ │ │ ├── FMResultSet.h.svn-base │ │ │ │ ├── FMResultSet.m.svn-base │ │ │ │ └── fmdb.m.svn-base │ │ ├── FMDatabase.h │ │ ├── FMDatabase.m │ │ ├── FMDatabaseAdditions.h │ │ ├── FMDatabaseAdditions.m │ │ ├── FMDatabasePool.h │ │ ├── FMDatabasePool.m │ │ ├── FMDatabaseQueue.h │ │ ├── FMDatabaseQueue.m │ │ ├── FMResultSet.h │ │ ├── FMResultSet.m │ │ └── fmdb.m │ ├── MMDrawerController │ │ ├── MMDrawerBarButtonItem.h │ │ ├── MMDrawerBarButtonItem.m │ │ ├── MMDrawerController.h │ │ ├── MMDrawerController.m │ │ ├── MMDrawerVisualState.h │ │ ├── MMDrawerVisualState.m │ │ ├── MMExampleDrawerVisualStateManager.h │ │ ├── MMExampleDrawerVisualStateManager.m │ │ ├── MMExampleLeftSideDrawerViewController.h │ │ ├── MMExampleLeftSideDrawerViewController.m │ │ ├── MMExampleRightSideDrawerViewController.h │ │ ├── MMExampleRightSideDrawerViewController.m │ │ ├── MMExampleSideDrawerViewController.h │ │ ├── MMExampleSideDrawerViewController.m │ │ ├── MMSideDrawerSectionHeaderView.h │ │ ├── MMSideDrawerSectionHeaderView.m │ │ ├── MMSideDrawerTableViewCell.h │ │ ├── MMSideDrawerTableViewCell.m │ │ ├── MMTableViewCell.h │ │ ├── MMTableViewCell.m │ │ ├── UIViewController+MMDrawerController.h │ │ └── UIViewController+MMDrawerController.m │ ├── NSDate+Helper.h │ └── NSDate+Helper.m ├── Res │ ├── MMPSilence.wav │ ├── desktop@2x.png │ ├── icon114@2x.png │ ├── icon120@2x.png │ └── mute.mp3 ├── StatusViewCell.h ├── StatusViewCell.m ├── StatusViewController.h ├── StatusViewController.m ├── Utility │ ├── AppRunInfo.h │ ├── AppRunInfo.m │ ├── AppTimeCounter.h │ ├── AppTimeCounter.m │ ├── MMPDeepSleepPreventer.h │ └── MMPDeepSleepPreventer.m ├── ViewController.h ├── ViewController.m ├── en.lproj │ └── InfoPlist.strings ├── main.m ├── rightViewController.h └── rightViewController.m └── AppTimeTests ├── AppTimeTests-Info.plist ├── AppTimeTests.m └── en.lproj └── InfoPlist.strings /AppTime.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/project.xcworkspace/xcuserdata/zc.xcuserdatad/UserInterfaceState(冲突_zc的Mac_2014-02-22 01-59-01).xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime.xcodeproj/project.xcworkspace/xcuserdata/zc.xcuserdatad/UserInterfaceState(冲突_zc的Mac_2014-02-22 01-59-01).xcuserstate -------------------------------------------------------------------------------- /AppTime.xcodeproj/project.xcworkspace/xcuserdata/zc.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime.xcodeproj/project.xcworkspace/xcuserdata/zc.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppTime.xcodeproj/project.xcworkspace/xcuserdata/zc.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/project.xcworkspace/xcuserdata/zczc.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime.xcodeproj/project.xcworkspace/xcuserdata/zczc.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zc.xcuserdatad/xcdebugger/Breakpoints_v2(冲突_zc的Mac_2014-02-22 02-04-08).xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 56 | 68 | 69 | 70 | 72 | 84 | 85 | 86 | 88 | 100 | 101 | 102 | 104 | 116 | 117 | 118 | 120 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 40 | 52 | 53 | 54 | 56 | 68 | 69 | 70 | 72 | 84 | 85 | 86 | 88 | 100 | 101 | 102 | 104 | 116 | 117 | 118 | 120 | 132 | 133 | 134 | 136 | 148 | 149 | 150 | 152 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zc.xcuserdatad/xcschemes/AppTime.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zc.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppTime.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 59571E5718AB862C0087E035 16 | 17 | primary 18 | 19 | 20 | 59571E7818AB862C0087E035 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zczc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zczc.xcuserdatad/xcschemes/AppTime.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /AppTime.xcodeproj/xcuserdata/zczc.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AppTime.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 59571E5718AB862C0087E035 16 | 17 | primary 18 | 19 | 20 | 59571E7818AB862C0087E035 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /AppTime/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | #import "StatusViewController.h" 12 | @interface AppDelegate : UIResponder 13 | { 14 | StatusViewController *statusController; 15 | 16 | } 17 | @property (strong, nonatomic) UIWindow *window; 18 | +(AppDelegate *)defaultAppDelegate; 19 | @end 20 | -------------------------------------------------------------------------------- /AppTime/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import "MMPDeepSleepPreventer.h" 13 | #import "AppTimeCounter.h" 14 | #import "MMDrawerController.h" 15 | #import "rightViewController.h" 16 | #import "MMExampleRightSideDrawerViewController.h" 17 | @implementation AppDelegate 18 | int runCount = 0; 19 | 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | // Override point for customization after application launch. 24 | statusController = [[StatusViewController alloc]init]; 25 | UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:statusController]; 26 | 27 | 28 | 29 | rightViewController * rightSideDrawerViewController = [[rightViewController alloc] init]; 30 | 31 | 32 | rightSideDrawerViewController.delegate = statusController; 33 | rightSideDrawerViewController.statusController = statusController; 34 | MMDrawerController * drawerController = [[MMDrawerController alloc] 35 | initWithCenterViewController:nav 36 | leftDrawerViewController:nil 37 | rightDrawerViewController:rightSideDrawerViewController]; 38 | 39 | 40 | [drawerController setMaximumRightDrawerWidth:200.0]; 41 | [drawerController setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeAll]; 42 | [drawerController setCloseDrawerGestureModeMask:MMCloseDrawerGestureModeAll]; 43 | [drawerController setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeBezelPanningCenterView]; 44 | 45 | [drawerController 46 | setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) { 47 | }]; 48 | 49 | // [self.navigationItem setTitle:@"日剧达人"]; 50 | 51 | [drawerController 52 | setMaximumLeftDrawerWidth:240 53 | animated:YES 54 | completion:^(BOOL finished) { 55 | }]; 56 | 57 | self.window.rootViewController = drawerController; 58 | 59 | 60 | MMPDeepSleepPreventer * soundBoard = [MMPDeepSleepPreventer new]; 61 | [soundBoard startPreventSleep]; 62 | 63 | [self registerforDeviceLockNotif]; 64 | [AppTimeCounter sharedInstance]; 65 | 66 | 67 | return YES; 68 | } 69 | 70 | 71 | 72 | static void displayStatusChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 73 | { 74 | CFStringRef nameCFString = (CFStringRef)name; 75 | NSString *lockState = (__bridge NSString*)nameCFString; 76 | 77 | if([lockState isEqualToString:@"com.apple.springboard.lockcomplete"]) 78 | { 79 | runCount ++; 80 | } 81 | else 82 | { 83 | runCount ++; 84 | if (runCount % 3 == 2) 85 | { 86 | [[AppTimeCounter sharedInstance]pauseTimer]; 87 | } 88 | else 89 | { 90 | [[AppTimeCounter sharedInstance]resumeTimer]; 91 | } 92 | } 93 | } 94 | 95 | -(void)registerforDeviceLockNotif 96 | { 97 | //Screen lock notifications 98 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center 99 | NULL, // observer 100 | displayStatusChanged, // callback 101 | CFSTR("com.apple.springboard.lockcomplete"), // event name 102 | NULL, // object 103 | CFNotificationSuspensionBehaviorDeliverImmediately); 104 | 105 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center 106 | NULL, // observer 107 | displayStatusChanged, // callback 108 | CFSTR("com.apple.springboard.lockstate"), // event name 109 | NULL, // object 110 | CFNotificationSuspensionBehaviorDeliverImmediately); 111 | } 112 | 113 | - (void)applicationWillResignActive:(UIApplication *)application 114 | { 115 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 116 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 117 | } 118 | 119 | - (void)applicationDidEnterBackground:(UIApplication *)application 120 | { 121 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 122 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 123 | } 124 | 125 | - (void)applicationWillEnterForeground:(UIApplication *)application 126 | { 127 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 128 | [statusController refresh]; 129 | } 130 | 131 | - (void)applicationDidBecomeActive:(UIApplication *)application 132 | { 133 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 134 | } 135 | 136 | - (void)applicationWillTerminate:(UIApplication *)application 137 | { 138 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 139 | } 140 | 141 | +(AppDelegate *)defaultAppDelegate{ 142 | 143 | AppDelegate *delegate= (AppDelegate *)[[UIApplication sharedApplication] delegate]; 144 | return delegate; 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /AppTime/AppTime-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | zc.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIBackgroundModes 34 | 35 | audio 36 | 37 | CFBundleIconFiles 38 | 39 | icon114@2x.png 40 | icon120@2x.png 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /AppTime/AppTime-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /AppTime/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AppTime/Control/AppTimeAccess.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppTimeAccess.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | #import "AppRunInfo.h" 12 | @interface AppTimeAccess : NSObject 13 | 14 | + (AppTimeAccess *)sharedInstance; 15 | 16 | -(void)insertAppRunInfoItem:(AppRunInfoItem*)itemEntity; 17 | -(NSArray*)readAllRecords; 18 | -(NSArray*)readAllRecordsByDate:(NSDate*)date; 19 | -(NSArray*)readAllRecordsGroupByAppId; 20 | -(void)insertFilterAppById:(NSString*)appId; 21 | -(NSArray*)readAllFilterApp; 22 | -(NSArray*)readThisWeekRescordsByDate; 23 | @end 24 | -------------------------------------------------------------------------------- /AppTime/Control/AppTimeAccess.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppTimeAccess.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "AppTimeAccess.h" 11 | 12 | #import "DBManager.h" 13 | #import "NSDate+Helper.h" 14 | @implementation AppTimeAccess 15 | #define TABLENAME @"AppRunInfo" 16 | #define FILTER @"FilterApp" 17 | + (AppTimeAccess *)sharedInstance 18 | { 19 | static AppTimeAccess *manager = nil; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken,^{ 22 | manager = [[AppTimeAccess alloc] init]; 23 | }); 24 | return manager; 25 | } 26 | 27 | - (id)init{ 28 | self = [super init]; 29 | if(self){ 30 | 31 | 32 | } 33 | return self; 34 | } 35 | 36 | -(void)insertAppRunInfoItem:(AppRunInfoItem*)itemEntity 37 | { 38 | NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; 39 | [dict setObject:itemEntity.appId forKey:@"appId"]; 40 | [dict setObject:itemEntity.appName forKey:@"appName"]; 41 | [dict setObject:itemEntity.runTime forKey:@"runTime"]; 42 | [dict setObject:itemEntity.date forKey:@"date"]; 43 | 44 | [[DBManager shareDBManager]insertData:dict toTable:TABLENAME]; 45 | 46 | } 47 | 48 | -(void)insertFilterAppById:(NSString*)appId 49 | { 50 | NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; 51 | [dict setObject:appId forKey:@"appId"]; 52 | 53 | 54 | [[DBManager shareDBManager]insertData:dict toTable:FILTER]; 55 | 56 | } 57 | 58 | 59 | -(NSArray*)readAllRecords 60 | { 61 | 62 | NSString *sql = @"select * from AppRunInfo where appId not in (select * from FilterApp)"; 63 | NSMutableArray *records = [[DBManager shareDBManager]executeSqlWithResult:sql]; 64 | NSMutableArray *entityArray = [[NSMutableArray alloc]init]; 65 | for (NSDictionary *dict in records) 66 | { 67 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 68 | itemEntity.appId = [dict objectForKey:@"appId"]; 69 | itemEntity.appName = [dict objectForKey:@"appName"]; 70 | itemEntity.runTime = [dict objectForKey:@"runTime"]; 71 | itemEntity.date = [dict objectForKey:@"date"]; 72 | [entityArray addObject:itemEntity]; 73 | 74 | } 75 | return entityArray; 76 | } 77 | 78 | 79 | 80 | -(NSArray*)readAllRecordsByDate:(NSDate*)date 81 | { 82 | NSString *datestring = [date stringWithFormat:[NSDate dateFormatString]]; 83 | 84 | NSString *sql = [NSString stringWithFormat:@"select appId,appName,sum(runTime) as runTime,date ,count(appId) as count from AppRunInfo where date='%@' and appId not in (select * from FilterApp)group by appId ",datestring ]; 85 | 86 | NSMutableArray *records = [[DBManager shareDBManager]executeSqlWithResult:sql]; 87 | NSMutableArray *entityArray = [[NSMutableArray alloc]init]; 88 | for (NSDictionary *dict in records) 89 | { 90 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 91 | itemEntity.appId = [dict objectForKey:@"appId"]; 92 | itemEntity.appName = [dict objectForKey:@"appName"]; 93 | itemEntity.runTime = [dict objectForKey:@"runTime"]; 94 | itemEntity.date = [dict objectForKey:@"date"]; 95 | itemEntity.count = [[dict objectForKey:@"count"]intValue]; 96 | [entityArray addObject:itemEntity]; 97 | 98 | } 99 | return entityArray; 100 | } 101 | 102 | -(NSArray*)readThisWeekRescordsByDate 103 | { 104 | 105 | int weekday = [NSDate getWeekDay]; 106 | int days = 0; 107 | if (weekday == 1) 108 | { 109 | days = 6; 110 | } 111 | else 112 | { 113 | days = weekday - 2; 114 | } 115 | 116 | NSDate *previousDate = [NSDate dateBeforeDate:days]; 117 | NSString *sql = [NSString stringWithFormat:@"select appId,appName,sum(runTime) as runTime,date,count(appId) as count from AppRunInfo where appId not in (select * from FilterApp) and date between '%@' and '%@' group by appId ",[previousDate stringWithFormat:[NSDate dateFormatString]],[[NSDate date]stringWithFormat:[NSDate dateFormatString]] ]; 118 | NSMutableArray *records = [[DBManager shareDBManager]executeSqlWithResult:sql]; 119 | NSMutableArray *entityArray = [[NSMutableArray alloc]init]; 120 | for (NSDictionary *dict in records) 121 | { 122 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 123 | itemEntity.appId = [dict objectForKey:@"appId"]; 124 | itemEntity.appName = [dict objectForKey:@"appName"]; 125 | itemEntity.runTime = [dict objectForKey:@"runTime"]; 126 | itemEntity.date = [dict objectForKey:@"date"]; 127 | itemEntity.count = [[dict objectForKey:@"count"]intValue]; 128 | [entityArray addObject:itemEntity]; 129 | 130 | } 131 | return entityArray; 132 | 133 | 134 | } 135 | 136 | -(NSArray*)readAllRecordsGroupByAppId 137 | { 138 | NSString *sql = [NSString stringWithFormat:@"select appId,appName,sum(runTime) as runTime,date,count(appId) as count from AppRunInfo where appId not in (select * from FilterApp) group by appId " ]; 139 | NSMutableArray *records = [[DBManager shareDBManager]executeSqlWithResult:sql]; 140 | NSMutableArray *entityArray = [[NSMutableArray alloc]init]; 141 | for (NSDictionary *dict in records) 142 | { 143 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 144 | itemEntity.appId = [dict objectForKey:@"appId"]; 145 | itemEntity.appName = [dict objectForKey:@"appName"]; 146 | itemEntity.runTime = [dict objectForKey:@"runTime"]; 147 | itemEntity.date = [dict objectForKey:@"date"]; 148 | itemEntity.count = [[dict objectForKey:@"count"]intValue]; 149 | [entityArray addObject:itemEntity]; 150 | 151 | } 152 | return entityArray; 153 | } 154 | 155 | -(NSArray*)readAllFilterApp 156 | { 157 | NSString *sql = [NSString stringWithFormat:@"select appId,appName,sum(runTime) as runTime,date,count(appId) as count from AppRunInfo where appId in (select * from FilterApp) group by appId " ]; 158 | NSMutableArray *records = [[DBManager shareDBManager]executeSqlWithResult:sql]; 159 | NSMutableArray *entityArray = [[NSMutableArray alloc]init]; 160 | for (NSDictionary *dict in records) 161 | { 162 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 163 | itemEntity.appId = [dict objectForKey:@"appId"]; 164 | itemEntity.appName = [dict objectForKey:@"appName"]; 165 | itemEntity.runTime = [dict objectForKey:@"runTime"]; 166 | itemEntity.date = [dict objectForKey:@"date"]; 167 | itemEntity.count = [[dict objectForKey:@"count"]intValue]; 168 | [entityArray addObject:itemEntity]; 169 | 170 | } 171 | return entityArray; 172 | } 173 | 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /AppTime/Control/DBManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // DBManager.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | @class FMDatabase; 12 | const NSString *DB_NAME; 13 | 14 | @interface DBManager : NSObject{ 15 | NSString * TAG; 16 | int DB_VERSION; 17 | FMDatabase *db; 18 | } 19 | + (DBManager *)shareDBManager; 20 | - (BOOL)openDB; 21 | - (BOOL)closeDB; 22 | - (BOOL)insertData:(id)data toTable:(NSString *)name; 23 | - (NSMutableArray*)executeSqlWithResult:(NSString *)sql; 24 | 25 | @end 26 | 27 | -------------------------------------------------------------------------------- /AppTime/Control/DBManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // DBManager.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | 11 | #import "DBManager.h" 12 | #import "FMDatabase.h" 13 | #import "FMDatabaseAdditions.h" 14 | #import "FMDatabasePool.h" 15 | #import "FMDatabaseQueue.h" 16 | 17 | const NSString *DB_NAME = @"BDCOOL"; 18 | 19 | @implementation DBManager 20 | 21 | + (DBManager *)shareDBManager{ 22 | static DBManager *manager = nil; 23 | static dispatch_once_t onceToken; 24 | dispatch_once(&onceToken,^{ 25 | manager = [[DBManager alloc] init]; 26 | }); 27 | return manager; 28 | } 29 | 30 | - (void)initTable{ 31 | NSArray *createTableSqls = [NSArray arrayWithObjects: 32 | @"CREATE TABLE AppRunInfo (appId VARCHAR ,appName char, runTime integer,date char)" 33 | 34 | , 35 | @"CREATE TABLE FilterApp (appId VARCHAR)" 36 | 37 | ,nil]; 38 | 39 | 40 | [db open]; 41 | [db beginTransaction]; 42 | for(NSString *sql in createTableSqls){ 43 | if(![db executeUpdate:sql]){ 44 | [db rollback]; 45 | break; 46 | } 47 | } 48 | [db commit]; 49 | [db close]; 50 | } 51 | 52 | - (id)init{ 53 | self = [super init]; 54 | if(self){ 55 | NSString *documentsDir = (NSString *)[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 56 | NSString *tmpPath = [documentsDir stringByAppendingPathComponent:@"AppTime.sqlite"]; 57 | // NSString *tmpPath = @"/Users/zc/AppTime.sqlite"; 58 | if (![[NSFileManager defaultManager] fileExistsAtPath:tmpPath]){ 59 | db = [[FMDatabase alloc] initWithPath:tmpPath]; 60 | [self initTable]; 61 | }else { 62 | db = [[FMDatabase alloc] initWithPath:tmpPath]; 63 | } 64 | 65 | } 66 | return self; 67 | } 68 | 69 | 70 | - (BOOL)openDB{ 71 | return [db open]; 72 | } 73 | - (BOOL)closeDB{ 74 | return [db close]; 75 | } 76 | - (BOOL)insertData:(id)data toTable:(NSString *)name{ 77 | @synchronized (self){ 78 | if ([data isKindOfClass:[NSDictionary class]]){ 79 | [db open]; 80 | 81 | NSMutableArray *s = [[NSMutableArray alloc] init]; 82 | for (id value in [data allValues]){ 83 | [s addObject:@"?"]; 84 | } 85 | NSString *sql = [[NSString alloc] initWithFormat:@"INSERT OR REPLACE into %@ (%@) values (%@)", name, [[data allKeys] componentsJoinedByString:@","], [s componentsJoinedByString:@","]]; 86 | BOOL result = [db executeUpdate:sql withArgumentsInArray:[data allValues]]; 87 | [db close]; 88 | return result; 89 | }else { 90 | [db open]; 91 | for (NSMutableDictionary *_data in data){ 92 | NSMutableArray *s = [[NSMutableArray alloc] init]; 93 | for (id value in [_data allValues]){ 94 | [s addObject:@"?"]; 95 | } 96 | 97 | NSString *sql = [[NSString alloc] initWithFormat:@"INSERT OR REPLACE into %@ (%@) values (%@)", name, [[_data allKeys] componentsJoinedByString:@","], [s componentsJoinedByString:@","]]; 98 | 99 | if (![db executeUpdate:sql withArgumentsInArray:[_data allValues]]){ 100 | NSLog(@"error"); 101 | } 102 | } 103 | [db close]; 104 | 105 | return YES; 106 | } 107 | return NO; 108 | } 109 | 110 | 111 | } 112 | 113 | - (NSMutableArray*)executeSqlWithResult:(NSString *)sql{ 114 | @synchronized (self){ 115 | NSMutableArray *result = [NSMutableArray array]; 116 | [db open]; 117 | FMResultSet *rs = [db executeQuery:sql]; 118 | if (rs){ 119 | while ([rs next]) { 120 | [result addObject:[rs resultDictionary]]; 121 | } 122 | } 123 | [db close]; 124 | return result; 125 | } 126 | } 127 | 128 | @end 129 | 130 | -------------------------------------------------------------------------------- /AppTime/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AppTime/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 76 4 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB 5 | END 6 | FMDatabaseAdditions.m 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 98 10 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabaseAdditions.m 11 | END 12 | FMDatabase.m 13 | K 25 14 | svn:wc:ra_dav:version-url 15 | V 89 16 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabase.m 17 | END 18 | FMDatabaseQueue.h 19 | K 25 20 | svn:wc:ra_dav:version-url 21 | V 94 22 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabaseQueue.h 23 | END 24 | FMResultSet.h 25 | K 25 26 | svn:wc:ra_dav:version-url 27 | V 90 28 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMResultSet.h 29 | END 30 | fmdb.m 31 | K 25 32 | svn:wc:ra_dav:version-url 33 | V 83 34 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/fmdb.m 35 | END 36 | FMDatabasePool.h 37 | K 25 38 | svn:wc:ra_dav:version-url 39 | V 93 40 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabasePool.h 41 | END 42 | FMDatabaseQueue.m 43 | K 25 44 | svn:wc:ra_dav:version-url 45 | V 94 46 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabaseQueue.m 47 | END 48 | FMResultSet.m 49 | K 25 50 | svn:wc:ra_dav:version-url 51 | V 90 52 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMResultSet.m 53 | END 54 | FMDatabaseAdditions.h 55 | K 25 56 | svn:wc:ra_dav:version-url 57 | V 98 58 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabaseAdditions.h 59 | END 60 | FMDatabasePool.m 61 | K 25 62 | svn:wc:ra_dav:version-url 63 | V 93 64 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabasePool.m 65 | END 66 | FMDatabase.h 67 | K 25 68 | svn:wc:ra_dav:version-url 69 | V 89 70 | /app/ecom/shifen/sf-crm/!svn/ver/213942/trunk/sf-bridge2/ios/Bridge/Lib/FMDB/FMDatabase.h 71 | END 72 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 217176 5 | https://zhangcong@svn.baidu.com/app/ecom/shifen/sf-crm/trunk/sf-bridge2/ios/Bridge/Lib/FMDB 6 | https://zhangcong@svn.baidu.com/app/ecom/shifen/sf-crm 7 | 8 | 9 | 10 | 2013-12-31T11:02:36.073008Z 11 | 213942 12 | limingming02 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 498ed21b-be56-4397-9586-e640519e7b9f 28 | 29 | FMDatabaseAdditions.m 30 | file 31 | 32 | 33 | 34 | 35 | 2014-01-09T05:27:19.000000Z 36 | 78170d3c6880cc03cb59f82e399d8e16 37 | 2013-12-31T11:02:36.073008Z 38 | 213942 39 | limingming02 40 | has-props 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 6152 62 | 63 | FMDatabase.m 64 | file 65 | 66 | 67 | 68 | 69 | 2014-01-09T05:27:19.000000Z 70 | a9d43dd68690a6535cb95d5f8a64b785 71 | 2013-12-31T11:02:36.073008Z 72 | 213942 73 | limingming02 74 | has-props 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 36069 96 | 97 | FMDatabaseQueue.h 98 | file 99 | 100 | 101 | 102 | 103 | 2014-01-09T05:27:19.000000Z 104 | dbc3d5cb90a33ed4e1a7105039ce7fe9 105 | 2013-12-31T11:02:36.073008Z 106 | 213942 107 | limingming02 108 | has-props 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 5675 130 | 131 | FMResultSet.h 132 | file 133 | 134 | 135 | 136 | 137 | 2014-01-09T05:27:19.000000Z 138 | c36f42c49e005f0993629d94a704d9b4 139 | 2013-12-31T11:02:36.073008Z 140 | 213942 141 | limingming02 142 | has-props 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 11832 164 | 165 | fmdb.m 166 | file 167 | 168 | 169 | 170 | 171 | 2014-01-09T05:27:19.000000Z 172 | a3f0bde9d5b5738c7ba6a0625b0645fb 173 | 2013-12-31T11:02:36.073008Z 174 | 213942 175 | limingming02 176 | has-props 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 54797 198 | 199 | FMDatabasePool.h 200 | file 201 | 202 | 203 | 204 | 205 | 2014-01-09T05:27:19.000000Z 206 | 5cbd36948c42cf4caf94ab231d7cfe65 207 | 2013-12-31T11:02:36.073008Z 208 | 213942 209 | limingming02 210 | has-props 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 4329 232 | 233 | FMDatabaseQueue.m 234 | file 235 | 236 | 237 | 238 | 239 | 2014-01-09T05:27:19.000000Z 240 | 393503dca9f5e5355d8f8b6bb8aaecbf 241 | 2013-12-31T11:02:36.073008Z 242 | 213942 243 | limingming02 244 | has-props 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 5303 266 | 267 | FMResultSet.m 268 | file 269 | 270 | 271 | 272 | 273 | 2014-01-09T05:27:19.000000Z 274 | e1953741f320cfa63205807e83fb0c22 275 | 2013-12-31T11:02:36.073008Z 276 | 213942 277 | limingming02 278 | has-props 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 11379 300 | 301 | FMDatabaseAdditions.h 302 | file 303 | 304 | 305 | 306 | 307 | 2014-01-09T05:27:19.000000Z 308 | 017c995043def8757dee235b3d869deb 309 | 2013-12-31T11:02:36.073008Z 310 | 213942 311 | limingming02 312 | has-props 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 6255 334 | 335 | FMDatabasePool.m 336 | file 337 | 338 | 339 | 340 | 341 | 2014-01-09T05:27:19.000000Z 342 | 35d9a09e73162e99f50e1024c1b027df 343 | 2013-12-31T11:02:36.073008Z 344 | 213942 345 | limingming02 346 | has-props 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 6545 368 | 369 | FMDatabase.h 370 | file 371 | 372 | 373 | 374 | 375 | 2014-01-09T05:27:19.000000Z 376 | 5e33cabcea87a255afe5dd9bb118a3ad 377 | 2013-12-31T11:02:36.073008Z 378 | 213942 379 | limingming02 380 | has-props 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 34007 402 | 403 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabase.h.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabase.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabaseAdditions.h.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabaseAdditions.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabasePool.h.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabasePool.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabaseQueue.h.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMDatabaseQueue.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMResultSet.h.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/FMResultSet.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/prop-base/fmdb.m.svn-base: -------------------------------------------------------------------------------- 1 | K 14 2 | svn:executable 3 | V 1 4 | * 5 | END 6 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabaseAdditions.h.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** Category of additions for `` class. 12 | 13 | ### See also 14 | 15 | - `` 16 | */ 17 | 18 | @interface FMDatabase (FMDatabaseAdditions) 19 | 20 | ///---------------------------------------- 21 | /// @name Return results of SQL to variable 22 | ///---------------------------------------- 23 | 24 | /** Return `int` value for query 25 | 26 | @param query The SQL query to be performed. 27 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 28 | 29 | @return `int` value. 30 | */ 31 | 32 | - (int)intForQuery:(NSString*)query, ...; 33 | 34 | /** Return `long` value for query 35 | 36 | @param query The SQL query to be performed. 37 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 38 | 39 | @return `long` value. 40 | */ 41 | 42 | - (long)longForQuery:(NSString*)query, ...; 43 | 44 | /** Return `BOOL` value for query 45 | 46 | @param query The SQL query to be performed. 47 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 48 | 49 | @return `BOOL` value. 50 | */ 51 | 52 | - (BOOL)boolForQuery:(NSString*)query, ...; 53 | 54 | /** Return `double` value for query 55 | 56 | @param query The SQL query to be performed. 57 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 58 | 59 | @return `double` value. 60 | */ 61 | 62 | - (double)doubleForQuery:(NSString*)query, ...; 63 | 64 | /** Return `NSString` value for query 65 | 66 | @param query The SQL query to be performed. 67 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 68 | 69 | @return `NSString` value. 70 | */ 71 | 72 | - (NSString*)stringForQuery:(NSString*)query, ...; 73 | 74 | /** Return `NSData` value for query 75 | 76 | @param query The SQL query to be performed. 77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 78 | 79 | @return `NSData` value. 80 | */ 81 | 82 | - (NSData*)dataForQuery:(NSString*)query, ...; 83 | 84 | /** Return `NSDate` value for query 85 | 86 | @param query The SQL query to be performed. 87 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 88 | 89 | @return `NSDate` value. 90 | */ 91 | 92 | - (NSDate*)dateForQuery:(NSString*)query, ...; 93 | 94 | 95 | // Notice that there's no dataNoCopyForQuery:. 96 | // That would be a bad idea, because we close out the result set, and then what 97 | // happens to the data that we just didn't copy? Who knows, not I. 98 | 99 | 100 | ///-------------------------------- 101 | /// @name Schema related operations 102 | ///-------------------------------- 103 | 104 | /** Does table exist in database? 105 | 106 | @param tableName The name of the table being looked for. 107 | 108 | @return `YES` if table found; `NO` if not found. 109 | */ 110 | 111 | - (BOOL)tableExists:(NSString*)tableName; 112 | 113 | /** The schema of the database. 114 | 115 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: 116 | 117 | - `type` - The type of entity (e.g. table, index, view, or trigger) 118 | - `name` - The name of the object 119 | - `tbl_name` - The name of the table to which the object references 120 | - `rootpage` - The page number of the root b-tree page for tables and indices 121 | - `sql` - The SQL that created the entity 122 | 123 | @return `FMResultSet` of schema; `nil` on error. 124 | 125 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html) 126 | */ 127 | 128 | - (FMResultSet*)getSchema; 129 | 130 | /** The schema of the database. 131 | 132 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: 133 | 134 | PRAGMA table_info('employees') 135 | 136 | This will report: 137 | 138 | - `cid` - The column ID number 139 | - `name` - The name of the column 140 | - `type` - The data type specified for the column 141 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required) 142 | - `dflt_value` - The default value for the column 143 | - `pk` - Whether the field is part of the primary key of the table 144 | 145 | @param tableName The name of the table for whom the schema will be returned. 146 | 147 | @return `FMResultSet` of schema; `nil` on error. 148 | 149 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) 150 | */ 151 | 152 | - (FMResultSet*)getTableSchema:(NSString*)tableName; 153 | 154 | /** Test to see if particular column exists for particular table in database 155 | 156 | @param columnName The name of the column. 157 | 158 | @param tableName The name of the table. 159 | 160 | @return `YES` if column exists in table in question; `NO` otherwise. 161 | */ 162 | 163 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; 164 | 165 | /** Test to see if particular column exists for particular table in database 166 | 167 | @param columnName The name of the column. 168 | 169 | @param tableName The name of the table. 170 | 171 | @return `YES` if column exists in table in question; `NO` otherwise. 172 | 173 | @see columnExists:inTableWithName: 174 | 175 | @warning Deprecated - use `` instead. 176 | */ 177 | 178 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)); 179 | 180 | 181 | /** Validate SQL statement 182 | 183 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. 184 | 185 | @param sql The SQL statement being validated. 186 | 187 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. 188 | 189 | @return `YES` if validation succeeded without incident; `NO` otherwise. 190 | 191 | */ 192 | 193 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error; 194 | 195 | 196 | #if SQLITE_VERSION_NUMBER >= 3007017 197 | 198 | ///----------------------------------- 199 | /// @name Application identifier tasks 200 | ///----------------------------------- 201 | 202 | /** Retrieve application ID 203 | 204 | @return The `uint32_t` numeric value of the application ID. 205 | 206 | @see setApplicationID: 207 | */ 208 | 209 | - (uint32_t)applicationID; 210 | 211 | /** Set the application ID 212 | 213 | @param appID The `uint32_t` numeric value of the application ID. 214 | 215 | @see applicationID 216 | */ 217 | 218 | - (void)setApplicationID:(uint32_t)appID; 219 | 220 | /** Retrieve application ID string 221 | 222 | @return The `NSString` value of the application ID. 223 | 224 | @see setApplicationIDString: 225 | */ 226 | 227 | - (NSString*)applicationIDString; 228 | 229 | /** Set the application ID string 230 | 231 | @param string The `NSString` value of the application ID. 232 | 233 | @see applicationIDString 234 | */ 235 | 236 | - (void)setApplicationIDString:(NSString*)string; 237 | #endif 238 | 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabaseAdditions.m.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import "FMDatabase.h" 10 | #import "FMDatabaseAdditions.h" 11 | #import "TargetConditionals.h" 12 | 13 | @interface FMDatabase (PrivateStuff) 14 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args; 15 | @end 16 | 17 | @implementation FMDatabase (FMDatabaseAdditions) 18 | 19 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ 20 | va_list args; \ 21 | va_start(args, query); \ 22 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ 23 | va_end(args); \ 24 | if (![resultSet next]) { return (type)0; } \ 25 | type ret = [resultSet sel:0]; \ 26 | [resultSet close]; \ 27 | [resultSet setParentDB:nil]; \ 28 | return ret; 29 | 30 | 31 | - (NSString*)stringForQuery:(NSString*)query, ... { 32 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); 33 | } 34 | 35 | - (int)intForQuery:(NSString*)query, ... { 36 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); 37 | } 38 | 39 | - (long)longForQuery:(NSString*)query, ... { 40 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); 41 | } 42 | 43 | - (BOOL)boolForQuery:(NSString*)query, ... { 44 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); 45 | } 46 | 47 | - (double)doubleForQuery:(NSString*)query, ... { 48 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); 49 | } 50 | 51 | - (NSData*)dataForQuery:(NSString*)query, ... { 52 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); 53 | } 54 | 55 | - (NSDate*)dateForQuery:(NSString*)query, ... { 56 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); 57 | } 58 | 59 | 60 | - (BOOL)tableExists:(NSString*)tableName { 61 | 62 | tableName = [tableName lowercaseString]; 63 | 64 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; 65 | 66 | //if at least one next exists, table exists 67 | BOOL returnBool = [rs next]; 68 | 69 | //close and free object 70 | [rs close]; 71 | 72 | return returnBool; 73 | } 74 | 75 | /* 76 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 77 | check if table exist in database (patch from OZLB) 78 | */ 79 | - (FMResultSet*)getSchema { 80 | 81 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 82 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; 83 | 84 | return rs; 85 | } 86 | 87 | /* 88 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 89 | */ 90 | - (FMResultSet*)getTableSchema:(NSString*)tableName { 91 | 92 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 93 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info('%@')", tableName]]; 94 | 95 | return rs; 96 | } 97 | 98 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { 99 | 100 | BOOL returnBool = NO; 101 | 102 | tableName = [tableName lowercaseString]; 103 | columnName = [columnName lowercaseString]; 104 | 105 | FMResultSet *rs = [self getTableSchema:tableName]; 106 | 107 | //check if column is present in table schema 108 | while ([rs next]) { 109 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { 110 | returnBool = YES; 111 | break; 112 | } 113 | } 114 | 115 | //If this is not done FMDatabase instance stays out of pool 116 | [rs close]; 117 | 118 | return returnBool; 119 | } 120 | 121 | 122 | #if SQLITE_VERSION_NUMBER >= 3007017 123 | 124 | - (uint32_t)applicationID { 125 | 126 | uint32_t r = 0; 127 | 128 | FMResultSet *rs = [self executeQuery:@"pragma application_id"]; 129 | 130 | if ([rs next]) { 131 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 132 | } 133 | 134 | [rs close]; 135 | 136 | return r; 137 | } 138 | 139 | - (void)setApplicationID:(uint32_t)appID { 140 | NSString *query = [NSString stringWithFormat:@"PRAGMA application_id=%d", appID]; 141 | FMResultSet *rs = [self executeQuery:query]; 142 | [rs next]; 143 | [rs close]; 144 | } 145 | 146 | 147 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 148 | - (NSString*)applicationIDString { 149 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); 150 | 151 | assert([s length] == 6); 152 | 153 | s = [s substringWithRange:NSMakeRange(1, 4)]; 154 | 155 | 156 | return s; 157 | 158 | } 159 | 160 | - (void)setApplicationIDString:(NSString*)s { 161 | 162 | if ([s length] != 4) { 163 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); 164 | } 165 | 166 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; 167 | } 168 | 169 | 170 | #endif 171 | 172 | #endif 173 | 174 | #pragma clang diagnostic push 175 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 176 | 177 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { 178 | return [self columnExists:columnName inTableWithName:tableName]; 179 | } 180 | 181 | #pragma clang diagnostic pop 182 | 183 | 184 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { 185 | sqlite3_stmt *pStmt = NULL; 186 | BOOL validationSucceeded = YES; 187 | 188 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); 189 | if (rc != SQLITE_OK) { 190 | validationSucceeded = NO; 191 | if (error) { 192 | *error = [NSError errorWithDomain:NSCocoaErrorDomain 193 | code:[self lastErrorCode] 194 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] 195 | forKey:NSLocalizedDescriptionKey]]; 196 | } 197 | } 198 | 199 | sqlite3_finalize(pStmt); 200 | 201 | return validationSucceeded; 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabasePool.h.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** Pool of `` objects. 15 | 16 | ### See also 17 | 18 | - `` 19 | - `` 20 | 21 | @warning Before using `FMDatabasePool`, please consider using `` instead. 22 | 23 | If you really really really know what you're doing and `FMDatabasePool` is what 24 | you really really need (ie, you're using a read only database), OK you can use 25 | it. But just be careful not to deadlock! 26 | 27 | For an example on deadlocking, search for: 28 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` 29 | in the main.m file. 30 | */ 31 | 32 | @interface FMDatabasePool : NSObject { 33 | NSString *_path; 34 | 35 | dispatch_queue_t _lockQueue; 36 | 37 | NSMutableArray *_databaseInPool; 38 | NSMutableArray *_databaseOutPool; 39 | 40 | __unsafe_unretained id _delegate; 41 | 42 | NSUInteger _maximumNumberOfDatabasesToCreate; 43 | int _openFlags; 44 | } 45 | 46 | @property (atomic, retain) NSString *path; 47 | @property (atomic, assign) id delegate; 48 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; 49 | @property (atomic, readonly) int openFlags; 50 | 51 | ///--------------------- 52 | /// @name Initialization 53 | ///--------------------- 54 | 55 | /** Create pool using path. 56 | 57 | @param aPath The file path of the database. 58 | 59 | @return The `FMDatabasePool` object. `nil` on error. 60 | */ 61 | 62 | + (instancetype)databasePoolWithPath:(NSString*)aPath; 63 | 64 | /** Create pool using path and specified flags 65 | 66 | @param aPath The file path of the database. 67 | @param openFlags Flags passed to the openWithFlags method of the database 68 | 69 | @return The `FMDatabasePool` object. `nil` on error. 70 | */ 71 | 72 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags; 73 | 74 | /** Create pool using path. 75 | 76 | @param aPath The file path of the database. 77 | 78 | @return The `FMDatabasePool` object. `nil` on error. 79 | */ 80 | 81 | - (instancetype)initWithPath:(NSString*)aPath; 82 | 83 | /** Create pool using path and specified flags. 84 | 85 | @param aPath The file path of the database. 86 | @param openFlags Flags passed to the openWithFlags method of the database 87 | 88 | @return The `FMDatabasePool` object. `nil` on error. 89 | */ 90 | 91 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 92 | 93 | ///------------------------------------------------ 94 | /// @name Keeping track of checked in/out databases 95 | ///------------------------------------------------ 96 | 97 | /** Number of checked-in databases in pool 98 | 99 | @returns Number of databases 100 | */ 101 | 102 | - (NSUInteger)countOfCheckedInDatabases; 103 | 104 | /** Number of checked-out databases in pool 105 | 106 | @returns Number of databases 107 | */ 108 | 109 | - (NSUInteger)countOfCheckedOutDatabases; 110 | 111 | /** Total number of databases in pool 112 | 113 | @returns Number of databases 114 | */ 115 | 116 | - (NSUInteger)countOfOpenDatabases; 117 | 118 | /** Release all databases in pool */ 119 | 120 | - (void)releaseAllDatabases; 121 | 122 | ///------------------------------------------ 123 | /// @name Perform database operations in pool 124 | ///------------------------------------------ 125 | 126 | /** Synchronously perform database operations in pool. 127 | 128 | @param block The code to be run on the `FMDatabasePool` pool. 129 | */ 130 | 131 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 132 | 133 | /** Synchronously perform database operations in pool using transaction. 134 | 135 | @param block The code to be run on the `FMDatabasePool` pool. 136 | */ 137 | 138 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 139 | 140 | /** Synchronously perform database operations in pool using deferred transaction. 141 | 142 | @param block The code to be run on the `FMDatabasePool` pool. 143 | */ 144 | 145 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 146 | 147 | #if SQLITE_VERSION_NUMBER >= 3007000 148 | 149 | /** Synchronously perform database operations in pool using save point. 150 | 151 | @param block The code to be run on the `FMDatabasePool` pool. 152 | 153 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. 154 | */ 155 | 156 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 157 | #endif 158 | 159 | @end 160 | 161 | 162 | @interface NSObject (FMDatabasePoolDelegate) 163 | 164 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; 165 | 166 | @end 167 | 168 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabasePool.m.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabasePool.h" 10 | #import "FMDatabase.h" 11 | 12 | @interface FMDatabasePool() 13 | 14 | - (void)pushDatabaseBackInPool:(FMDatabase*)db; 15 | - (FMDatabase*)db; 16 | 17 | @end 18 | 19 | 20 | @implementation FMDatabasePool 21 | @synthesize path=_path; 22 | @synthesize delegate=_delegate; 23 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate; 24 | @synthesize openFlags=_openFlags; 25 | 26 | 27 | + (instancetype)databasePoolWithPath:(NSString*)aPath { 28 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); 29 | } 30 | 31 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags { 32 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]); 33 | } 34 | 35 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 36 | 37 | self = [super init]; 38 | 39 | if (self != nil) { 40 | _path = [aPath copy]; 41 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 42 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]); 43 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]); 44 | _openFlags = openFlags; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (instancetype)initWithPath:(NSString*)aPath 51 | { 52 | // default flags for sqlite3_open 53 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 54 | } 55 | 56 | - (instancetype)init { 57 | return [self initWithPath:nil]; 58 | } 59 | 60 | 61 | - (void)dealloc { 62 | 63 | _delegate = 0x00; 64 | FMDBRelease(_path); 65 | FMDBRelease(_databaseInPool); 66 | FMDBRelease(_databaseOutPool); 67 | 68 | if (_lockQueue) { 69 | FMDBDispatchQueueRelease(_lockQueue); 70 | _lockQueue = 0x00; 71 | } 72 | #if ! __has_feature(objc_arc) 73 | [super dealloc]; 74 | #endif 75 | } 76 | 77 | 78 | - (void)executeLocked:(void (^)(void))aBlock { 79 | dispatch_sync(_lockQueue, aBlock); 80 | } 81 | 82 | - (void)pushDatabaseBackInPool:(FMDatabase*)db { 83 | 84 | if (!db) { // db can be null if we set an upper bound on the # of databases to create. 85 | return; 86 | } 87 | 88 | [self executeLocked:^() { 89 | 90 | if ([_databaseInPool containsObject:db]) { 91 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise]; 92 | } 93 | 94 | [_databaseInPool addObject:db]; 95 | [_databaseOutPool removeObject:db]; 96 | 97 | }]; 98 | } 99 | 100 | - (FMDatabase*)db { 101 | 102 | __block FMDatabase *db; 103 | 104 | [self executeLocked:^() { 105 | db = [_databaseInPool lastObject]; 106 | 107 | if (db) { 108 | [_databaseOutPool addObject:db]; 109 | [_databaseInPool removeLastObject]; 110 | } 111 | else { 112 | 113 | if (_maximumNumberOfDatabasesToCreate) { 114 | NSUInteger currentCount = [_databaseOutPool count] + [_databaseInPool count]; 115 | 116 | if (currentCount >= _maximumNumberOfDatabasesToCreate) { 117 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount); 118 | return; 119 | } 120 | } 121 | 122 | db = [FMDatabase databaseWithPath:_path]; 123 | } 124 | 125 | //This ensures that the db is opened before returning 126 | #if SQLITE_VERSION_NUMBER >= 3005000 127 | if ([db openWithFlags:_openFlags]) { 128 | #else 129 | if ([db open]) { 130 | #endif 131 | if ([_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![_delegate databasePool:self shouldAddDatabaseToPool:db]) { 132 | [db close]; 133 | db = 0x00; 134 | } 135 | else { 136 | //It should not get added in the pool twice if lastObject was found 137 | if (![_databaseOutPool containsObject:db]) { 138 | [_databaseOutPool addObject:db]; 139 | } 140 | } 141 | } 142 | else { 143 | NSLog(@"Could not open up the database at path %@", _path); 144 | db = 0x00; 145 | } 146 | }]; 147 | 148 | return db; 149 | } 150 | 151 | - (NSUInteger)countOfCheckedInDatabases { 152 | 153 | __block NSUInteger count; 154 | 155 | [self executeLocked:^() { 156 | count = [_databaseInPool count]; 157 | }]; 158 | 159 | return count; 160 | } 161 | 162 | - (NSUInteger)countOfCheckedOutDatabases { 163 | 164 | __block NSUInteger count; 165 | 166 | [self executeLocked:^() { 167 | count = [_databaseOutPool count]; 168 | }]; 169 | 170 | return count; 171 | } 172 | 173 | - (NSUInteger)countOfOpenDatabases { 174 | __block NSUInteger count; 175 | 176 | [self executeLocked:^() { 177 | count = [_databaseOutPool count] + [_databaseInPool count]; 178 | }]; 179 | 180 | return count; 181 | } 182 | 183 | - (void)releaseAllDatabases { 184 | [self executeLocked:^() { 185 | [_databaseOutPool removeAllObjects]; 186 | [_databaseInPool removeAllObjects]; 187 | }]; 188 | } 189 | 190 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 191 | 192 | FMDatabase *db = [self db]; 193 | 194 | block(db); 195 | 196 | [self pushDatabaseBackInPool:db]; 197 | } 198 | 199 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 200 | 201 | BOOL shouldRollback = NO; 202 | 203 | FMDatabase *db = [self db]; 204 | 205 | if (useDeferred) { 206 | [db beginDeferredTransaction]; 207 | } 208 | else { 209 | [db beginTransaction]; 210 | } 211 | 212 | 213 | block(db, &shouldRollback); 214 | 215 | if (shouldRollback) { 216 | [db rollback]; 217 | } 218 | else { 219 | [db commit]; 220 | } 221 | 222 | [self pushDatabaseBackInPool:db]; 223 | } 224 | 225 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 226 | [self beginTransaction:YES withBlock:block]; 227 | } 228 | 229 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 230 | [self beginTransaction:NO withBlock:block]; 231 | } 232 | #if SQLITE_VERSION_NUMBER >= 3007000 233 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 234 | 235 | static unsigned long savePointIdx = 0; 236 | 237 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 238 | 239 | BOOL shouldRollback = NO; 240 | 241 | FMDatabase *db = [self db]; 242 | 243 | NSError *err = 0x00; 244 | 245 | if (![db startSavePointWithName:name error:&err]) { 246 | [self pushDatabaseBackInPool:db]; 247 | return err; 248 | } 249 | 250 | block(db, &shouldRollback); 251 | 252 | if (shouldRollback) { 253 | // We need to rollback and release this savepoint to remove it 254 | [db rollbackToSavePointWithName:name error:&err]; 255 | } 256 | [db releaseSavePointWithName:name error:&err]; 257 | 258 | [self pushDatabaseBackInPool:db]; 259 | 260 | return err; 261 | } 262 | #endif 263 | 264 | @end 265 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabaseQueue.h.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`. 15 | 16 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time. 17 | 18 | Instead, use `FMDatabaseQueue`. Here's how to use it: 19 | 20 | First, make your queue. 21 | 22 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 23 | 24 | Then use it like so: 25 | 26 | [queue inDatabase:^(FMDatabase *db) { 27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 29 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 30 | 31 | FMResultSet *rs = [db executeQuery:@"select * from foo"]; 32 | while ([rs next]) { 33 | //… 34 | } 35 | }]; 36 | 37 | An easy way to wrap things up in a transaction can be done like this: 38 | 39 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 42 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 43 | 44 | if (whoopsSomethingWrongHappened) { 45 | *rollback = YES; 46 | return; 47 | } 48 | // etc… 49 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; 50 | }]; 51 | 52 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy. 53 | 54 | ### See also 55 | 56 | - `` 57 | 58 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead. 59 | 60 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread. 61 | 62 | */ 63 | 64 | @interface FMDatabaseQueue : NSObject { 65 | NSString *_path; 66 | dispatch_queue_t _queue; 67 | FMDatabase *_db; 68 | int _openFlags; 69 | } 70 | 71 | @property (atomic, retain) NSString *path; 72 | @property (atomic, readonly) int openFlags; 73 | 74 | ///---------------------------------------------------- 75 | /// @name Initialization, opening, and closing of queue 76 | ///---------------------------------------------------- 77 | 78 | /** Create queue using path. 79 | 80 | @param aPath The file path of the database. 81 | 82 | @return The `FMDatabaseQueue` object. `nil` on error. 83 | */ 84 | 85 | + (instancetype)databaseQueueWithPath:(NSString*)aPath; 86 | 87 | /** Create queue using path and specified flags. 88 | 89 | @param aPath The file path of the database. 90 | @param openFlags Flags passed to the openWithFlags method of the database 91 | 92 | @return The `FMDatabaseQueue` object. `nil` on error. 93 | */ 94 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags; 95 | 96 | /** Create queue using path. 97 | 98 | @param aPath The file path of the database. 99 | 100 | @return The `FMDatabaseQueue` object. `nil` on error. 101 | */ 102 | 103 | - (instancetype)initWithPath:(NSString*)aPath; 104 | 105 | /** Create queue using path and specified flags. 106 | 107 | @param aPath The file path of the database. 108 | @param openFlags Flags passed to the openWithFlags method of the database 109 | 110 | @return The `FMDatabaseQueue` object. `nil` on error. 111 | */ 112 | 113 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 114 | 115 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. 116 | 117 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass. 118 | 119 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. 120 | */ 121 | 122 | + (Class)databaseClass; 123 | 124 | /** Close database used by queue. */ 125 | 126 | - (void)close; 127 | 128 | ///----------------------------------------------- 129 | /// @name Dispatching database operations to queue 130 | ///----------------------------------------------- 131 | 132 | /** Synchronously perform database operations on queue. 133 | 134 | @param block The code to be run on the queue of `FMDatabaseQueue` 135 | */ 136 | 137 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 138 | 139 | /** Synchronously perform database operations on queue, using transactions. 140 | 141 | @param block The code to be run on the queue of `FMDatabaseQueue` 142 | */ 143 | 144 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 145 | 146 | /** Synchronously perform database operations on queue, using deferred transactions. 147 | 148 | @param block The code to be run on the queue of `FMDatabaseQueue` 149 | */ 150 | 151 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 152 | 153 | ///----------------------------------------------- 154 | /// @name Dispatching database operations to queue 155 | ///----------------------------------------------- 156 | 157 | /** Synchronously perform database operations using save point. 158 | 159 | @param block The code to be run on the queue of `FMDatabaseQueue` 160 | */ 161 | 162 | #if SQLITE_VERSION_NUMBER >= 3007000 163 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. 164 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead. 165 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 166 | #endif 167 | 168 | @end 169 | 170 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/.svn/text-base/FMDatabaseQueue.m.svn-base: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabase.h" 11 | 12 | /* 13 | 14 | Note: we call [self retain]; before using dispatch_sync, just incase 15 | FMDatabaseQueue is released on another thread and we're in the middle of doing 16 | something in dispatch_sync 17 | 18 | */ 19 | 20 | @implementation FMDatabaseQueue 21 | 22 | @synthesize path = _path; 23 | @synthesize openFlags = _openFlags; 24 | 25 | + (instancetype)databaseQueueWithPath:(NSString*)aPath { 26 | 27 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath]; 28 | 29 | FMDBAutorelease(q); 30 | 31 | return q; 32 | } 33 | 34 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags { 35 | 36 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags]; 37 | 38 | FMDBAutorelease(q); 39 | 40 | return q; 41 | } 42 | 43 | + (Class)databaseClass { 44 | return [FMDatabase class]; 45 | } 46 | 47 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 48 | 49 | self = [super init]; 50 | 51 | if (self != nil) { 52 | 53 | _db = [[[self class] databaseClass] databaseWithPath:aPath]; 54 | FMDBRetain(_db); 55 | 56 | #if SQLITE_VERSION_NUMBER >= 3005000 57 | if (![_db openWithFlags:openFlags]) { 58 | #else 59 | if (![_db open]) { 60 | #endif 61 | NSLog(@"Could not create database queue for path %@", aPath); 62 | FMDBRelease(self); 63 | return 0x00; 64 | } 65 | 66 | _path = FMDBReturnRetained(aPath); 67 | 68 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 69 | _openFlags = openFlags; 70 | } 71 | 72 | return self; 73 | } 74 | 75 | - (instancetype)initWithPath:(NSString*)aPath { 76 | 77 | // default flags for sqlite3_open 78 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 79 | } 80 | 81 | - (instancetype)init { 82 | return [self initWithPath:nil]; 83 | } 84 | 85 | 86 | - (void)dealloc { 87 | 88 | FMDBRelease(_db); 89 | FMDBRelease(_path); 90 | 91 | if (_queue) { 92 | FMDBDispatchQueueRelease(_queue); 93 | _queue = 0x00; 94 | } 95 | #if ! __has_feature(objc_arc) 96 | [super dealloc]; 97 | #endif 98 | } 99 | 100 | - (void)close { 101 | FMDBRetain(self); 102 | dispatch_sync(_queue, ^() { 103 | [_db close]; 104 | FMDBRelease(_db); 105 | _db = 0x00; 106 | }); 107 | FMDBRelease(self); 108 | } 109 | 110 | - (FMDatabase*)database { 111 | if (!_db) { 112 | _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]); 113 | 114 | #if SQLITE_VERSION_NUMBER >= 3005000 115 | if (![_db openWithFlags:_openFlags]) { 116 | #else 117 | if (![db open]) { 118 | #endif 119 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path); 120 | FMDBRelease(_db); 121 | _db = 0x00; 122 | return 0x00; 123 | } 124 | } 125 | 126 | return _db; 127 | } 128 | 129 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 130 | FMDBRetain(self); 131 | 132 | dispatch_sync(_queue, ^() { 133 | 134 | FMDatabase *db = [self database]; 135 | block(db); 136 | 137 | if ([db hasOpenResultSets]) { 138 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]"); 139 | 140 | #ifdef DEBUG 141 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]); 142 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { 143 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; 144 | NSLog(@"query: '%@'", [rs query]); 145 | } 146 | #endif 147 | } 148 | }); 149 | 150 | FMDBRelease(self); 151 | } 152 | 153 | 154 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 155 | FMDBRetain(self); 156 | dispatch_sync(_queue, ^() { 157 | 158 | BOOL shouldRollback = NO; 159 | 160 | if (useDeferred) { 161 | [[self database] beginDeferredTransaction]; 162 | } 163 | else { 164 | [[self database] beginTransaction]; 165 | } 166 | 167 | block([self database], &shouldRollback); 168 | 169 | if (shouldRollback) { 170 | [[self database] rollback]; 171 | } 172 | else { 173 | [[self database] commit]; 174 | } 175 | }); 176 | 177 | FMDBRelease(self); 178 | } 179 | 180 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 181 | [self beginTransaction:YES withBlock:block]; 182 | } 183 | 184 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 185 | [self beginTransaction:NO withBlock:block]; 186 | } 187 | 188 | #if SQLITE_VERSION_NUMBER >= 3007000 189 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 190 | 191 | static unsigned long savePointIdx = 0; 192 | __block NSError *err = 0x00; 193 | FMDBRetain(self); 194 | dispatch_sync(_queue, ^() { 195 | 196 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 197 | 198 | BOOL shouldRollback = NO; 199 | 200 | if ([[self database] startSavePointWithName:name error:&err]) { 201 | 202 | block([self database], &shouldRollback); 203 | 204 | if (shouldRollback) { 205 | // We need to rollback and release this savepoint to remove it 206 | [[self database] rollbackToSavePointWithName:name error:&err]; 207 | } 208 | [[self database] releaseSavePointWithName:name error:&err]; 209 | 210 | } 211 | }); 212 | FMDBRelease(self); 213 | return err; 214 | } 215 | #endif 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabaseAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** Category of additions for `` class. 12 | 13 | ### See also 14 | 15 | - `` 16 | */ 17 | 18 | @interface FMDatabase (FMDatabaseAdditions) 19 | 20 | ///---------------------------------------- 21 | /// @name Return results of SQL to variable 22 | ///---------------------------------------- 23 | 24 | /** Return `int` value for query 25 | 26 | @param query The SQL query to be performed. 27 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 28 | 29 | @return `int` value. 30 | */ 31 | 32 | - (int)intForQuery:(NSString*)query, ...; 33 | 34 | /** Return `long` value for query 35 | 36 | @param query The SQL query to be performed. 37 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 38 | 39 | @return `long` value. 40 | */ 41 | 42 | - (long)longForQuery:(NSString*)query, ...; 43 | 44 | /** Return `BOOL` value for query 45 | 46 | @param query The SQL query to be performed. 47 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 48 | 49 | @return `BOOL` value. 50 | */ 51 | 52 | - (BOOL)boolForQuery:(NSString*)query, ...; 53 | 54 | /** Return `double` value for query 55 | 56 | @param query The SQL query to be performed. 57 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 58 | 59 | @return `double` value. 60 | */ 61 | 62 | - (double)doubleForQuery:(NSString*)query, ...; 63 | 64 | /** Return `NSString` value for query 65 | 66 | @param query The SQL query to be performed. 67 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 68 | 69 | @return `NSString` value. 70 | */ 71 | 72 | - (NSString*)stringForQuery:(NSString*)query, ...; 73 | 74 | /** Return `NSData` value for query 75 | 76 | @param query The SQL query to be performed. 77 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 78 | 79 | @return `NSData` value. 80 | */ 81 | 82 | - (NSData*)dataForQuery:(NSString*)query, ...; 83 | 84 | /** Return `NSDate` value for query 85 | 86 | @param query The SQL query to be performed. 87 | @param ... A list of parameters that will be bound to the `?` placeholders in the SQL query. 88 | 89 | @return `NSDate` value. 90 | */ 91 | 92 | - (NSDate*)dateForQuery:(NSString*)query, ...; 93 | 94 | 95 | // Notice that there's no dataNoCopyForQuery:. 96 | // That would be a bad idea, because we close out the result set, and then what 97 | // happens to the data that we just didn't copy? Who knows, not I. 98 | 99 | 100 | ///-------------------------------- 101 | /// @name Schema related operations 102 | ///-------------------------------- 103 | 104 | /** Does table exist in database? 105 | 106 | @param tableName The name of the table being looked for. 107 | 108 | @return `YES` if table found; `NO` if not found. 109 | */ 110 | 111 | - (BOOL)tableExists:(NSString*)tableName; 112 | 113 | /** The schema of the database. 114 | 115 | This will be the schema for the entire database. For each entity, each row of the result set will include the following fields: 116 | 117 | - `type` - The type of entity (e.g. table, index, view, or trigger) 118 | - `name` - The name of the object 119 | - `tbl_name` - The name of the table to which the object references 120 | - `rootpage` - The page number of the root b-tree page for tables and indices 121 | - `sql` - The SQL that created the entity 122 | 123 | @return `FMResultSet` of schema; `nil` on error. 124 | 125 | @see [SQLite File Format](http://www.sqlite.org/fileformat.html) 126 | */ 127 | 128 | - (FMResultSet*)getSchema; 129 | 130 | /** The schema of the database. 131 | 132 | This will be the schema for a particular table as report by SQLite `PRAGMA`, for example: 133 | 134 | PRAGMA table_info('employees') 135 | 136 | This will report: 137 | 138 | - `cid` - The column ID number 139 | - `name` - The name of the column 140 | - `type` - The data type specified for the column 141 | - `notnull` - whether the field is defined as NOT NULL (i.e. values required) 142 | - `dflt_value` - The default value for the column 143 | - `pk` - Whether the field is part of the primary key of the table 144 | 145 | @param tableName The name of the table for whom the schema will be returned. 146 | 147 | @return `FMResultSet` of schema; `nil` on error. 148 | 149 | @see [table_info](http://www.sqlite.org/pragma.html#pragma_table_info) 150 | */ 151 | 152 | - (FMResultSet*)getTableSchema:(NSString*)tableName; 153 | 154 | /** Test to see if particular column exists for particular table in database 155 | 156 | @param columnName The name of the column. 157 | 158 | @param tableName The name of the table. 159 | 160 | @return `YES` if column exists in table in question; `NO` otherwise. 161 | */ 162 | 163 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName; 164 | 165 | /** Test to see if particular column exists for particular table in database 166 | 167 | @param columnName The name of the column. 168 | 169 | @param tableName The name of the table. 170 | 171 | @return `YES` if column exists in table in question; `NO` otherwise. 172 | 173 | @see columnExists:inTableWithName: 174 | 175 | @warning Deprecated - use `` instead. 176 | */ 177 | 178 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)); 179 | 180 | 181 | /** Validate SQL statement 182 | 183 | This validates SQL statement by performing `sqlite3_prepare_v2`, but not returning the results, but instead immediately calling `sqlite3_finalize`. 184 | 185 | @param sql The SQL statement being validated. 186 | 187 | @param error This is a pointer to a `NSError` object that will receive the autoreleased `NSError` object if there was any error. If this is `nil`, no `NSError` result will be returned. 188 | 189 | @return `YES` if validation succeeded without incident; `NO` otherwise. 190 | 191 | */ 192 | 193 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error; 194 | 195 | 196 | #if SQLITE_VERSION_NUMBER >= 3007017 197 | 198 | ///----------------------------------- 199 | /// @name Application identifier tasks 200 | ///----------------------------------- 201 | 202 | /** Retrieve application ID 203 | 204 | @return The `uint32_t` numeric value of the application ID. 205 | 206 | @see setApplicationID: 207 | */ 208 | 209 | - (uint32_t)applicationID; 210 | 211 | /** Set the application ID 212 | 213 | @param appID The `uint32_t` numeric value of the application ID. 214 | 215 | @see applicationID 216 | */ 217 | 218 | - (void)setApplicationID:(uint32_t)appID; 219 | 220 | /** Retrieve application ID string 221 | 222 | @return The `NSString` value of the application ID. 223 | 224 | @see setApplicationIDString: 225 | */ 226 | 227 | - (NSString*)applicationIDString; 228 | 229 | /** Set the application ID string 230 | 231 | @param string The `NSString` value of the application ID. 232 | 233 | @see applicationIDString 234 | */ 235 | 236 | - (void)setApplicationIDString:(NSString*)string; 237 | #endif 238 | 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabaseAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseAdditions.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 10/30/05. 6 | // Copyright 2005 Flying Meat Inc.. All rights reserved. 7 | // 8 | 9 | #import "FMDatabase.h" 10 | #import "FMDatabaseAdditions.h" 11 | #import "TargetConditionals.h" 12 | 13 | @interface FMDatabase (PrivateStuff) 14 | - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray*)arrayArgs orDictionary:(NSDictionary *)dictionaryArgs orVAList:(va_list)args; 15 | @end 16 | 17 | @implementation FMDatabase (FMDatabaseAdditions) 18 | 19 | #define RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(type, sel) \ 20 | va_list args; \ 21 | va_start(args, query); \ 22 | FMResultSet *resultSet = [self executeQuery:query withArgumentsInArray:0x00 orDictionary:0x00 orVAList:args]; \ 23 | va_end(args); \ 24 | if (![resultSet next]) { return (type)0; } \ 25 | type ret = [resultSet sel:0]; \ 26 | [resultSet close]; \ 27 | [resultSet setParentDB:nil]; \ 28 | return ret; 29 | 30 | 31 | - (NSString*)stringForQuery:(NSString*)query, ... { 32 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSString *, stringForColumnIndex); 33 | } 34 | 35 | - (int)intForQuery:(NSString*)query, ... { 36 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(int, intForColumnIndex); 37 | } 38 | 39 | - (long)longForQuery:(NSString*)query, ... { 40 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(long, longForColumnIndex); 41 | } 42 | 43 | - (BOOL)boolForQuery:(NSString*)query, ... { 44 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(BOOL, boolForColumnIndex); 45 | } 46 | 47 | - (double)doubleForQuery:(NSString*)query, ... { 48 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(double, doubleForColumnIndex); 49 | } 50 | 51 | - (NSData*)dataForQuery:(NSString*)query, ... { 52 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSData *, dataForColumnIndex); 53 | } 54 | 55 | - (NSDate*)dateForQuery:(NSString*)query, ... { 56 | RETURN_RESULT_FOR_QUERY_WITH_SELECTOR(NSDate *, dateForColumnIndex); 57 | } 58 | 59 | 60 | - (BOOL)tableExists:(NSString*)tableName { 61 | 62 | tableName = [tableName lowercaseString]; 63 | 64 | FMResultSet *rs = [self executeQuery:@"select [sql] from sqlite_master where [type] = 'table' and lower(name) = ?", tableName]; 65 | 66 | //if at least one next exists, table exists 67 | BOOL returnBool = [rs next]; 68 | 69 | //close and free object 70 | [rs close]; 71 | 72 | return returnBool; 73 | } 74 | 75 | /* 76 | get table with list of tables: result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 77 | check if table exist in database (patch from OZLB) 78 | */ 79 | - (FMResultSet*)getSchema { 80 | 81 | //result colums: type[STRING], name[STRING],tbl_name[STRING],rootpage[INTEGER],sql[STRING] 82 | FMResultSet *rs = [self executeQuery:@"SELECT type, name, tbl_name, rootpage, sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type != 'meta' AND name NOT LIKE 'sqlite_%' ORDER BY tbl_name, type DESC, name"]; 83 | 84 | return rs; 85 | } 86 | 87 | /* 88 | get table schema: result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 89 | */ 90 | - (FMResultSet*)getTableSchema:(NSString*)tableName { 91 | 92 | //result colums: cid[INTEGER], name,type [STRING], notnull[INTEGER], dflt_value[],pk[INTEGER] 93 | FMResultSet *rs = [self executeQuery:[NSString stringWithFormat: @"PRAGMA table_info('%@')", tableName]]; 94 | 95 | return rs; 96 | } 97 | 98 | - (BOOL)columnExists:(NSString*)columnName inTableWithName:(NSString*)tableName { 99 | 100 | BOOL returnBool = NO; 101 | 102 | tableName = [tableName lowercaseString]; 103 | columnName = [columnName lowercaseString]; 104 | 105 | FMResultSet *rs = [self getTableSchema:tableName]; 106 | 107 | //check if column is present in table schema 108 | while ([rs next]) { 109 | if ([[[rs stringForColumn:@"name"] lowercaseString] isEqualToString:columnName]) { 110 | returnBool = YES; 111 | break; 112 | } 113 | } 114 | 115 | //If this is not done FMDatabase instance stays out of pool 116 | [rs close]; 117 | 118 | return returnBool; 119 | } 120 | 121 | 122 | #if SQLITE_VERSION_NUMBER >= 3007017 123 | 124 | - (uint32_t)applicationID { 125 | 126 | uint32_t r = 0; 127 | 128 | FMResultSet *rs = [self executeQuery:@"pragma application_id"]; 129 | 130 | if ([rs next]) { 131 | r = (uint32_t)[rs longLongIntForColumnIndex:0]; 132 | } 133 | 134 | [rs close]; 135 | 136 | return r; 137 | } 138 | 139 | - (void)setApplicationID:(uint32_t)appID { 140 | NSString *query = [NSString stringWithFormat:@"PRAGMA application_id=%d", appID]; 141 | FMResultSet *rs = [self executeQuery:query]; 142 | [rs next]; 143 | [rs close]; 144 | } 145 | 146 | 147 | #if TARGET_OS_MAC && !TARGET_OS_IPHONE 148 | - (NSString*)applicationIDString { 149 | NSString *s = NSFileTypeForHFSTypeCode([self applicationID]); 150 | 151 | assert([s length] == 6); 152 | 153 | s = [s substringWithRange:NSMakeRange(1, 4)]; 154 | 155 | 156 | return s; 157 | 158 | } 159 | 160 | - (void)setApplicationIDString:(NSString*)s { 161 | 162 | if ([s length] != 4) { 163 | NSLog(@"setApplicationIDString: string passed is not exactly 4 chars long. (was %ld)", [s length]); 164 | } 165 | 166 | [self setApplicationID:NSHFSTypeCodeFromFileType([NSString stringWithFormat:@"'%@'", s])]; 167 | } 168 | 169 | 170 | #endif 171 | 172 | #endif 173 | 174 | #pragma clang diagnostic push 175 | #pragma clang diagnostic ignored "-Wdeprecated-implementations" 176 | 177 | - (BOOL)columnExists:(NSString*)tableName columnName:(NSString*)columnName __attribute__ ((deprecated)) { 178 | return [self columnExists:columnName inTableWithName:tableName]; 179 | } 180 | 181 | #pragma clang diagnostic pop 182 | 183 | 184 | - (BOOL)validateSQL:(NSString*)sql error:(NSError**)error { 185 | sqlite3_stmt *pStmt = NULL; 186 | BOOL validationSucceeded = YES; 187 | 188 | int rc = sqlite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0); 189 | if (rc != SQLITE_OK) { 190 | validationSucceeded = NO; 191 | if (error) { 192 | *error = [NSError errorWithDomain:NSCocoaErrorDomain 193 | code:[self lastErrorCode] 194 | userInfo:[NSDictionary dictionaryWithObject:[self lastErrorMessage] 195 | forKey:NSLocalizedDescriptionKey]]; 196 | } 197 | } 198 | 199 | sqlite3_finalize(pStmt); 200 | 201 | return validationSucceeded; 202 | } 203 | 204 | @end 205 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabasePool.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** Pool of `` objects. 15 | 16 | ### See also 17 | 18 | - `` 19 | - `` 20 | 21 | @warning Before using `FMDatabasePool`, please consider using `` instead. 22 | 23 | If you really really really know what you're doing and `FMDatabasePool` is what 24 | you really really need (ie, you're using a read only database), OK you can use 25 | it. But just be careful not to deadlock! 26 | 27 | For an example on deadlocking, search for: 28 | `ONLY_USE_THE_POOL_IF_YOU_ARE_DOING_READS_OTHERWISE_YOULL_DEADLOCK_USE_FMDATABASEQUEUE_INSTEAD` 29 | in the main.m file. 30 | */ 31 | 32 | @interface FMDatabasePool : NSObject { 33 | NSString *_path; 34 | 35 | dispatch_queue_t _lockQueue; 36 | 37 | NSMutableArray *_databaseInPool; 38 | NSMutableArray *_databaseOutPool; 39 | 40 | __unsafe_unretained id _delegate; 41 | 42 | NSUInteger _maximumNumberOfDatabasesToCreate; 43 | int _openFlags; 44 | } 45 | 46 | @property (atomic, retain) NSString *path; 47 | @property (atomic, assign) id delegate; 48 | @property (atomic, assign) NSUInteger maximumNumberOfDatabasesToCreate; 49 | @property (atomic, readonly) int openFlags; 50 | 51 | ///--------------------- 52 | /// @name Initialization 53 | ///--------------------- 54 | 55 | /** Create pool using path. 56 | 57 | @param aPath The file path of the database. 58 | 59 | @return The `FMDatabasePool` object. `nil` on error. 60 | */ 61 | 62 | + (instancetype)databasePoolWithPath:(NSString*)aPath; 63 | 64 | /** Create pool using path and specified flags 65 | 66 | @param aPath The file path of the database. 67 | @param openFlags Flags passed to the openWithFlags method of the database 68 | 69 | @return The `FMDatabasePool` object. `nil` on error. 70 | */ 71 | 72 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags; 73 | 74 | /** Create pool using path. 75 | 76 | @param aPath The file path of the database. 77 | 78 | @return The `FMDatabasePool` object. `nil` on error. 79 | */ 80 | 81 | - (instancetype)initWithPath:(NSString*)aPath; 82 | 83 | /** Create pool using path and specified flags. 84 | 85 | @param aPath The file path of the database. 86 | @param openFlags Flags passed to the openWithFlags method of the database 87 | 88 | @return The `FMDatabasePool` object. `nil` on error. 89 | */ 90 | 91 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 92 | 93 | ///------------------------------------------------ 94 | /// @name Keeping track of checked in/out databases 95 | ///------------------------------------------------ 96 | 97 | /** Number of checked-in databases in pool 98 | 99 | @returns Number of databases 100 | */ 101 | 102 | - (NSUInteger)countOfCheckedInDatabases; 103 | 104 | /** Number of checked-out databases in pool 105 | 106 | @returns Number of databases 107 | */ 108 | 109 | - (NSUInteger)countOfCheckedOutDatabases; 110 | 111 | /** Total number of databases in pool 112 | 113 | @returns Number of databases 114 | */ 115 | 116 | - (NSUInteger)countOfOpenDatabases; 117 | 118 | /** Release all databases in pool */ 119 | 120 | - (void)releaseAllDatabases; 121 | 122 | ///------------------------------------------ 123 | /// @name Perform database operations in pool 124 | ///------------------------------------------ 125 | 126 | /** Synchronously perform database operations in pool. 127 | 128 | @param block The code to be run on the `FMDatabasePool` pool. 129 | */ 130 | 131 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 132 | 133 | /** Synchronously perform database operations in pool using transaction. 134 | 135 | @param block The code to be run on the `FMDatabasePool` pool. 136 | */ 137 | 138 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 139 | 140 | /** Synchronously perform database operations in pool using deferred transaction. 141 | 142 | @param block The code to be run on the `FMDatabasePool` pool. 143 | */ 144 | 145 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 146 | 147 | #if SQLITE_VERSION_NUMBER >= 3007000 148 | 149 | /** Synchronously perform database operations in pool using save point. 150 | 151 | @param block The code to be run on the `FMDatabasePool` pool. 152 | 153 | @warning You can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. If you need to nest, use `<[FMDatabase startSavePointWithName:error:]>` instead. 154 | */ 155 | 156 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 157 | #endif 158 | 159 | @end 160 | 161 | 162 | @interface NSObject (FMDatabasePoolDelegate) 163 | 164 | - (BOOL)databasePool:(FMDatabasePool*)pool shouldAddDatabaseToPool:(FMDatabase*)database; 165 | 166 | @end 167 | 168 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabasePool.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabasePool.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabasePool.h" 10 | #import "FMDatabase.h" 11 | 12 | @interface FMDatabasePool() 13 | 14 | - (void)pushDatabaseBackInPool:(FMDatabase*)db; 15 | - (FMDatabase*)db; 16 | 17 | @end 18 | 19 | 20 | @implementation FMDatabasePool 21 | @synthesize path=_path; 22 | @synthesize delegate=_delegate; 23 | @synthesize maximumNumberOfDatabasesToCreate=_maximumNumberOfDatabasesToCreate; 24 | @synthesize openFlags=_openFlags; 25 | 26 | 27 | + (instancetype)databasePoolWithPath:(NSString*)aPath { 28 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath]); 29 | } 30 | 31 | + (instancetype)databasePoolWithPath:(NSString*)aPath flags:(int)openFlags { 32 | return FMDBReturnAutoreleased([[self alloc] initWithPath:aPath flags:openFlags]); 33 | } 34 | 35 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 36 | 37 | self = [super init]; 38 | 39 | if (self != nil) { 40 | _path = [aPath copy]; 41 | _lockQueue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 42 | _databaseInPool = FMDBReturnRetained([NSMutableArray array]); 43 | _databaseOutPool = FMDBReturnRetained([NSMutableArray array]); 44 | _openFlags = openFlags; 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (instancetype)initWithPath:(NSString*)aPath 51 | { 52 | // default flags for sqlite3_open 53 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 54 | } 55 | 56 | - (instancetype)init { 57 | return [self initWithPath:nil]; 58 | } 59 | 60 | 61 | - (void)dealloc { 62 | 63 | _delegate = 0x00; 64 | FMDBRelease(_path); 65 | FMDBRelease(_databaseInPool); 66 | FMDBRelease(_databaseOutPool); 67 | 68 | if (_lockQueue) { 69 | FMDBDispatchQueueRelease(_lockQueue); 70 | _lockQueue = 0x00; 71 | } 72 | #if ! __has_feature(objc_arc) 73 | [super dealloc]; 74 | #endif 75 | } 76 | 77 | 78 | - (void)executeLocked:(void (^)(void))aBlock { 79 | dispatch_sync(_lockQueue, aBlock); 80 | } 81 | 82 | - (void)pushDatabaseBackInPool:(FMDatabase*)db { 83 | 84 | if (!db) { // db can be null if we set an upper bound on the # of databases to create. 85 | return; 86 | } 87 | 88 | [self executeLocked:^() { 89 | 90 | if ([_databaseInPool containsObject:db]) { 91 | [[NSException exceptionWithName:@"Database already in pool" reason:@"The FMDatabase being put back into the pool is already present in the pool" userInfo:nil] raise]; 92 | } 93 | 94 | [_databaseInPool addObject:db]; 95 | [_databaseOutPool removeObject:db]; 96 | 97 | }]; 98 | } 99 | 100 | - (FMDatabase*)db { 101 | 102 | __block FMDatabase *db; 103 | 104 | [self executeLocked:^() { 105 | db = [_databaseInPool lastObject]; 106 | 107 | if (db) { 108 | [_databaseOutPool addObject:db]; 109 | [_databaseInPool removeLastObject]; 110 | } 111 | else { 112 | 113 | if (_maximumNumberOfDatabasesToCreate) { 114 | NSUInteger currentCount = [_databaseOutPool count] + [_databaseInPool count]; 115 | 116 | if (currentCount >= _maximumNumberOfDatabasesToCreate) { 117 | NSLog(@"Maximum number of databases (%ld) has already been reached!", (long)currentCount); 118 | return; 119 | } 120 | } 121 | 122 | db = [FMDatabase databaseWithPath:_path]; 123 | } 124 | 125 | //This ensures that the db is opened before returning 126 | #if SQLITE_VERSION_NUMBER >= 3005000 127 | if ([db openWithFlags:_openFlags]) { 128 | #else 129 | if ([db open]) { 130 | #endif 131 | if ([_delegate respondsToSelector:@selector(databasePool:shouldAddDatabaseToPool:)] && ![_delegate databasePool:self shouldAddDatabaseToPool:db]) { 132 | [db close]; 133 | db = 0x00; 134 | } 135 | else { 136 | //It should not get added in the pool twice if lastObject was found 137 | if (![_databaseOutPool containsObject:db]) { 138 | [_databaseOutPool addObject:db]; 139 | } 140 | } 141 | } 142 | else { 143 | NSLog(@"Could not open up the database at path %@", _path); 144 | db = 0x00; 145 | } 146 | }]; 147 | 148 | return db; 149 | } 150 | 151 | - (NSUInteger)countOfCheckedInDatabases { 152 | 153 | __block NSUInteger count; 154 | 155 | [self executeLocked:^() { 156 | count = [_databaseInPool count]; 157 | }]; 158 | 159 | return count; 160 | } 161 | 162 | - (NSUInteger)countOfCheckedOutDatabases { 163 | 164 | __block NSUInteger count; 165 | 166 | [self executeLocked:^() { 167 | count = [_databaseOutPool count]; 168 | }]; 169 | 170 | return count; 171 | } 172 | 173 | - (NSUInteger)countOfOpenDatabases { 174 | __block NSUInteger count; 175 | 176 | [self executeLocked:^() { 177 | count = [_databaseOutPool count] + [_databaseInPool count]; 178 | }]; 179 | 180 | return count; 181 | } 182 | 183 | - (void)releaseAllDatabases { 184 | [self executeLocked:^() { 185 | [_databaseOutPool removeAllObjects]; 186 | [_databaseInPool removeAllObjects]; 187 | }]; 188 | } 189 | 190 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 191 | 192 | FMDatabase *db = [self db]; 193 | 194 | block(db); 195 | 196 | [self pushDatabaseBackInPool:db]; 197 | } 198 | 199 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 200 | 201 | BOOL shouldRollback = NO; 202 | 203 | FMDatabase *db = [self db]; 204 | 205 | if (useDeferred) { 206 | [db beginDeferredTransaction]; 207 | } 208 | else { 209 | [db beginTransaction]; 210 | } 211 | 212 | 213 | block(db, &shouldRollback); 214 | 215 | if (shouldRollback) { 216 | [db rollback]; 217 | } 218 | else { 219 | [db commit]; 220 | } 221 | 222 | [self pushDatabaseBackInPool:db]; 223 | } 224 | 225 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 226 | [self beginTransaction:YES withBlock:block]; 227 | } 228 | 229 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 230 | [self beginTransaction:NO withBlock:block]; 231 | } 232 | #if SQLITE_VERSION_NUMBER >= 3007000 233 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 234 | 235 | static unsigned long savePointIdx = 0; 236 | 237 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 238 | 239 | BOOL shouldRollback = NO; 240 | 241 | FMDatabase *db = [self db]; 242 | 243 | NSError *err = 0x00; 244 | 245 | if (![db startSavePointWithName:name error:&err]) { 246 | [self pushDatabaseBackInPool:db]; 247 | return err; 248 | } 249 | 250 | block(db, &shouldRollback); 251 | 252 | if (shouldRollback) { 253 | // We need to rollback and release this savepoint to remove it 254 | [db rollbackToSavePointWithName:name error:&err]; 255 | } 256 | [db releaseSavePointWithName:name error:&err]; 257 | 258 | [self pushDatabaseBackInPool:db]; 259 | 260 | return err; 261 | } 262 | #endif 263 | 264 | @end 265 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabaseQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.h 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "sqlite3.h" 11 | 12 | @class FMDatabase; 13 | 14 | /** To perform queries and updates on multiple threads, you'll want to use `FMDatabaseQueue`. 15 | 16 | Using a single instance of `` from multiple threads at once is a bad idea. It has always been OK to make a `` object *per thread*. Just don't share a single instance across threads, and definitely not across multiple threads at the same time. 17 | 18 | Instead, use `FMDatabaseQueue`. Here's how to use it: 19 | 20 | First, make your queue. 21 | 22 | FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath]; 23 | 24 | Then use it like so: 25 | 26 | [queue inDatabase:^(FMDatabase *db) { 27 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 28 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 29 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 30 | 31 | FMResultSet *rs = [db executeQuery:@"select * from foo"]; 32 | while ([rs next]) { 33 | //… 34 | } 35 | }]; 36 | 37 | An easy way to wrap things up in a transaction can be done like this: 38 | 39 | [queue inTransaction:^(FMDatabase *db, BOOL *rollback) { 40 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]]; 41 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]]; 42 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]]; 43 | 44 | if (whoopsSomethingWrongHappened) { 45 | *rollback = YES; 46 | return; 47 | } 48 | // etc… 49 | [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]]; 50 | }]; 51 | 52 | `FMDatabaseQueue` will run the blocks on a serialized queue (hence the name of the class). So if you call `FMDatabaseQueue`'s methods from multiple threads at the same time, they will be executed in the order they are received. This way queries and updates won't step on each other's toes, and every one is happy. 53 | 54 | ### See also 55 | 56 | - `` 57 | 58 | @warning Do not instantiate a single `` object and use it across multiple threads. Use `FMDatabaseQueue` instead. 59 | 60 | @warning The calls to `FMDatabaseQueue`'s methods are blocking. So even though you are passing along blocks, they will **not** be run on another thread. 61 | 62 | */ 63 | 64 | @interface FMDatabaseQueue : NSObject { 65 | NSString *_path; 66 | dispatch_queue_t _queue; 67 | FMDatabase *_db; 68 | int _openFlags; 69 | } 70 | 71 | @property (atomic, retain) NSString *path; 72 | @property (atomic, readonly) int openFlags; 73 | 74 | ///---------------------------------------------------- 75 | /// @name Initialization, opening, and closing of queue 76 | ///---------------------------------------------------- 77 | 78 | /** Create queue using path. 79 | 80 | @param aPath The file path of the database. 81 | 82 | @return The `FMDatabaseQueue` object. `nil` on error. 83 | */ 84 | 85 | + (instancetype)databaseQueueWithPath:(NSString*)aPath; 86 | 87 | /** Create queue using path and specified flags. 88 | 89 | @param aPath The file path of the database. 90 | @param openFlags Flags passed to the openWithFlags method of the database 91 | 92 | @return The `FMDatabaseQueue` object. `nil` on error. 93 | */ 94 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags; 95 | 96 | /** Create queue using path. 97 | 98 | @param aPath The file path of the database. 99 | 100 | @return The `FMDatabaseQueue` object. `nil` on error. 101 | */ 102 | 103 | - (instancetype)initWithPath:(NSString*)aPath; 104 | 105 | /** Create queue using path and specified flags. 106 | 107 | @param aPath The file path of the database. 108 | @param openFlags Flags passed to the openWithFlags method of the database 109 | 110 | @return The `FMDatabaseQueue` object. `nil` on error. 111 | */ 112 | 113 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags; 114 | 115 | /** Returns the Class of 'FMDatabase' subclass, that will be used to instantiate database object. 116 | 117 | Subclasses can override this method to return specified Class of 'FMDatabase' subclass. 118 | 119 | @return The Class of 'FMDatabase' subclass, that will be used to instantiate database object. 120 | */ 121 | 122 | + (Class)databaseClass; 123 | 124 | /** Close database used by queue. */ 125 | 126 | - (void)close; 127 | 128 | ///----------------------------------------------- 129 | /// @name Dispatching database operations to queue 130 | ///----------------------------------------------- 131 | 132 | /** Synchronously perform database operations on queue. 133 | 134 | @param block The code to be run on the queue of `FMDatabaseQueue` 135 | */ 136 | 137 | - (void)inDatabase:(void (^)(FMDatabase *db))block; 138 | 139 | /** Synchronously perform database operations on queue, using transactions. 140 | 141 | @param block The code to be run on the queue of `FMDatabaseQueue` 142 | */ 143 | 144 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 145 | 146 | /** Synchronously perform database operations on queue, using deferred transactions. 147 | 148 | @param block The code to be run on the queue of `FMDatabaseQueue` 149 | */ 150 | 151 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block; 152 | 153 | ///----------------------------------------------- 154 | /// @name Dispatching database operations to queue 155 | ///----------------------------------------------- 156 | 157 | /** Synchronously perform database operations using save point. 158 | 159 | @param block The code to be run on the queue of `FMDatabaseQueue` 160 | */ 161 | 162 | #if SQLITE_VERSION_NUMBER >= 3007000 163 | // NOTE: you can not nest these, since calling it will pull another database out of the pool and you'll get a deadlock. 164 | // If you need to nest, use FMDatabase's startSavePointWithName:error: instead. 165 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block; 166 | #endif 167 | 168 | @end 169 | 170 | -------------------------------------------------------------------------------- /AppTime/Lib/FMDB/FMDatabaseQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // FMDatabaseQueue.m 3 | // fmdb 4 | // 5 | // Created by August Mueller on 6/22/11. 6 | // Copyright 2011 Flying Meat Inc. All rights reserved. 7 | // 8 | 9 | #import "FMDatabaseQueue.h" 10 | #import "FMDatabase.h" 11 | 12 | /* 13 | 14 | Note: we call [self retain]; before using dispatch_sync, just incase 15 | FMDatabaseQueue is released on another thread and we're in the middle of doing 16 | something in dispatch_sync 17 | 18 | */ 19 | 20 | @implementation FMDatabaseQueue 21 | 22 | @synthesize path = _path; 23 | @synthesize openFlags = _openFlags; 24 | 25 | + (instancetype)databaseQueueWithPath:(NSString*)aPath { 26 | 27 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath]; 28 | 29 | FMDBAutorelease(q); 30 | 31 | return q; 32 | } 33 | 34 | + (instancetype)databaseQueueWithPath:(NSString*)aPath flags:(int)openFlags { 35 | 36 | FMDatabaseQueue *q = [[self alloc] initWithPath:aPath flags:openFlags]; 37 | 38 | FMDBAutorelease(q); 39 | 40 | return q; 41 | } 42 | 43 | + (Class)databaseClass { 44 | return [FMDatabase class]; 45 | } 46 | 47 | - (instancetype)initWithPath:(NSString*)aPath flags:(int)openFlags { 48 | 49 | self = [super init]; 50 | 51 | if (self != nil) { 52 | 53 | _db = [[[self class] databaseClass] databaseWithPath:aPath]; 54 | FMDBRetain(_db); 55 | 56 | #if SQLITE_VERSION_NUMBER >= 3005000 57 | if (![_db openWithFlags:openFlags]) { 58 | #else 59 | if (![_db open]) { 60 | #endif 61 | NSLog(@"Could not create database queue for path %@", aPath); 62 | FMDBRelease(self); 63 | return 0x00; 64 | } 65 | 66 | _path = FMDBReturnRetained(aPath); 67 | 68 | _queue = dispatch_queue_create([[NSString stringWithFormat:@"fmdb.%@", self] UTF8String], NULL); 69 | _openFlags = openFlags; 70 | } 71 | 72 | return self; 73 | } 74 | 75 | - (instancetype)initWithPath:(NSString*)aPath { 76 | 77 | // default flags for sqlite3_open 78 | return [self initWithPath:aPath flags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE]; 79 | } 80 | 81 | - (instancetype)init { 82 | return [self initWithPath:nil]; 83 | } 84 | 85 | 86 | - (void)dealloc { 87 | 88 | FMDBRelease(_db); 89 | FMDBRelease(_path); 90 | 91 | if (_queue) { 92 | FMDBDispatchQueueRelease(_queue); 93 | _queue = 0x00; 94 | } 95 | #if ! __has_feature(objc_arc) 96 | [super dealloc]; 97 | #endif 98 | } 99 | 100 | - (void)close { 101 | FMDBRetain(self); 102 | dispatch_sync(_queue, ^() { 103 | [_db close]; 104 | FMDBRelease(_db); 105 | _db = 0x00; 106 | }); 107 | FMDBRelease(self); 108 | } 109 | 110 | - (FMDatabase*)database { 111 | if (!_db) { 112 | _db = FMDBReturnRetained([FMDatabase databaseWithPath:_path]); 113 | 114 | #if SQLITE_VERSION_NUMBER >= 3005000 115 | if (![_db openWithFlags:_openFlags]) { 116 | #else 117 | if (![db open]) { 118 | #endif 119 | NSLog(@"FMDatabaseQueue could not reopen database for path %@", _path); 120 | FMDBRelease(_db); 121 | _db = 0x00; 122 | return 0x00; 123 | } 124 | } 125 | 126 | return _db; 127 | } 128 | 129 | - (void)inDatabase:(void (^)(FMDatabase *db))block { 130 | FMDBRetain(self); 131 | 132 | dispatch_sync(_queue, ^() { 133 | 134 | FMDatabase *db = [self database]; 135 | block(db); 136 | 137 | if ([db hasOpenResultSets]) { 138 | NSLog(@"Warning: there is at least one open result set around after performing [FMDatabaseQueue inDatabase:]"); 139 | 140 | #ifdef DEBUG 141 | NSSet *openSetCopy = FMDBReturnAutoreleased([[db valueForKey:@"_openResultSets"] copy]); 142 | for (NSValue *rsInWrappedInATastyValueMeal in openSetCopy) { 143 | FMResultSet *rs = (FMResultSet *)[rsInWrappedInATastyValueMeal pointerValue]; 144 | NSLog(@"query: '%@'", [rs query]); 145 | } 146 | #endif 147 | } 148 | }); 149 | 150 | FMDBRelease(self); 151 | } 152 | 153 | 154 | - (void)beginTransaction:(BOOL)useDeferred withBlock:(void (^)(FMDatabase *db, BOOL *rollback))block { 155 | FMDBRetain(self); 156 | dispatch_sync(_queue, ^() { 157 | 158 | BOOL shouldRollback = NO; 159 | 160 | if (useDeferred) { 161 | [[self database] beginDeferredTransaction]; 162 | } 163 | else { 164 | [[self database] beginTransaction]; 165 | } 166 | 167 | block([self database], &shouldRollback); 168 | 169 | if (shouldRollback) { 170 | [[self database] rollback]; 171 | } 172 | else { 173 | [[self database] commit]; 174 | } 175 | }); 176 | 177 | FMDBRelease(self); 178 | } 179 | 180 | - (void)inDeferredTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 181 | [self beginTransaction:YES withBlock:block]; 182 | } 183 | 184 | - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block { 185 | [self beginTransaction:NO withBlock:block]; 186 | } 187 | 188 | #if SQLITE_VERSION_NUMBER >= 3007000 189 | - (NSError*)inSavePoint:(void (^)(FMDatabase *db, BOOL *rollback))block { 190 | 191 | static unsigned long savePointIdx = 0; 192 | __block NSError *err = 0x00; 193 | FMDBRetain(self); 194 | dispatch_sync(_queue, ^() { 195 | 196 | NSString *name = [NSString stringWithFormat:@"savePoint%ld", savePointIdx++]; 197 | 198 | BOOL shouldRollback = NO; 199 | 200 | if ([[self database] startSavePointWithName:name error:&err]) { 201 | 202 | block([self database], &shouldRollback); 203 | 204 | if (shouldRollback) { 205 | // We need to rollback and release this savepoint to remove it 206 | [[self database] rollbackToSavePointWithName:name error:&err]; 207 | } 208 | [[self database] releaseSavePointWithName:name error:&err]; 209 | 210 | } 211 | }); 212 | FMDBRelease(self); 213 | return err; 214 | } 215 | #endif 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMDrawerBarButtonItem.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | /** 24 | `MMDrawerBarButtonItem` provides convenience methods to create `UIBarButtonItems` with a default hamburger-menu asset. 25 | */ 26 | 27 | @interface MMDrawerBarButtonItem : UIBarButtonItem 28 | 29 | ///--------------------------------------- 30 | /// @name Initializing a `MMDrawerBarButtonItem` 31 | ///--------------------------------------- 32 | 33 | /** 34 | Creates and initializes an `MMDrawerBarButtonItem` without a border. 35 | 36 | @param target The target to forward the `action` to when the button is pressed. 37 | @param action The action to call when the button is pressed. 38 | 39 | @return The newly-initialized bar button item. 40 | */ 41 | -(id)initWithTarget:(id)target action:(SEL)action; 42 | 43 | /** 44 | Returns the current color of the menu button for the state requested. 45 | 46 | @param state The UIControl state that the color is being requested for. 47 | 48 | @return The menu button color for the requested state. 49 | */ 50 | -(UIColor *)menuButtonColorForState:(UIControlState)state; 51 | 52 | /** 53 | Sets the color of the menu button for the specified state. For this control, only set colors for `UIControlStateNormal` and `UIControlStateHighlighted`. 54 | 55 | @param color The color to set. 56 | @param state The state to set the color for. 57 | */ 58 | -(void)setMenuButtonColor:(UIColor *)color forState:(UIControlState)state; 59 | 60 | /** 61 | Returns the current color of the shadow for the state requested. 62 | 63 | @param state The UIControl state that the color is being requested for. 64 | 65 | @return The menu button color for the requested state. 66 | */ 67 | -(UIColor *)shadowColorForState:(UIControlState)state; 68 | 69 | /** 70 | Sets the color of the shadow for the specified state. For this control, only set colors for `UIControlStateNormal` and `UIControlStateHighlighted`. 71 | 72 | @param color The color to set. 73 | @param state The state to set the color for. 74 | */ 75 | -(void)setShadowColor:(UIColor *)color forState:(UIControlState)state; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMDrawerVisualState.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import 23 | #import "MMDrawerController.h" 24 | 25 | /** 26 | `MMDrawerVisualState` provides prebuilt visual state update blocks that can be used in the callback block of `MMDrawerController` for drawer animation. 27 | */ 28 | 29 | @interface MMDrawerVisualState : NSObject 30 | 31 | /** 32 | Creates a slide and scale visual state block that gives an experience similar to Mailbox.app. It scales from 90% to 100%, and translates 50 pixels in the x direction. In addition, it also sets alpha from 0.0 to 1.0. 33 | 34 | @return The visual state block. 35 | */ 36 | +(MMDrawerControllerDrawerVisualStateBlock)slideAndScaleVisualStateBlock; 37 | 38 | /** 39 | Creates a slide visual state block that gives the user an experience that slides at the same speed of the center view controller during animation. This is equal to calling `parallaxVisualStateBlockWithParallaxFactor:` with a parallax factor of 1.0. 40 | 41 | @return The visual state block. 42 | */ 43 | +(MMDrawerControllerDrawerVisualStateBlock)slideVisualStateBlock; 44 | 45 | /** 46 | Creates a swinging door visual state block that gives the user an experience that animates the drawer in along the hinge. 47 | 48 | @return The visual state block. 49 | */ 50 | +(MMDrawerControllerDrawerVisualStateBlock)swingingDoorVisualStateBlock; 51 | 52 | /** 53 | Creates a parallax experience that slides the side drawer view controller at a different rate than the center view controller during animation. For every parallaxFactor of points moved by the center view controller, the side drawer view controller will move 1 point. Passing in 1.0 is the equivalent of a applying a sliding animation, while passing in MAX_FLOAT is the equivalent of having no animation at all. 54 | 55 | @param parallaxFactor The amount of parallax applied to the side drawer conroller. This value must be greater than 1.0. The closer the value is to 1.0, the faster the side drawer view controller will be parallaxing. 56 | 57 | @return The visual state block. 58 | */ 59 | +(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMDrawerVisualState.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMDrawerVisualState.h" 23 | #import 24 | 25 | @implementation MMDrawerVisualState 26 | +(MMDrawerControllerDrawerVisualStateBlock)slideAndScaleVisualStateBlock{ 27 | MMDrawerControllerDrawerVisualStateBlock visualStateBlock = 28 | ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){ 29 | CGFloat minScale = .90; 30 | CGFloat scale = minScale + (percentVisible*(1.0-minScale)); 31 | CATransform3D scaleTransform = CATransform3DMakeScale(scale, scale, scale); 32 | 33 | CGFloat maxDistance = 50; 34 | CGFloat distance = maxDistance * percentVisible; 35 | CATransform3D translateTransform; 36 | UIViewController * sideDrawerViewController; 37 | if(drawerSide == MMDrawerSideLeft) { 38 | sideDrawerViewController = drawerController.leftDrawerViewController; 39 | translateTransform = CATransform3DMakeTranslation((maxDistance-distance), 0.0, 0.0); 40 | } 41 | else if(drawerSide == MMDrawerSideRight){ 42 | sideDrawerViewController = drawerController.rightDrawerViewController; 43 | translateTransform = CATransform3DMakeTranslation(-(maxDistance-distance), 0.0, 0.0); 44 | } 45 | 46 | [sideDrawerViewController.view.layer setTransform:CATransform3DConcat(scaleTransform, translateTransform)]; 47 | [sideDrawerViewController.view setAlpha:percentVisible]; 48 | }; 49 | return visualStateBlock; 50 | } 51 | 52 | +(MMDrawerControllerDrawerVisualStateBlock)slideVisualStateBlock{ 53 | return [self parallaxVisualStateBlockWithParallaxFactor:1.0]; 54 | } 55 | 56 | 57 | +(MMDrawerControllerDrawerVisualStateBlock)swingingDoorVisualStateBlock{ 58 | MMDrawerControllerDrawerVisualStateBlock visualStateBlock = 59 | ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){ 60 | UIViewController * sideDrawerViewController; 61 | CGPoint anchorPoint = CGPointMake(0.5, 0.5); 62 | CGFloat maxDrawerWidth = 0.0; 63 | CGFloat xOffset; 64 | CGFloat angle = 0.0; 65 | 66 | if(drawerSide==MMDrawerSideLeft){ 67 | 68 | sideDrawerViewController = drawerController.leftDrawerViewController; 69 | anchorPoint = CGPointMake(1.0, .5); 70 | maxDrawerWidth = MAX(drawerController.maximumLeftDrawerWidth,drawerController.visibleLeftDrawerWidth); 71 | xOffset = -(maxDrawerWidth/2.0) + (maxDrawerWidth)*percentVisible; 72 | angle = -M_PI_2+(percentVisible*M_PI_2); 73 | } 74 | else { 75 | sideDrawerViewController = drawerController.rightDrawerViewController; 76 | anchorPoint = CGPointMake(0.0, .5); 77 | maxDrawerWidth = MAX(drawerController.maximumRightDrawerWidth,drawerController.visibleRightDrawerWidth); 78 | xOffset = (maxDrawerWidth/2.0) - (maxDrawerWidth)*percentVisible; 79 | angle = M_PI_2-(percentVisible*M_PI_2); 80 | } 81 | 82 | [sideDrawerViewController.view.layer setAnchorPoint:anchorPoint]; 83 | [sideDrawerViewController.view.layer setShouldRasterize:YES]; 84 | [sideDrawerViewController.view.layer setRasterizationScale:[[UIScreen mainScreen] scale]]; 85 | 86 | CATransform3D swingingDoorTransform = CATransform3DIdentity; 87 | if (percentVisible <= 1.f) { 88 | 89 | CATransform3D identity = CATransform3DIdentity; 90 | identity.m34 = -1.0/1000.0; 91 | CATransform3D rotateTransform = CATransform3DRotate(identity, angle, 0.0, 1.0, 0.0); 92 | 93 | CATransform3D translateTransform = CATransform3DMakeTranslation(xOffset, 0.0, 0.0); 94 | 95 | CATransform3D concatTransform = CATransform3DConcat(rotateTransform, translateTransform); 96 | 97 | swingingDoorTransform = concatTransform; 98 | } 99 | else{ 100 | CATransform3D overshootTransform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); 101 | 102 | NSInteger scalingModifier = 1.f; 103 | if (drawerSide == MMDrawerSideRight) { 104 | scalingModifier = -1.f; 105 | } 106 | 107 | overshootTransform = CATransform3DTranslate(overshootTransform, scalingModifier*maxDrawerWidth/2, 0.f, 0.f); 108 | swingingDoorTransform = overshootTransform; 109 | } 110 | 111 | [sideDrawerViewController.view.layer setTransform:swingingDoorTransform]; 112 | }; 113 | return visualStateBlock; 114 | } 115 | 116 | +(MMDrawerControllerDrawerVisualStateBlock)parallaxVisualStateBlockWithParallaxFactor:(CGFloat)parallaxFactor{ 117 | MMDrawerControllerDrawerVisualStateBlock visualStateBlock = 118 | ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){ 119 | NSParameterAssert(parallaxFactor >= 1.0); 120 | CATransform3D transform; 121 | UIViewController * sideDrawerViewController; 122 | if(drawerSide == MMDrawerSideLeft) { 123 | sideDrawerViewController = drawerController.leftDrawerViewController; 124 | CGFloat distance = MAX(drawerController.maximumLeftDrawerWidth,drawerController.visibleLeftDrawerWidth); 125 | if (percentVisible <= 1.f) { 126 | transform = CATransform3DMakeTranslation((-distance)/parallaxFactor+(distance*percentVisible/parallaxFactor), 0.0, 0.0); 127 | } 128 | else{ 129 | transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); 130 | transform = CATransform3DTranslate(transform, drawerController.maximumLeftDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); 131 | } 132 | } 133 | else if(drawerSide == MMDrawerSideRight){ 134 | sideDrawerViewController = drawerController.rightDrawerViewController; 135 | CGFloat distance = MAX(drawerController.maximumRightDrawerWidth,drawerController.visibleRightDrawerWidth); 136 | if(percentVisible <= 1.f){ 137 | transform = CATransform3DMakeTranslation((distance)/parallaxFactor-(distance*percentVisible)/parallaxFactor, 0.0, 0.0); 138 | } 139 | else{ 140 | transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); 141 | transform = CATransform3DTranslate(transform, -drawerController.maximumRightDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); 142 | } 143 | } 144 | 145 | [sideDrawerViewController.view.layer setTransform:transform]; 146 | }; 147 | return visualStateBlock; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleDrawerVisualStateManager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import 23 | #import "MMDrawerVisualState.h" 24 | 25 | typedef NS_ENUM(NSInteger, MMDrawerAnimationType){ 26 | MMDrawerAnimationTypeNone, 27 | MMDrawerAnimationTypeSlide, 28 | MMDrawerAnimationTypeSlideAndScale, 29 | MMDrawerAnimationTypeSwingingDoor, 30 | MMDrawerAnimationTypeParallax, 31 | }; 32 | 33 | @interface MMExampleDrawerVisualStateManager : NSObject 34 | 35 | @property (nonatomic,assign) MMDrawerAnimationType leftDrawerAnimationType; 36 | @property (nonatomic,assign) MMDrawerAnimationType rightDrawerAnimationType; 37 | 38 | + (MMExampleDrawerVisualStateManager *)sharedManager; 39 | 40 | -(MMDrawerControllerDrawerVisualStateBlock)drawerVisualStateBlockForDrawerSide:(MMDrawerSide)drawerSide; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleDrawerVisualStateManager.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMExampleDrawerVisualStateManager.h" 23 | 24 | #import 25 | 26 | @implementation MMExampleDrawerVisualStateManager 27 | 28 | + (MMExampleDrawerVisualStateManager *)sharedManager { 29 | static MMExampleDrawerVisualStateManager *_sharedManager = nil; 30 | static dispatch_once_t onceToken; 31 | dispatch_once(&onceToken, ^{ 32 | _sharedManager = [[MMExampleDrawerVisualStateManager alloc] init]; 33 | [_sharedManager setLeftDrawerAnimationType:MMDrawerAnimationTypeParallax]; 34 | [_sharedManager setRightDrawerAnimationType:MMDrawerAnimationTypeParallax]; 35 | }); 36 | 37 | return _sharedManager; 38 | } 39 | 40 | -(MMDrawerControllerDrawerVisualStateBlock)drawerVisualStateBlockForDrawerSide:(MMDrawerSide)drawerSide{ 41 | MMDrawerAnimationType animationType; 42 | if(drawerSide == MMDrawerSideLeft){ 43 | animationType = self.leftDrawerAnimationType; 44 | } 45 | else { 46 | animationType = self.rightDrawerAnimationType; 47 | } 48 | 49 | MMDrawerControllerDrawerVisualStateBlock visualStateBlock = nil; 50 | switch (animationType) { 51 | case MMDrawerAnimationTypeSlide: 52 | visualStateBlock = [MMDrawerVisualState slideVisualStateBlock]; 53 | break; 54 | case MMDrawerAnimationTypeSlideAndScale: 55 | visualStateBlock = [MMDrawerVisualState slideAndScaleVisualStateBlock]; 56 | break; 57 | case MMDrawerAnimationTypeParallax: 58 | visualStateBlock = [MMDrawerVisualState parallaxVisualStateBlockWithParallaxFactor:2.0]; 59 | break; 60 | case MMDrawerAnimationTypeSwingingDoor: 61 | visualStateBlock = [MMDrawerVisualState swingingDoorVisualStateBlock]; 62 | break; 63 | default: 64 | visualStateBlock = ^(MMDrawerController * drawerController, MMDrawerSide drawerSide, CGFloat percentVisible){ 65 | 66 | UIViewController * sideDrawerViewController; 67 | CATransform3D transform; 68 | CGFloat maxDrawerWidth; 69 | 70 | if(drawerSide == MMDrawerSideLeft){ 71 | sideDrawerViewController = drawerController.leftDrawerViewController; 72 | maxDrawerWidth = drawerController.maximumLeftDrawerWidth; 73 | } 74 | else if(drawerSide == MMDrawerSideRight){ 75 | sideDrawerViewController = drawerController.rightDrawerViewController; 76 | maxDrawerWidth = drawerController.maximumRightDrawerWidth; 77 | } 78 | 79 | if(percentVisible > 1.0){ 80 | transform = CATransform3DMakeScale(percentVisible, 1.f, 1.f); 81 | 82 | if(drawerSide == MMDrawerSideLeft){ 83 | transform = CATransform3DTranslate(transform, maxDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); 84 | }else if(drawerSide == MMDrawerSideRight){ 85 | transform = CATransform3DTranslate(transform, -maxDrawerWidth*(percentVisible-1.f)/2, 0.f, 0.f); 86 | } 87 | } 88 | else { 89 | transform = CATransform3DIdentity; 90 | } 91 | [sideDrawerViewController.view.layer setTransform:transform]; 92 | }; 93 | break; 94 | } 95 | return visualStateBlock; 96 | } 97 | @end 98 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleLeftSideDrawerViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMExampleSideDrawerViewController.h" 23 | 24 | @interface MMExampleLeftSideDrawerViewController : MMExampleSideDrawerViewController 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleLeftSideDrawerViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMExampleLeftSideDrawerViewController.h" 23 | #import "MMTableViewCell.h" 24 | 25 | @interface MMExampleLeftSideDrawerViewController () 26 | 27 | @end 28 | 29 | @implementation MMExampleLeftSideDrawerViewController 30 | 31 | -(void)viewWillAppear:(BOOL)animated{ 32 | [super viewWillAppear:animated]; 33 | NSLog(@"Left will appear"); 34 | } 35 | 36 | -(void)viewDidAppear:(BOOL)animated{ 37 | [super viewDidAppear:animated]; 38 | NSLog(@"Left did appear"); 39 | } 40 | 41 | -(void)viewWillDisappear:(BOOL)animated{ 42 | [super viewWillDisappear:animated]; 43 | NSLog(@"Left will disappear"); 44 | } 45 | 46 | -(void)viewDidDisappear:(BOOL)animated{ 47 | [super viewDidDisappear:animated]; 48 | NSLog(@"Left did disappear"); 49 | } 50 | 51 | 52 | -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 53 | 54 | if(section == MMDrawerSectionDrawerWidth) 55 | return @"Left Drawer Width"; 56 | else 57 | return [super tableView:tableView titleForHeaderInSection:section]; 58 | } 59 | 60 | -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 61 | UITableViewCell * cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 62 | if(indexPath.section == MMDrawerSectionDrawerWidth){ 63 | 64 | CGFloat width = [self.drawerWidths[indexPath.row] intValue]; 65 | CGFloat drawerWidth = self.mm_drawerController.maximumLeftDrawerWidth; 66 | if(drawerWidth == width){ 67 | [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 68 | } 69 | else{ 70 | [cell setAccessoryType:UITableViewCellAccessoryNone]; 71 | } 72 | [cell.textLabel setText:[NSString stringWithFormat:@"Width %d",[self.drawerWidths[indexPath.row] intValue]]]; 73 | } 74 | return cell; 75 | } 76 | 77 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 78 | if(indexPath.section == MMDrawerSectionDrawerWidth){ 79 | [self.mm_drawerController 80 | setMaximumLeftDrawerWidth:[self.drawerWidths[indexPath.row] floatValue] 81 | animated:YES 82 | completion:^(BOOL finished) { 83 | [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone]; 84 | [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; 85 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 86 | }]; 87 | 88 | } 89 | else { 90 | [super tableView:tableView didSelectRowAtIndexPath:indexPath]; 91 | } 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleRightSideDrawerViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "MMExampleSideDrawerViewController.h" 22 | 23 | @interface MMExampleRightSideDrawerViewController : MMExampleSideDrawerViewController 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleRightSideDrawerViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMExampleRightSideDrawerViewController.h" 23 | 24 | @interface MMExampleRightSideDrawerViewController () 25 | 26 | @end 27 | 28 | @implementation MMExampleRightSideDrawerViewController 29 | 30 | -(void)viewWillAppear:(BOOL)animated{ 31 | [super viewWillAppear:animated]; 32 | NSLog(@"Right will appear"); 33 | } 34 | 35 | -(void)viewDidAppear:(BOOL)animated{ 36 | [super viewDidAppear:animated]; 37 | NSLog(@"Right did appear"); 38 | } 39 | 40 | -(void)viewWillDisappear:(BOOL)animated{ 41 | [super viewWillDisappear:animated]; 42 | NSLog(@"Right will disappear"); 43 | } 44 | 45 | -(void)viewDidDisappear:(BOOL)animated{ 46 | [super viewDidDisappear:animated]; 47 | NSLog(@"Right did disappear"); 48 | } 49 | 50 | -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 51 | 52 | if(section == MMDrawerSectionDrawerWidth) 53 | return @"类别"; 54 | else 55 | return [super tableView:tableView titleForHeaderInSection:section]; 56 | } 57 | 58 | -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 59 | UITableViewCell * cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 60 | if(indexPath.section == MMDrawerSectionDrawerWidth){ 61 | CGFloat width = [self.drawerWidths[indexPath.row] intValue]; 62 | CGFloat drawerWidth = self.mm_drawerController.maximumRightDrawerWidth; 63 | if(drawerWidth == width) 64 | [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 65 | else 66 | [cell setAccessoryType:UITableViewCellAccessoryNone]; 67 | [cell.textLabel setText:[NSString stringWithFormat:@"Width %d",[self.drawerWidths[indexPath.row] intValue]]]; 68 | } 69 | 70 | return cell; 71 | } 72 | 73 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 74 | if(indexPath.section == MMDrawerSectionDrawerWidth){ 75 | [self.mm_drawerController 76 | setMaximumRightDrawerWidth:[self.drawerWidths[indexPath.row] floatValue] 77 | animated:YES 78 | completion:^(BOOL finished) { 79 | [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationNone]; 80 | [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; 81 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 82 | }]; 83 | } 84 | else { 85 | [super tableView:tableView didSelectRowAtIndexPath:indexPath]; 86 | } 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMExampleSideDrawerViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import 23 | #import "UIViewController+MMDrawerController.h" 24 | 25 | typedef NS_ENUM(NSInteger, MMDrawerSection){ 26 | MMDrawerSectionViewSelection, 27 | MMDrawerSectionDrawerWidth, 28 | MMDrawerSectionShadowToggle, 29 | MMDrawerSectionOpenDrawerGestures, 30 | MMDrawerSectionCloseDrawerGestures, 31 | MMDrawerSectionCenterHiddenInteraction, 32 | MMDrawerSectionStretchDrawer, 33 | }; 34 | 35 | @interface MMExampleSideDrawerViewController : UIViewController 36 | @property (nonatomic, strong) UITableView * tableView; 37 | @property (nonatomic,strong) NSArray * drawerWidths; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMSideDrawerSectionHeaderView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import 23 | 24 | @interface MMSideDrawerSectionHeaderView : UIView 25 | 26 | @property (nonatomic, copy) NSString * title; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMSideDrawerSectionHeaderView.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "MMSideDrawerSectionHeaderView.h" 22 | #import 23 | 24 | @interface MMSideDrawerSectionHeaderView () 25 | @property (nonatomic, strong) UILabel * label; 26 | @end 27 | 28 | @implementation MMSideDrawerSectionHeaderView 29 | 30 | - (id)initWithFrame:(CGRect)frame 31 | { 32 | self = [super initWithFrame:frame]; 33 | if (self) { 34 | // Initialization code 35 | 36 | [self setBackgroundColor:[UIColor colorWithRed:77.0/255.0 37 | green:79.0/255.0 38 | blue:80.0/255.0 39 | alpha:1.0]]; 40 | 41 | _label = [[UILabel alloc] initWithFrame:CGRectInset(self.bounds, 10.0, 2.0)]; 42 | [self.label setFont:[UIFont boldSystemFontOfSize:16.0]]; 43 | [self.label setBackgroundColor:[UIColor clearColor]]; 44 | [self.label setTextColor:[UIColor colorWithRed:203.0/255.0 45 | green:206.0/255.0 46 | blue:209.0/255.0 47 | alpha:1.0]]; 48 | [self.label setShadowOffset:CGSizeMake(0, 1)]; 49 | [self.label setShadowColor:[[UIColor blackColor] colorWithAlphaComponent:.5]]; 50 | [self.label setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; 51 | [self addSubview:self.label]; 52 | [self setClipsToBounds:NO]; 53 | } 54 | return self; 55 | } 56 | 57 | -(void)setTitle:(NSString *)title{ 58 | _title = title; 59 | [self.label setText:self.title]; 60 | } 61 | 62 | -(void)drawRect:(CGRect)rect{ 63 | //// General Declarations 64 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 65 | CGContextRef context = UIGraphicsGetCurrentContext(); 66 | 67 | //// Color Declarations 68 | UIColor* color = [UIColor colorWithRed: 0.373 green: 0.388 blue: 0.404 alpha: 1]; 69 | UIColor* color2 = [UIColor colorWithRed: 0.216 green: 0.231 blue: 0.243 alpha: 1]; 70 | UIColor* color3 = [UIColor colorWithRed: 0.451 green: 0.463 blue: 0.475 alpha: 1]; 71 | UIColor* color4 = [UIColor colorWithRed: 0.184 green: 0.2 blue: 0.212 alpha: 1]; 72 | UIColor* fillColor2 = [UIColor colorWithRed: 0.373 green: 0.388 blue: 0.404 alpha: 0]; 73 | 74 | //// Gradient Declarations 75 | NSArray* gradient2Colors = [NSArray arrayWithObjects: 76 | (id)color.CGColor, 77 | (id)fillColor2.CGColor, nil]; 78 | CGFloat gradient2Locations[] = {0, 1}; 79 | CGGradientRef gradient2 = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradient2Colors, gradient2Locations); 80 | 81 | //// Frames 82 | CGRect frame = CGRectMake(0, -1, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)+1); 83 | 84 | 85 | //// Fill Drawing 86 | CGRect fillRect = CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame), CGRectGetWidth(frame), CGRectGetHeight(frame) - 1); 87 | UIBezierPath* fillPath = [UIBezierPath bezierPathWithRect: fillRect]; 88 | CGContextSaveGState(context); 89 | [fillPath addClip]; 90 | CGContextDrawLinearGradient(context, gradient2, 91 | CGPointMake(CGRectGetMidX(fillRect), CGRectGetMinY(fillRect)), 92 | CGPointMake(CGRectGetMidX(fillRect), CGRectGetMaxY(fillRect)), 93 | 0); 94 | CGContextRestoreGState(context); 95 | 96 | 97 | //// TopStroke Drawing 98 | UIBezierPath* topStrokePath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame), CGRectGetWidth(frame), 1)]; 99 | [color4 setFill]; 100 | [topStrokePath fill]; 101 | 102 | 103 | //// Highlight Drawing 104 | UIBezierPath* highlightPath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + 1, CGRectGetWidth(frame), 1)]; 105 | [color3 setFill]; 106 | [highlightPath fill]; 107 | 108 | 109 | //// BottomStroke Drawing 110 | UIBezierPath* bottomStrokePath = [UIBezierPath bezierPathWithRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame) + CGRectGetHeight(frame) - 1, CGRectGetWidth(frame), 1)]; 111 | [color2 setFill]; 112 | [bottomStrokePath fill]; 113 | 114 | 115 | //// Cleanup 116 | CGGradientRelease(gradient2); 117 | CGColorSpaceRelease(colorSpace); 118 | 119 | 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMSideDrawerTableViewCell.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMTableViewCell.h" 23 | 24 | @interface MMSideDrawerTableViewCell : MMTableViewCell 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMSideDrawerTableViewCell.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "MMSideDrawerTableViewCell.h" 23 | 24 | @implementation MMSideDrawerTableViewCell 25 | 26 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 27 | { 28 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 29 | if (self) { 30 | [self setAccessoryCheckmarkColor:[UIColor whiteColor]]; 31 | 32 | UIView * backgroundView = [[UIView alloc] initWithFrame:self.bounds]; 33 | [backgroundView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth]; 34 | [backgroundView setBackgroundColor:[UIColor colorWithRed:77.0/255.0 35 | green:79.0/255.0 36 | blue:80.0/255.0 37 | alpha:1.0]]; 38 | [self setBackgroundView:backgroundView]; 39 | 40 | [self.textLabel setBackgroundColor:[UIColor clearColor]]; 41 | [self.textLabel setTextColor:[UIColor 42 | colorWithRed:230.0/255.0 43 | green:236.0/255.0 44 | blue:242.0/255.0 45 | alpha:1.0]]; 46 | [self.textLabel setShadowColor:[[UIColor blackColor] colorWithAlphaComponent:.5]]; 47 | [self.textLabel setShadowOffset:CGSizeMake(0, 1)]; 48 | [self.textLabel setFont:[UIFont boldSystemFontOfSize:16.0]]; 49 | } 50 | return self; 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/MMTableViewCell.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import 23 | 24 | @interface MMTableViewCell : UITableViewCell 25 | 26 | @property (nonatomic, strong) UIColor * accessoryCheckmarkColor; 27 | @property (nonatomic, strong) UIColor * disclosureIndicatorColor; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/UIViewController+MMDrawerController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | #import "MMDrawerController.h" 24 | 25 | /** 26 | A helper category on `UIViewController` that exposes the parent drawer controller, the visible side drawer frame, and a `mm_drawerWillAppear` method that is called when the drawer is about to appear. 27 | */ 28 | 29 | @interface UIViewController (MMDrawerController) 30 | 31 | ///--------------------------------------- 32 | /// @name Accessing Drawer View Controller Properties 33 | ///--------------------------------------- 34 | 35 | /** 36 | The `MMDrawerController` that the view controller is contained within. If the view controller is not contained within a `MMDrawerController`, this property is nil. Note that if the view controller is contained within a `UINavigationController`, that navigation controller is contained within a `MMDrawerController`, this property will return a refernce to the `MMDrawerController`, despite the fact that it is not the direct parent of the view controller. 37 | */ 38 | @property(nonatomic, strong, readonly) MMDrawerController *mm_drawerController; 39 | 40 | /** 41 | The visible rect of the side drawer view controller in the drawer controller coordinate space. If the view controller is not a drawer in a `MMDrawerController`, then this property returns `CGRectNull` 42 | */ 43 | @property(nonatomic, assign, readonly) CGRect mm_visibleDrawerFrame; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /AppTime/Lib/MMDrawerController/UIViewController+MMDrawerController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Mutual Mobile (http://mutualmobile.com/) 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | 22 | #import "UIViewController+MMDrawerController.h" 23 | 24 | @implementation UIViewController (MMDrawerController) 25 | 26 | 27 | -(MMDrawerController*)mm_drawerController{ 28 | if([self.parentViewController isKindOfClass:[MMDrawerController class]]){ 29 | return (MMDrawerController*)self.parentViewController; 30 | } 31 | else if([self.parentViewController isKindOfClass:[UINavigationController class]] && 32 | [self.parentViewController.parentViewController isKindOfClass:[MMDrawerController class]]){ 33 | return (MMDrawerController*)[self.parentViewController parentViewController]; 34 | } 35 | else{ 36 | return nil; 37 | } 38 | } 39 | 40 | -(CGRect)mm_visibleDrawerFrame{ 41 | if([self isEqual:self.mm_drawerController.leftDrawerViewController] || 42 | [self.navigationController isEqual:self.mm_drawerController.leftDrawerViewController]){ 43 | CGRect rect = self.mm_drawerController.view.bounds; 44 | rect.size.width = self.mm_drawerController.maximumLeftDrawerWidth; 45 | return rect; 46 | 47 | } 48 | else if([self isEqual:self.mm_drawerController.rightDrawerViewController] || 49 | [self.navigationController isEqual:self.mm_drawerController.rightDrawerViewController]){ 50 | CGRect rect = self.mm_drawerController.view.bounds; 51 | rect.size.width = self.mm_drawerController.maximumRightDrawerWidth; 52 | rect.origin.x = CGRectGetWidth(self.mm_drawerController.view.bounds)-rect.size.width; 53 | return rect; 54 | } 55 | else { 56 | return CGRectNull; 57 | } 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /AppTime/Lib/NSDate+Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Helper.h 3 | // 4 | // Created by Billy Gray on 2/26/09. 5 | // Copyright (c) 2009, 2010, ZETETIC LLC 6 | // All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // * Neither the name of the ZETETIC LLC nor the 16 | // names of its contributors may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY 20 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY 23 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | #import 32 | 33 | @interface NSDate (Helper) 34 | 35 | - (NSUInteger)daysAgo; 36 | - (NSInteger)secondAgo; 37 | - (NSInteger)secondfrom:(NSDate *)srcDate; 38 | - (NSInteger)minuteCompare:(NSDate *)date; 39 | - (NSInteger)hourCompare:(NSDate *)date; 40 | - (NSInteger)dayCompare:(NSDate *)date; 41 | - (NSInteger)dayFCompare:(NSDate *)date; 42 | - (NSUInteger)daysAgoAgainstMidnight; 43 | - (NSString *)stringDaysAgo; 44 | - (NSString *)stringDaysAgoAgainstMidnight:(BOOL)flag; 45 | - (NSUInteger)weekday; 46 | 47 | + (NSDate *)dateFromString:(NSString *)string; 48 | + (NSDate *)dateFromString:(NSString *)string withFormat:(NSString *)format; 49 | + (NSString *)stringFromDate:(NSDate *)date withFormat:(NSString *)string; 50 | + (NSString *)stringFromDate:(NSDate *)date; 51 | + (NSString *)stringForDisplayFromDate:(NSDate *)date; 52 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed; 53 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed alwaysDisplayTime:(BOOL)displayTime; 54 | 55 | - (NSString *)string; 56 | - (NSString *)stringWithFormat:(NSString *)format; 57 | - (NSString *)stringWithDateStyle:(NSDateFormatterStyle)dateStyle timeStyle:(NSDateFormatterStyle)timeStyle; 58 | 59 | - (NSDate *)beginningOfWeek; 60 | - (NSDate *)beginningOfDay; 61 | - (NSDate *)endOfWeek; 62 | 63 | + (NSString *)dateFormatString; 64 | + (NSString *)timeFormatString; 65 | + (NSString *)timestampFormatString; 66 | + (NSString *)dbFormatString; 67 | + (NSString *)dateFormatString2 ; 68 | +(NSDate*)dateBeforeDate:(int)n; 69 | +(int)getWeekDay; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /AppTime/Res/MMPSilence.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime/Res/MMPSilence.wav -------------------------------------------------------------------------------- /AppTime/Res/desktop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime/Res/desktop@2x.png -------------------------------------------------------------------------------- /AppTime/Res/icon114@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime/Res/icon114@2x.png -------------------------------------------------------------------------------- /AppTime/Res/icon120@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime/Res/icon120@2x.png -------------------------------------------------------------------------------- /AppTime/Res/mute.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gugupluto/iOSAppTime/7d8afaaf52315686b0e0cd26d934f8d765f0af47/AppTime/Res/mute.mp3 -------------------------------------------------------------------------------- /AppTime/StatusViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // StatusViewCell.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | #import "AppRunInfo.h" 12 | 13 | @protocol StatusViewCellDelegate 14 | 15 | @optional 16 | -(void)popMenuClicked:(UITableViewCell*)cell withIndex:(int)index; 17 | 18 | @end 19 | @interface StatusViewCell : UITableViewCell 20 | { 21 | UILabel *label ; 22 | 23 | UILabel *labelCount ; 24 | UILabel *labelTime ; 25 | UIImageView *iconView ; 26 | } 27 | @property(nonatomic,unsafe_unretained)iddelegate; 28 | -(void)setAppInfo:(AppRunInfoItem*)appInfo; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /AppTime/StatusViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // StatusViewCell.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "StatusViewCell.h" 11 | #import "AppRunInfo.h" 12 | #import "AppTimeCounter.h" 13 | #define kTagLabel 100 14 | #define kTagLabelCount 105 15 | #define kTagLabelTime 110 16 | #define kTagImg 200 17 | #define kTagSwitch 300 18 | @implementation StatusViewCell 19 | @synthesize delegate; 20 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 21 | { 22 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 23 | if (self) { 24 | // Initialization code 25 | 26 | self.selectionStyle = UITableViewCellSelectionStyleNone; 27 | self.clipsToBounds = NO; 28 | 29 | label = [[UILabel alloc] initWithFrame:CGRectMake(64, 10, 150, 20)]; 30 | label.lineBreakMode = NSLineBreakByTruncatingTail; 31 | label.backgroundColor = [UIColor clearColor]; 32 | label.font = [UIFont boldSystemFontOfSize:15]; 33 | label.textColor = [UIColor blackColor]; 34 | label.tag = kTagLabel; 35 | [self.contentView addSubview:label]; 36 | 37 | UILabel *labelCountTitle = [[UILabel alloc] initWithFrame:CGRectMake(64, 35,80, 20)]; 38 | labelCountTitle.backgroundColor = [UIColor clearColor]; 39 | labelCountTitle.font = [UIFont systemFontOfSize:13]; 40 | labelCountTitle.textColor = [UIColor grayColor]; 41 | labelCountTitle.text = @"打开次数:"; 42 | [self.contentView addSubview:labelCountTitle]; 43 | 44 | labelCount = [[UILabel alloc] initWithFrame:CGRectMake(124, 35, 40, 20)]; 45 | labelCount.backgroundColor = [UIColor clearColor]; 46 | labelCount.font = [UIFont systemFontOfSize:13]; 47 | labelCount.textColor = [UIColor grayColor]; 48 | labelCount.tag = kTagLabelCount; 49 | 50 | [self.contentView addSubview:labelCount]; 51 | 52 | UILabel *labelTimeTitle = [[UILabel alloc] initWithFrame:CGRectMake(64, 50,80, 20)]; 53 | labelTimeTitle.backgroundColor = [UIColor clearColor]; 54 | labelTimeTitle.font = [UIFont systemFontOfSize:13]; 55 | labelTimeTitle.textColor = [UIColor grayColor]; 56 | labelTimeTitle.text = @"使用时长:"; 57 | [self.contentView addSubview:labelTimeTitle]; 58 | 59 | labelTime = [[UILabel alloc] initWithFrame:CGRectMake(124, 50, 90, 20)]; 60 | labelTime.backgroundColor = [UIColor clearColor]; 61 | labelTime.font = [UIFont systemFontOfSize:13]; 62 | labelTime.textColor = [UIColor grayColor]; 63 | labelTime.tag = kTagLabelTime; 64 | [self.contentView addSubview:labelTime]; 65 | 66 | 67 | 68 | iconView = [[UIImageView alloc]initWithFrame:CGRectMake(150, 8, 45, 45)]; 69 | iconView.tag = kTagImg; 70 | [self.contentView addSubview:iconView]; 71 | } 72 | return self; 73 | } 74 | 75 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated 76 | { 77 | [super setSelected:selected animated:animated]; 78 | 79 | 80 | // Configure the view for the selected state 81 | } 82 | 83 | -(void)setAppInfo:(AppRunInfoItem*)appInfo 84 | { 85 | 86 | 87 | label.text = appInfo.appName; 88 | iconView.image = [[AppTimeCounter sharedInstance]getAppIconImageByBundleId:appInfo.appId]; 89 | labelCount.text =[NSString stringWithFormat:@"%d次",appInfo.count]; 90 | iconView.hidden = NO; 91 | iconView.frame = CGRectMake(10, 8, 45, 45); 92 | label.frame = CGRectMake(64, 10, 120, 20); 93 | NSString *timeString = @""; 94 | 95 | int time = appInfo.runTime.intValue; 96 | if (time >= 0 && time < 60) 97 | { 98 | timeString = [NSString stringWithFormat:@"%d秒",time]; 99 | } 100 | else if (time >=60 && time < 3600) 101 | { 102 | timeString = [NSString stringWithFormat:@"%d分%d秒",time / 60, time % 60]; 103 | } 104 | else if (time >3600) 105 | { 106 | timeString = [NSString stringWithFormat:@"%d小时%d分",time / 3600, (time % 3600) / 60 ]; 107 | } 108 | else if (time >86400) 109 | { 110 | timeString = [NSString stringWithFormat:@"%d天%d小时",time/ 86400, (time % 3600) ]; 111 | } 112 | 113 | labelTime.text = timeString; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /AppTime/StatusViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // StatusViewController.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | #import "StatusViewCell.h" 12 | #import "rightViewController.h" 13 | typedef enum { 14 | CATE_COUNT, 15 | CATE_TIME, 16 | CATE_AVETIME 17 | } CATEGORY; 18 | 19 | typedef enum { 20 | DES, 21 | ASC 22 | } ORDER; 23 | @class QBPopupMenu; 24 | @interface StatusViewController:UIViewController 25 | { 26 | UITableView *statusTable; 27 | NSMutableArray *appInfoDatasource; 28 | int currentIndex; 29 | 30 | BOOL isFilter; 31 | } 32 | 33 | -(void)refresh; 34 | @property(nonatomic,assign)CATEGORY category; 35 | @property(nonatomic,assign)ORDER order; 36 | @end 37 | -------------------------------------------------------------------------------- /AppTime/Utility/AppRunInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppRunInfo.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | 12 | @interface AppRunInfoItem : NSObject 13 | @property(nonatomic,retain)NSString *appName; 14 | @property(nonatomic,retain)NSNumber *runTime; 15 | @property(nonatomic,retain)NSString *date; 16 | @property(nonatomic,retain)NSString *appId; 17 | @property(nonatomic,assign)int count; 18 | @end 19 | -------------------------------------------------------------------------------- /AppTime/Utility/AppRunInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppRunInfo.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "AppRunInfo.h" 11 | 12 | @implementation AppRunInfoItem 13 | @synthesize runTime; 14 | @synthesize appName; 15 | @synthesize date; 16 | @synthesize appId; 17 | @synthesize count; 18 | @end 19 | -------------------------------------------------------------------------------- /AppTime/Utility/AppTimeCounter.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppTimeCounter.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | @interface AppTimeCounter : NSObject 12 | { 13 | mach_port_t *p; 14 | void *uikit; 15 | int (*SBSSpringBoardServerPort)(); 16 | void *sbserv; 17 | NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggablet); 18 | void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result); 19 | void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result); 20 | NSString * (*SBSCopyLocalizedApplicationNameForDisplayIdentifier)(NSString* ); 21 | NSString * topAppBundleId; 22 | 23 | 24 | NSDate *dateForTopmostApp; 25 | 26 | NSTimer *timer; 27 | NSString *preTopMostAppId; 28 | NSString *currentTopAppId; 29 | 30 | int runTime; 31 | 32 | } 33 | +(AppTimeCounter*)sharedInstance; 34 | -(NSString*)getTopMostAppBundleId; 35 | -(void)pauseTimer; 36 | -(void)resumeTimer; 37 | -(UIImage*)getAppIconImageByBundleId:(NSString*)bundleid; 38 | @end 39 | 40 | -------------------------------------------------------------------------------- /AppTime/Utility/AppTimeCounter.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppTimeCounter.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "AppTimeCounter.h" 11 | #import 12 | #import 13 | #import 14 | #import "AppTimeAccess.h" 15 | #import "NSDate+Helper.h" 16 | 17 | @implementation AppTimeCounter 18 | static AppTimeCounter *instance = nil; 19 | 20 | #define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices" 21 | #define UIKITPATH "/System/Library/Framework/UIKit.framework/UIKit" 22 | #define PREPATH "/System/Library/PrivateFrameworks/Preferences.framework/Preferences" 23 | 24 | 25 | +(AppTimeCounter*)sharedInstance 26 | { 27 | @synchronized(self) 28 | { 29 | if (nil == instance) 30 | { 31 | instance = [[super allocWithZone:NULL] init]; 32 | 33 | } 34 | } 35 | return instance; 36 | } 37 | 38 | -(id)init 39 | { 40 | if (self = [super init]) 41 | { 42 | [self initPrivateAPI]; 43 | timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES]; 44 | currentTopAppId = [self getTopMostAppBundleId]; 45 | if (currentTopAppId != nil && ![currentTopAppId isEqualToString:@""]) 46 | { 47 | dateForTopmostApp = [NSDate date]; 48 | runTime = 0; 49 | } 50 | } 51 | return self; 52 | } 53 | 54 | -(void)initPrivateAPI 55 | { 56 | uikit = dlopen(UIKITPATH, RTLD_LAZY); 57 | SBSSpringBoardServerPort = 58 | dlsym(uikit, "SBSSpringBoardServerPort"); 59 | p = (mach_port_t *)SBSSpringBoardServerPort(); 60 | dlclose(uikit); 61 | sbserv = dlopen(SBSERVPATH, RTLD_LAZY); 62 | 63 | SBSCopyApplicationDisplayIdentifiers =dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers"); 64 | 65 | SBDisplayIdentifierForPID = 66 | dlsym(sbserv, "SBDisplayIdentifierForPID"); 67 | SBFrontmostApplicationDisplayIdentifier = dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier"); 68 | SBSCopyLocalizedApplicationNameForDisplayIdentifier = 69 | dlsym(sbserv, "SBSCopyLocalizedApplicationNameForDisplayIdentifier"); 70 | } 71 | 72 | -(NSString*)getTopMostAppBundleId 73 | { 74 | char topapp[256]; 75 | SBFrontmostApplicationDisplayIdentifier(p,topapp); 76 | 77 | NSString *bundleId=[NSString stringWithFormat:@"%s",topapp];//获取前台运行的app bundle id 78 | // if (topapp[0] == '\xd8') 79 | //{ 80 | // bundleId = @"Desktop"; 81 | // } 82 | return bundleId; 83 | } 84 | 85 | -(NSString*)getAppName:(NSString*)appId 86 | { 87 | return SBSCopyLocalizedApplicationNameForDisplayIdentifier(appId); 88 | } 89 | 90 | -(void)onTimer 91 | { 92 | preTopMostAppId = currentTopAppId; 93 | currentTopAppId = [self getTopMostAppBundleId]; 94 | 95 | NSString *preAppName = [self getAppName:preTopMostAppId]; 96 | 97 | BOOL isPreValid = [self isAppNameValid:preTopMostAppId]; 98 | BOOL isCurrentValid = [self isAppNameValid:currentTopAppId]; 99 | BOOL isSameId = [self isSame:preTopMostAppId withId:currentTopAppId]; 100 | 101 | 102 | if (isPreValid) 103 | { 104 | if (isCurrentValid) 105 | { 106 | if (isSameId) 107 | { 108 | runTime ++; 109 | }else 110 | { 111 | [self insertDataWithAppId:preTopMostAppId andAppName:preAppName andTime:runTime]; 112 | runTime = 0; 113 | 114 | } 115 | } 116 | else 117 | { 118 | [self insertDataWithAppId:preTopMostAppId andAppName:preAppName andTime:runTime]; 119 | runTime = 0; 120 | } 121 | } 122 | else 123 | { 124 | if (isCurrentValid) 125 | { 126 | runTime = 0; 127 | } 128 | } 129 | 130 | } 131 | 132 | -(BOOL)isAppIdValid:(NSString*)appId 133 | { 134 | return appId.length > 0; 135 | } 136 | 137 | -(BOOL)isAppNameValid:(NSString*)appId 138 | { 139 | NSString *appName = SBSCopyLocalizedApplicationNameForDisplayIdentifier(appId); 140 | return appName.length > 0; 141 | } 142 | 143 | -(BOOL)isSame:(NSString*)a withId:(NSString*)b 144 | { 145 | return [a isEqualToString:b]; 146 | } 147 | 148 | 149 | -(void)pauseTimer 150 | { 151 | [timer setFireDate:[NSDate distantFuture]]; 152 | } 153 | 154 | -(void)resumeTimer 155 | { 156 | [timer setFireDate:[NSDate date]]; 157 | 158 | } 159 | 160 | -(void)insertDataWithAppId:(NSString*)appId andAppName:(NSString*)appName andTime:(int)time 161 | { 162 | 163 | AppRunInfoItem *itemEntity = [[AppRunInfoItem alloc]init]; 164 | itemEntity.appId = appId; 165 | itemEntity.appName = appName; 166 | itemEntity.runTime = [NSNumber numberWithInt:time]; 167 | itemEntity.date = [[NSDate date]stringWithFormat:[NSDate dateFormatString]]; 168 | [[AppTimeAccess sharedInstance]insertAppRunInfoItem:itemEntity]; 169 | } 170 | 171 | 172 | -(UIImage*)getAppIconImageByBundleId:(NSString*)bundleid 173 | { 174 | NSData* (*SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString * bundleid) = 175 | dlsym(sbserv, "SBSCopyIconImagePNGDataForDisplayIdentifier"); 176 | 177 | UIImage *icon = nil; 178 | NSData *iconData = SBSCopyIconImagePNGDataForDisplayIdentifier(bundleid); 179 | if (iconData != nil) { 180 | icon = [UIImage imageWithData:iconData]; 181 | 182 | } 183 | return icon; 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /AppTime/Utility/MMPDeepSleepPreventer.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMPDeepSleepPreventer.h 3 | // MMPDeepSleepPreventer 4 | // 5 | // Created by Marco Peluso on 20.08.09. 6 | // Copyright (c) 2009-2010, Marco Peluso - marcopeluso.com 7 | // All rights reserved. 8 | // 9 | // Redistribution and use in source and binary forms, with or without 10 | // modification, are permitted provided that the following conditions are met: 11 | // 12 | // 1. Redistributions of source code must retain the above copyright notice, 13 | // this list of conditions and the following disclaimer. 14 | // 15 | // 2. Redistributions in binary form must reproduce the above copyright 16 | // notice, this list of conditions and the following disclaimer in the 17 | // documentation and/or other materials provided with the distribution. 18 | // 19 | // 3. Neither the name of the copyright holders nor the names of its 20 | // contributors may be used to endorse or promote products derived from 21 | // this software without specific prior written permission. 22 | // 23 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 25 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 27 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 30 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | // 35 | 36 | #pragma mark - 37 | #pragma mark MMPLog 38 | 39 | // Set up some advanced logging preprocessor macros to replace NSLog. 40 | // I usually have this in an external file (MMPLog.h) which is maintained in its own git repository. 41 | // I add this repository in my other projects as a submodule (via git submodule) and import the MMPLog.h 42 | // in a project's Prefix.pch. 43 | // 44 | // For convenience reasons, I just include these macros here, so other people are not confused by 45 | // git submodule if they are unfamiliar with it or simply don't have to bother and can use MMPDeepSleepPreventer 46 | // as simple drop-in code. 47 | 48 | #ifndef MMPDLog 49 | #ifdef DEBUG 50 | #define MMPDLog(format, ...) NSLog((@"%s [Line %d] " format), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 51 | #else 52 | #define MMPDLog(...) do { } while (0) 53 | #endif 54 | #endif 55 | 56 | #ifndef MMPALog 57 | #define MMPALog(format, ...) NSLog((@"%s [Line %d] " format), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) 58 | #endif 59 | 60 | 61 | #pragma mark - 62 | #pragma mark Imports and Forward Declarations 63 | 64 | #import 65 | 66 | @class AVAudioPlayer; 67 | 68 | 69 | #pragma mark - 70 | #pragma mark Public Interface 71 | 72 | @interface MMPDeepSleepPreventer : NSObject 73 | { 74 | 75 | } 76 | 77 | 78 | #pragma mark - 79 | #pragma mark Properties 80 | 81 | @property (nonatomic, retain) AVAudioPlayer *audioPlayer; 82 | @property (nonatomic, retain) NSTimer *preventSleepTimer; 83 | 84 | 85 | #pragma mark - 86 | #pragma mark Public Methods 87 | 88 | - (void)startPreventSleep; 89 | - (void)stopPreventSleep; 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /AppTime/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | 12 | @interface ViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /AppTime/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "ViewController.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | self.title = @"使用时间统计"; 22 | self.view.backgroundColor = [UIColor whiteColor]; 23 | // Do any additional setup after loading the view, typically from a nib. 24 | } 25 | 26 | - (void)didReceiveMemoryWarning 27 | { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /AppTime/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AppTime/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AppTime 4 | // 5 | // Created by zc on 14-2-12. 6 | // Copyright (c) 2014年 zc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /AppTime/rightViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // rightViewController.h 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import 11 | @class StatusViewController; 12 | @protocol rightViewControllerDelegate 13 | 14 | -(void)tableViewDidSelectedWithSection:(int)setion andRow:(int)row; 15 | 16 | @end 17 | 18 | @interface rightViewController : UIViewController 19 | 20 | @property (nonatomic, strong) UITableView * tableView; 21 | 22 | @property(nonatomic,unsafe_unretained)id delegate; 23 | 24 | @property(nonatomic,retain)StatusViewController *statusController; 25 | @end 26 | -------------------------------------------------------------------------------- /AppTime/rightViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // rightViewController.m 3 | // AppTime 4 | // 5 | // Created by gugupluto on 14-2-23. 6 | // Copyright (c) 2013年 gugupluto. All rights reserved. 7 | // http://www.cnblogs.com/gugupluto 8 | // https://github.com/gugupluto/iOSAppTime 9 | 10 | #import "rightViewController.h" 11 | #import "UIViewController+MMDrawerController.h" 12 | #import "StatusViewController.h" 13 | @interface rightViewController () 14 | { 15 | NSArray *orderArray; 16 | NSArray *cateArray; 17 | } 18 | @end 19 | 20 | @implementation rightViewController 21 | @synthesize tableView = _tableView; 22 | @synthesize delegate; 23 | @synthesize statusController; 24 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 25 | { 26 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 27 | if (self) { 28 | // Custom initialization 29 | } 30 | return self; 31 | } 32 | 33 | - (void)viewDidLoad 34 | { 35 | [super viewDidLoad]; 36 | self.view.backgroundColor = [UIColor whiteColor]; 37 | 38 | int y = 0; 39 | NSString * tmpVersonType = [UIDevice currentDevice].systemVersion; 40 | NSArray * tmpArr = [tmpVersonType componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"."]]; 41 | if([[tmpArr objectAtIndex:0] isEqualToString:@"7"]) 42 | { 43 | self.automaticallyAdjustsScrollViewInsets = NO; 44 | y = 70; 45 | } 46 | CGRect rc = self.view.bounds; 47 | rc.origin.y = y; 48 | _tableView = [[UITableView alloc] initWithFrame:rc style:UITableViewStyleGrouped]; 49 | [self.tableView setDelegate:self]; 50 | [self.tableView setDataSource:self]; 51 | [self.view addSubview:self.tableView]; 52 | [self.tableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; 53 | 54 | orderArray = [[NSArray alloc]initWithObjects:[NSNumber numberWithInt:DES],[NSNumber numberWithInt:ASC], nil]; 55 | 56 | cateArray = [[NSArray alloc]initWithObjects:[NSNumber numberWithInt:CATE_COUNT],[NSNumber numberWithInt:CATE_TIME],[NSNumber numberWithInt:CATE_AVETIME], nil]; 57 | 58 | 59 | 60 | 61 | 62 | // Do any additional setup after loading the view. 63 | } 64 | 65 | -(void)viewDidAppear:(BOOL)animated 66 | { 67 | [self.tableView reloadData]; 68 | } 69 | 70 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 71 | { 72 | return 2; 73 | } 74 | 75 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 76 | { 77 | // Return the number of rows in the section. 78 | switch (section) { 79 | case 0: 80 | return 2; 81 | case 1: 82 | return 3; 83 | default: 84 | return 0; 85 | } 86 | } 87 | 88 | 89 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 90 | { 91 | static NSString *CellIdentifier = @"Cell"; 92 | 93 | UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 94 | if (cell == nil) { 95 | 96 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 97 | [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 98 | } 99 | 100 | 101 | 102 | if (indexPath.section == 0) 103 | { 104 | NSNumber *order = [orderArray objectAtIndex:indexPath.row]; 105 | if(indexPath.row == 0){ 106 | [cell.textLabel setText:@"降序"]; 107 | } 108 | else { 109 | [cell.textLabel setText:@"升序"]; 110 | } 111 | 112 | if (order.intValue == self.statusController.order) { 113 | 114 | 115 | [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 116 | } 117 | else [cell setAccessoryType:UITableViewCellAccessoryNone]; 118 | } 119 | else 120 | { 121 | NSNumber *cate = [cateArray objectAtIndex:indexPath.row]; 122 | if(indexPath.row == 0){ 123 | [cell.textLabel setText:@"打开次数"]; 124 | } 125 | else if(indexPath.row == 1){ 126 | [cell.textLabel setText:@"使用时长"]; 127 | } 128 | else if(indexPath.row == 2){ 129 | [cell.textLabel setText:@"每次平均使用时长"]; 130 | } 131 | if (cate.intValue == self.statusController.category) { 132 | 133 | 134 | [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; 135 | } 136 | else [cell setAccessoryType:UITableViewCellAccessoryNone]; 137 | 138 | } 139 | return cell; 140 | } 141 | 142 | -(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ 143 | switch (section) { 144 | case 0: 145 | return @"顺序"; 146 | case 1: 147 | return @"类别"; 148 | default: 149 | return nil; 150 | } 151 | } 152 | 153 | -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 154 | return 23.0; 155 | } 156 | 157 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 158 | return 40.0; 159 | } 160 | 161 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 162 | { 163 | if (delegate != nil && [delegate respondsToSelector:@selector(tableViewDidSelectedWithSection:andRow: )]) 164 | { 165 | [delegate tableViewDidSelectedWithSection:indexPath.section andRow:indexPath.row]; 166 | } 167 | 168 | [self.mm_drawerController toggleDrawerSide:MMDrawerSideRight animated:YES completion:^(BOOL finished){}]; 169 | } 170 | 171 | - (void)didReceiveMemoryWarning 172 | { 173 | [super didReceiveMemoryWarning]; 174 | // Dispose of any resources that can be recreated. 175 | } 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /AppTimeTests/AppTimeTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | zc.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /AppTimeTests/AppTimeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppTimeTests.m 3 | // AppTimeTests 4 | // 5 | // Created by zc on 14-2-12. 6 | // Copyright (c) 2014年 zc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppTimeTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation AppTimeTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /AppTimeTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | --------------------------------------------------------------------------------