├── 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 |
--------------------------------------------------------------------------------