appjam 0.1.8.6 → 0.1.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/lib/appjam.rb +1 -1
  2. data/lib/appjam/generators/blank.rb +133 -0
  3. data/lib/appjam/generators/help.rb +5 -3
  4. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +855 -0
  5. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  6. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  7. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/EiffelApplication.xcscheme +96 -0
  8. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/xcuserdata/eiffel.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
  9. data/lib/appjam/generators/templates/blank/EiffelApplication/AppDelegate.h.tt +22 -0
  10. data/lib/appjam/generators/templates/blank/EiffelApplication/AppDelegate.m.tt +156 -0
  11. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Info.plist +45 -0
  12. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +30 -0
  13. data/lib/appjam/generators/templates/blank/EiffelApplication/en.lproj/InfoPlist.strings +2 -0
  14. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPClient.h +636 -0
  15. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPClient.m +1359 -0
  16. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPRequestOperation.h +133 -0
  17. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFHTTPRequestOperation.m +318 -0
  18. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFImageRequestOperation.h +108 -0
  19. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFImageRequestOperation.m +234 -0
  20. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFJSONRequestOperation.h +71 -0
  21. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFJSONRequestOperation.m +142 -0
  22. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworkActivityIndicatorManager.h +75 -0
  23. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworkActivityIndicatorManager.m +145 -0
  24. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFNetworking.h +43 -0
  25. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFPropertyListRequestOperation.h +68 -0
  26. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFPropertyListRequestOperation.m +142 -0
  27. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFURLConnectionOperation.h +379 -0
  28. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFURLConnectionOperation.m +818 -0
  29. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFXMLRequestOperation.h +89 -0
  30. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/AFXMLRequestOperation.m +166 -0
  31. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/UIImageView+AFNetworking.h +78 -0
  32. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFNetworking/UIImageView+AFNetworking.m +184 -0
  33. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/JSONKit/JSONKit.h +251 -0
  34. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/JSONKit/JSONKit.m +3067 -0
  35. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabase.h +155 -0
  36. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabase.m +1162 -0
  37. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseAdditions.h +37 -0
  38. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseAdditions.m +163 -0
  39. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabasePool.h +75 -0
  40. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabasePool.m +244 -0
  41. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseQueue.h +38 -0
  42. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMDatabaseQueue.m +176 -0
  43. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMResultSet.h +104 -0
  44. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/fmdb/FMResultSet.m +413 -0
  45. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/EGOCache/EGOCache.h +78 -0
  46. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/EGOCache/EGOCache.m +370 -0
  47. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDASLLogger.h +41 -0
  48. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDASLLogger.m +99 -0
  49. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDAbstractDatabaseLogger.h +102 -0
  50. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDAbstractDatabaseLogger.m +727 -0
  51. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDFileLogger.h +334 -0
  52. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDFileLogger.m +1353 -0
  53. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDLog.h +601 -0
  54. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDLog.m +1083 -0
  55. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDTTYLogger.h +167 -0
  56. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/DDTTYLogger.m +1479 -0
  57. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/ContextFilterLogFormatter.h +65 -0
  58. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/ContextFilterLogFormatter.m +191 -0
  59. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/DispatchQueueLogFormatter.h +116 -0
  60. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Lumberjack/Extensions/DispatchQueueLogFormatter.m +251 -0
  61. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/ObjectiveMixin/Mixin.h +33 -0
  62. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/ObjectiveMixin/Mixin.m +122 -0
  63. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USArrayWrapper.h +72 -0
  64. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USArrayWrapper.m +305 -0
  65. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USConstants.h +38 -0
  66. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USDictionaryWrapper.h +57 -0
  67. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/USDictionaryWrapper.m +188 -0
  68. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore+Functional.h +89 -0
  69. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore+Functional.m +261 -0
  70. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore-Prefix.pch +7 -0
  71. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore.h +50 -0
  72. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/Underscore/Underscore.m +100 -0
  73. data/lib/appjam/generators/templates/blank/EiffelApplication/main.m.tt +18 -0
  74. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests-Info.plist +22 -0
  75. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests.h.tt +13 -0
  76. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/EiffelApplicationTests.m.tt +32 -0
  77. data/lib/appjam/generators/templates/blank/EiffelApplicationTests/en.lproj/InfoPlist.strings +2 -0
  78. data/lib/appjam/generators/templates/resources/Default-568h@2x.png +0 -0
  79. data/lib/appjam/generators/templates/resources/Default.png +0 -0
  80. data/lib/appjam/generators/templates/resources/Default@2x.png +0 -0
  81. data/lib/appjam/generators/templates/resources/contents.tt +4 -0
  82. data/lib/appjam/version.rb +1 -1
  83. metadata +462 -326
  84. data/test/helper.rb +0 -132
  85. data/test/test_model_generator.rb +0 -28
  86. data/test/test_project_generator.rb +0 -38
@@ -0,0 +1,99 @@
1
+ #import "DDASLLogger.h"
2
+
3
+ #import <libkern/OSAtomic.h>
4
+
5
+ /**
6
+ * Welcome to Cocoa Lumberjack!
7
+ *
8
+ * The project page has a wealth of documentation if you have any questions.
9
+ * https://github.com/robbiehanson/CocoaLumberjack
10
+ *
11
+ * If you're new to the project you may wish to read the "Getting Started" wiki.
12
+ * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted
13
+ **/
14
+
15
+ #if ! __has_feature(objc_arc)
16
+ #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
17
+ #endif
18
+
19
+
20
+ @implementation DDASLLogger
21
+
22
+ static DDASLLogger *sharedInstance;
23
+
24
+ /**
25
+ * The runtime sends initialize to each class in a program exactly one time just before the class,
26
+ * or any class that inherits from it, is sent its first message from within the program. (Thus the
27
+ * method may never be invoked if the class is not used.) The runtime sends the initialize message to
28
+ * classes in a thread-safe manner. Superclasses receive this message before their subclasses.
29
+ *
30
+ * This method may also be called directly (assumably by accident), hence the safety mechanism.
31
+ **/
32
+ + (void)initialize
33
+ {
34
+ static BOOL initialized = NO;
35
+ if (!initialized)
36
+ {
37
+ initialized = YES;
38
+
39
+ sharedInstance = [[DDASLLogger alloc] init];
40
+ }
41
+ }
42
+
43
+ + (DDASLLogger *)sharedInstance
44
+ {
45
+ return sharedInstance;
46
+ }
47
+
48
+ - (id)init
49
+ {
50
+ if (sharedInstance != nil)
51
+ {
52
+ return nil;
53
+ }
54
+
55
+ if ((self = [super init]))
56
+ {
57
+ // A default asl client is provided for the main thread,
58
+ // but background threads need to create their own client.
59
+
60
+ client = asl_open(NULL, "com.apple.console", 0);
61
+ }
62
+ return self;
63
+ }
64
+
65
+ - (void)logMessage:(DDLogMessage *)logMessage
66
+ {
67
+ NSString *logMsg = logMessage->logMsg;
68
+
69
+ if (formatter)
70
+ {
71
+ logMsg = [formatter formatLogMessage:logMessage];
72
+ }
73
+
74
+ if (logMsg)
75
+ {
76
+ const char *msg = [logMsg UTF8String];
77
+
78
+ int aslLogLevel;
79
+ switch (logMessage->logFlag)
80
+ {
81
+ // Note: By default ASL will filter anything above level 5 (Notice).
82
+ // So our mappings shouldn't go above that level.
83
+
84
+ case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_CRIT; break;
85
+ case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_ERR; break;
86
+ case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_WARNING; break;
87
+ default : aslLogLevel = ASL_LEVEL_NOTICE; break;
88
+ }
89
+
90
+ asl_log(client, NULL, aslLogLevel, "%s", msg);
91
+ }
92
+ }
93
+
94
+ - (NSString *)loggerName
95
+ {
96
+ return @"cocoa.lumberjack.aslLogger";
97
+ }
98
+
99
+ @end
@@ -0,0 +1,102 @@
1
+ #import <Foundation/Foundation.h>
2
+
3
+ #import "DDLog.h"
4
+
5
+ /**
6
+ * Welcome to Cocoa Lumberjack!
7
+ *
8
+ * The project page has a wealth of documentation if you have any questions.
9
+ * https://github.com/robbiehanson/CocoaLumberjack
10
+ *
11
+ * If you're new to the project you may wish to read the "Getting Started" wiki.
12
+ * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted
13
+ *
14
+ *
15
+ * This class provides an abstract implementation of a database logger.
16
+ *
17
+ * That is, it provides the base implementation for a database logger to build atop of.
18
+ * All that is needed for a concrete database logger is to extend this class
19
+ * and override the methods in the implementation file that are prefixed with "db_".
20
+ **/
21
+
22
+ @interface DDAbstractDatabaseLogger : DDAbstractLogger {
23
+ @protected
24
+ NSUInteger saveThreshold;
25
+ NSTimeInterval saveInterval;
26
+ NSTimeInterval maxAge;
27
+ NSTimeInterval deleteInterval;
28
+ BOOL deleteOnEverySave;
29
+
30
+ BOOL saveTimerSuspended;
31
+ NSUInteger unsavedCount;
32
+ dispatch_time_t unsavedTime;
33
+ dispatch_source_t saveTimer;
34
+ dispatch_time_t lastDeleteTime;
35
+ dispatch_source_t deleteTimer;
36
+ }
37
+
38
+ /**
39
+ * Specifies how often to save the data to disk.
40
+ * Since saving is an expensive operation (disk io) it is not done after every log statement.
41
+ * These properties allow you to configure how/when the logger saves to disk.
42
+ *
43
+ * A save is done when either (whichever happens first):
44
+ *
45
+ * - The number of unsaved log entries reaches saveThreshold
46
+ * - The amount of time since the oldest unsaved log entry was created reaches saveInterval
47
+ *
48
+ * You can optionally disable the saveThreshold by setting it to zero.
49
+ * If you disable the saveThreshold you are entirely dependent on the saveInterval.
50
+ *
51
+ * You can optionally disable the saveInterval by setting it to zero (or a negative value).
52
+ * If you disable the saveInterval you are entirely dependent on the saveThreshold.
53
+ *
54
+ * It's not wise to disable both saveThreshold and saveInterval.
55
+ *
56
+ * The default saveThreshold is 500.
57
+ * The default saveInterval is 60 seconds.
58
+ **/
59
+ @property (assign, readwrite) NSUInteger saveThreshold;
60
+ @property (assign, readwrite) NSTimeInterval saveInterval;
61
+
62
+ /**
63
+ * It is likely you don't want the log entries to persist forever.
64
+ * Doing so would allow the database to grow infinitely large over time.
65
+ *
66
+ * The maxAge property provides a way to specify how old a log statement can get
67
+ * before it should get deleted from the database.
68
+ *
69
+ * The deleteInterval specifies how often to sweep for old log entries.
70
+ * Since deleting is an expensive operation (disk io) is is done on a fixed interval.
71
+ *
72
+ * An alternative to the deleteInterval is the deleteOnEverySave option.
73
+ * This specifies that old log entries should be deleted during every save operation.
74
+ *
75
+ * You can optionally disable the maxAge by setting it to zero (or a negative value).
76
+ * If you disable the maxAge then old log statements are not deleted.
77
+ *
78
+ * You can optionally disable the deleteInterval by setting it to zero (or a negative value).
79
+ *
80
+ * If you disable both deleteInterval and deleteOnEverySave then old log statements are not deleted.
81
+ *
82
+ * It's not wise to enable both deleteInterval and deleteOnEverySave.
83
+ *
84
+ * The default maxAge is 7 days.
85
+ * The default deleteInterval is 5 minutes.
86
+ * The default deleteOnEverySave is NO.
87
+ **/
88
+ @property (assign, readwrite) NSTimeInterval maxAge;
89
+ @property (assign, readwrite) NSTimeInterval deleteInterval;
90
+ @property (assign, readwrite) BOOL deleteOnEverySave;
91
+
92
+ /**
93
+ * Forces a save of any pending log entries (flushes log entries to disk).
94
+ **/
95
+ - (void)savePendingLogEntries;
96
+
97
+ /**
98
+ * Removes any log entries that are older than maxAge.
99
+ **/
100
+ - (void)deleteOldLogEntries;
101
+
102
+ @end
@@ -0,0 +1,727 @@
1
+ #import "DDAbstractDatabaseLogger.h"
2
+ #import <math.h>
3
+
4
+ /**
5
+ * Welcome to Cocoa Lumberjack!
6
+ *
7
+ * The project page has a wealth of documentation if you have any questions.
8
+ * https://github.com/robbiehanson/CocoaLumberjack
9
+ *
10
+ * If you're new to the project you may wish to read the "Getting Started" wiki.
11
+ * https://github.com/robbiehanson/CocoaLumberjack/wiki/GettingStarted
12
+ **/
13
+
14
+ #if ! __has_feature(objc_arc)
15
+ #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
16
+ #endif
17
+
18
+ @interface DDAbstractDatabaseLogger ()
19
+ - (void)destroySaveTimer;
20
+ - (void)destroyDeleteTimer;
21
+ @end
22
+
23
+ #pragma mark -
24
+
25
+ @implementation DDAbstractDatabaseLogger
26
+
27
+ - (id)init
28
+ {
29
+ if ((self = [super init]))
30
+ {
31
+ saveThreshold = 500;
32
+ saveInterval = 60; // 60 seconds
33
+ maxAge = (60 * 60 * 24 * 7); // 7 days
34
+ deleteInterval = (60 * 5); // 5 minutes
35
+ }
36
+ return self;
37
+ }
38
+
39
+ - (void)dealloc
40
+ {
41
+ [self destroySaveTimer];
42
+ [self destroyDeleteTimer];
43
+
44
+ }
45
+
46
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
47
+ #pragma mark Override Me
48
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49
+
50
+ - (BOOL)db_log:(DDLogMessage *)logMessage
51
+ {
52
+ // Override me and add your implementation.
53
+ //
54
+ // Return YES if an item was added to the buffer.
55
+ // Return NO if the logMessage was ignored.
56
+
57
+ return NO;
58
+ }
59
+
60
+ - (void)db_save
61
+ {
62
+ // Override me and add your implementation.
63
+ }
64
+
65
+ - (void)db_delete
66
+ {
67
+ // Override me and add your implementation.
68
+ }
69
+
70
+ - (void)db_saveAndDelete
71
+ {
72
+ // Override me and add your implementation.
73
+ }
74
+
75
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76
+ #pragma mark Private API
77
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78
+
79
+ - (void)performSaveAndSuspendSaveTimer
80
+ {
81
+ if (unsavedCount > 0)
82
+ {
83
+ if (deleteOnEverySave)
84
+ [self db_saveAndDelete];
85
+ else
86
+ [self db_save];
87
+ }
88
+
89
+ unsavedCount = 0;
90
+ unsavedTime = 0;
91
+
92
+ if (saveTimer && !saveTimerSuspended)
93
+ {
94
+ dispatch_suspend(saveTimer);
95
+ saveTimerSuspended = YES;
96
+ }
97
+ }
98
+
99
+ - (void)performDelete
100
+ {
101
+ if (maxAge > 0.0)
102
+ {
103
+ [self db_delete];
104
+
105
+ lastDeleteTime = dispatch_time(DISPATCH_TIME_NOW, 0);
106
+ }
107
+ }
108
+
109
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110
+ #pragma mark Timers
111
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
112
+
113
+ - (void)destroySaveTimer
114
+ {
115
+ if (saveTimer)
116
+ {
117
+ dispatch_source_cancel(saveTimer);
118
+ if (saveTimerSuspended)
119
+ {
120
+ // Must resume a timer before releasing it (or it will crash)
121
+ dispatch_resume(saveTimer);
122
+ saveTimerSuspended = NO;
123
+ }
124
+ #if !OS_OBJECT_USE_OBJC
125
+ dispatch_release(saveTimer);
126
+ #endif
127
+ saveTimer = NULL;
128
+ }
129
+ }
130
+
131
+ - (void)updateAndResumeSaveTimer
132
+ {
133
+ if ((saveTimer != NULL) && (saveInterval > 0.0) && (unsavedTime > 0.0))
134
+ {
135
+ uint64_t interval = (uint64_t)(saveInterval * NSEC_PER_SEC);
136
+ dispatch_time_t startTime = dispatch_time(unsavedTime, interval);
137
+
138
+ dispatch_source_set_timer(saveTimer, startTime, interval, 1.0);
139
+
140
+ if (saveTimerSuspended)
141
+ {
142
+ dispatch_resume(saveTimer);
143
+ saveTimerSuspended = NO;
144
+ }
145
+ }
146
+ }
147
+
148
+ - (void)createSuspendedSaveTimer
149
+ {
150
+ if ((saveTimer == NULL) && (saveInterval > 0.0))
151
+ {
152
+ saveTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue);
153
+
154
+ dispatch_source_set_event_handler(saveTimer, ^{ @autoreleasepool {
155
+
156
+ [self performSaveAndSuspendSaveTimer];
157
+
158
+ }});
159
+
160
+ saveTimerSuspended = YES;
161
+ }
162
+ }
163
+
164
+ - (void)destroyDeleteTimer
165
+ {
166
+ if (deleteTimer)
167
+ {
168
+ dispatch_source_cancel(deleteTimer);
169
+ #if !OS_OBJECT_USE_OBJC
170
+ dispatch_release(deleteTimer);
171
+ #endif
172
+ deleteTimer = NULL;
173
+ }
174
+ }
175
+
176
+ - (void)updateDeleteTimer
177
+ {
178
+ if ((deleteTimer != NULL) && (deleteInterval > 0.0) && (maxAge > 0.0))
179
+ {
180
+ uint64_t interval = (uint64_t)(deleteInterval * NSEC_PER_SEC);
181
+ dispatch_time_t startTime;
182
+
183
+ if (lastDeleteTime > 0)
184
+ startTime = dispatch_time(lastDeleteTime, interval);
185
+ else
186
+ startTime = dispatch_time(DISPATCH_TIME_NOW, interval);
187
+
188
+ dispatch_source_set_timer(deleteTimer, startTime, interval, 1.0);
189
+ }
190
+ }
191
+
192
+ - (void)createAndStartDeleteTimer
193
+ {
194
+ if ((deleteTimer == NULL) && (deleteInterval > 0.0) && (maxAge > 0.0))
195
+ {
196
+ deleteTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, loggerQueue);
197
+
198
+ if (deleteTimer != NULL) {
199
+ dispatch_source_set_event_handler(deleteTimer, ^{ @autoreleasepool {
200
+
201
+ [self performDelete];
202
+
203
+ }});
204
+
205
+ [self updateDeleteTimer];
206
+
207
+ dispatch_resume(deleteTimer);
208
+ }
209
+ }
210
+ }
211
+
212
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
213
+ #pragma mark Configuration
214
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
215
+
216
+ - (NSUInteger)saveThreshold
217
+ {
218
+ // The design of this method is taken from the DDAbstractLogger implementation.
219
+ // For extensive documentation please refer to the DDAbstractLogger implementation.
220
+
221
+ // Note: The internal implementation MUST access the colorsEnabled variable directly,
222
+ // This method is designed explicitly for external access.
223
+ //
224
+ // Using "self." syntax to go through this method will cause immediate deadlock.
225
+ // This is the intended result. Fix it by accessing the ivar directly.
226
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
227
+
228
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
229
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
230
+
231
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
232
+
233
+ __block NSUInteger result;
234
+
235
+ dispatch_sync(globalLoggingQueue, ^{
236
+ dispatch_sync(loggerQueue, ^{
237
+ result = saveThreshold;
238
+ });
239
+ });
240
+
241
+ return result;
242
+ }
243
+
244
+ - (void)setSaveThreshold:(NSUInteger)threshold
245
+ {
246
+ dispatch_block_t block = ^{ @autoreleasepool {
247
+
248
+ if (saveThreshold != threshold)
249
+ {
250
+ saveThreshold = threshold;
251
+
252
+ // Since the saveThreshold has changed,
253
+ // we check to see if the current unsavedCount has surpassed the new threshold.
254
+ //
255
+ // If it has, we immediately save the log.
256
+
257
+ if ((unsavedCount >= saveThreshold) && (saveThreshold > 0))
258
+ {
259
+ [self performSaveAndSuspendSaveTimer];
260
+ }
261
+ }
262
+ }};
263
+
264
+ // The design of the setter logic below is taken from the DDAbstractLogger implementation.
265
+ // For documentation please refer to the DDAbstractLogger implementation.
266
+
267
+ if ([self isOnInternalLoggerQueue])
268
+ {
269
+ block();
270
+ }
271
+ else
272
+ {
273
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
274
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
275
+
276
+ dispatch_async(globalLoggingQueue, ^{
277
+ dispatch_async(loggerQueue, block);
278
+ });
279
+ }
280
+ }
281
+
282
+ - (NSTimeInterval)saveInterval
283
+ {
284
+ // The design of this method is taken from the DDAbstractLogger implementation.
285
+ // For extensive documentation please refer to the DDAbstractLogger implementation.
286
+
287
+ // Note: The internal implementation MUST access the colorsEnabled variable directly,
288
+ // This method is designed explicitly for external access.
289
+ //
290
+ // Using "self." syntax to go through this method will cause immediate deadlock.
291
+ // This is the intended result. Fix it by accessing the ivar directly.
292
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
293
+
294
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
295
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
296
+
297
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
298
+
299
+ __block NSTimeInterval result;
300
+
301
+ dispatch_sync(globalLoggingQueue, ^{
302
+ dispatch_sync(loggerQueue, ^{
303
+ result = saveInterval;
304
+ });
305
+ });
306
+
307
+ return result;
308
+ }
309
+
310
+ - (void)setSaveInterval:(NSTimeInterval)interval
311
+ {
312
+ dispatch_block_t block = ^{ @autoreleasepool {
313
+
314
+ // C99 recommended floating point comparison macro
315
+ // Read: isLessThanOrGreaterThan(floatA, floatB)
316
+
317
+ if (/* saveInterval != interval */ islessgreater(saveInterval, interval))
318
+ {
319
+ saveInterval = interval;
320
+
321
+ // There are several cases we need to handle here.
322
+ //
323
+ // 1. If the saveInterval was previously enabled and it just got disabled,
324
+ // then we need to stop the saveTimer. (And we might as well release it.)
325
+ //
326
+ // 2. If the saveInterval was previously disabled and it just got enabled,
327
+ // then we need to setup the saveTimer. (Plus we might need to do an immediate save.)
328
+ //
329
+ // 3. If the saveInterval increased, then we need to reset the timer so that it fires at the later date.
330
+ //
331
+ // 4. If the saveInterval decreased, then we need to reset the timer so that it fires at an earlier date.
332
+ // (Plus we might need to do an immediate save.)
333
+
334
+ if (saveInterval > 0.0)
335
+ {
336
+ if (saveTimer == NULL)
337
+ {
338
+ // Handles #2
339
+ //
340
+ // Since the saveTimer uses the unsavedTime to calculate it's first fireDate,
341
+ // if a save is needed the timer will fire immediately.
342
+
343
+ [self createSuspendedSaveTimer];
344
+ [self updateAndResumeSaveTimer];
345
+ }
346
+ else
347
+ {
348
+ // Handles #3
349
+ // Handles #4
350
+ //
351
+ // Since the saveTimer uses the unsavedTime to calculate it's first fireDate,
352
+ // if a save is needed the timer will fire immediately.
353
+
354
+ [self updateAndResumeSaveTimer];
355
+ }
356
+ }
357
+ else if (saveTimer)
358
+ {
359
+ // Handles #1
360
+
361
+ [self destroySaveTimer];
362
+ }
363
+ }
364
+ }};
365
+
366
+ // The design of the setter logic below is taken from the DDAbstractLogger implementation.
367
+ // For documentation please refer to the DDAbstractLogger implementation.
368
+
369
+ if ([self isOnInternalLoggerQueue])
370
+ {
371
+ block();
372
+ }
373
+ else
374
+ {
375
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
376
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
377
+
378
+ dispatch_async(globalLoggingQueue, ^{
379
+ dispatch_async(loggerQueue, block);
380
+ });
381
+ }
382
+ }
383
+
384
+ - (NSTimeInterval)maxAge
385
+ {
386
+ // The design of this method is taken from the DDAbstractLogger implementation.
387
+ // For extensive documentation please refer to the DDAbstractLogger implementation.
388
+
389
+ // Note: The internal implementation MUST access the colorsEnabled variable directly,
390
+ // This method is designed explicitly for external access.
391
+ //
392
+ // Using "self." syntax to go through this method will cause immediate deadlock.
393
+ // This is the intended result. Fix it by accessing the ivar directly.
394
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
395
+
396
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
397
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
398
+
399
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
400
+
401
+ __block NSTimeInterval result;
402
+
403
+ dispatch_sync(globalLoggingQueue, ^{
404
+ dispatch_sync(loggerQueue, ^{
405
+ result = maxAge;
406
+ });
407
+ });
408
+
409
+ return result;
410
+ }
411
+
412
+ - (void)setMaxAge:(NSTimeInterval)interval
413
+ {
414
+ dispatch_block_t block = ^{ @autoreleasepool {
415
+
416
+ // C99 recommended floating point comparison macro
417
+ // Read: isLessThanOrGreaterThan(floatA, floatB)
418
+
419
+ if (/* maxAge != interval */ islessgreater(maxAge, interval))
420
+ {
421
+ NSTimeInterval oldMaxAge = maxAge;
422
+ NSTimeInterval newMaxAge = interval;
423
+
424
+ maxAge = interval;
425
+
426
+ // There are several cases we need to handle here.
427
+ //
428
+ // 1. If the maxAge was previously enabled and it just got disabled,
429
+ // then we need to stop the deleteTimer. (And we might as well release it.)
430
+ //
431
+ // 2. If the maxAge was previously disabled and it just got enabled,
432
+ // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.)
433
+ //
434
+ // 3. If the maxAge was increased,
435
+ // then we don't need to do anything.
436
+ //
437
+ // 4. If the maxAge was decreased,
438
+ // then we should do an immediate delete.
439
+
440
+ BOOL shouldDeleteNow = NO;
441
+
442
+ if (oldMaxAge > 0.0)
443
+ {
444
+ if (newMaxAge <= 0.0)
445
+ {
446
+ // Handles #1
447
+
448
+ [self destroyDeleteTimer];
449
+ }
450
+ else if (oldMaxAge > newMaxAge)
451
+ {
452
+ // Handles #4
453
+ shouldDeleteNow = YES;
454
+ }
455
+ }
456
+ else if (newMaxAge > 0.0)
457
+ {
458
+ // Handles #2
459
+ shouldDeleteNow = YES;
460
+ }
461
+
462
+ if (shouldDeleteNow)
463
+ {
464
+ [self performDelete];
465
+
466
+ if (deleteTimer)
467
+ [self updateDeleteTimer];
468
+ else
469
+ [self createAndStartDeleteTimer];
470
+ }
471
+ }
472
+ }};
473
+
474
+ // The design of the setter logic below is taken from the DDAbstractLogger implementation.
475
+ // For documentation please refer to the DDAbstractLogger implementation.
476
+
477
+ if ([self isOnInternalLoggerQueue])
478
+ {
479
+ block();
480
+ }
481
+ else
482
+ {
483
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
484
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
485
+
486
+ dispatch_async(globalLoggingQueue, ^{
487
+ dispatch_async(loggerQueue, block);
488
+ });
489
+ }
490
+ }
491
+
492
+ - (NSTimeInterval)deleteInterval
493
+ {
494
+ // The design of this method is taken from the DDAbstractLogger implementation.
495
+ // For extensive documentation please refer to the DDAbstractLogger implementation.
496
+
497
+ // Note: The internal implementation MUST access the colorsEnabled variable directly,
498
+ // This method is designed explicitly for external access.
499
+ //
500
+ // Using "self." syntax to go through this method will cause immediate deadlock.
501
+ // This is the intended result. Fix it by accessing the ivar directly.
502
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
503
+
504
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
505
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
506
+
507
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
508
+
509
+ __block NSTimeInterval result;
510
+
511
+ dispatch_sync(globalLoggingQueue, ^{
512
+ dispatch_sync(loggerQueue, ^{
513
+ result = deleteInterval;
514
+ });
515
+ });
516
+
517
+ return result;
518
+ }
519
+
520
+ - (void)setDeleteInterval:(NSTimeInterval)interval
521
+ {
522
+ dispatch_block_t block = ^{ @autoreleasepool {
523
+
524
+ // C99 recommended floating point comparison macro
525
+ // Read: isLessThanOrGreaterThan(floatA, floatB)
526
+
527
+ if (/* deleteInterval != interval */ islessgreater(deleteInterval, interval))
528
+ {
529
+ deleteInterval = interval;
530
+
531
+ // There are several cases we need to handle here.
532
+ //
533
+ // 1. If the deleteInterval was previously enabled and it just got disabled,
534
+ // then we need to stop the deleteTimer. (And we might as well release it.)
535
+ //
536
+ // 2. If the deleteInterval was previously disabled and it just got enabled,
537
+ // then we need to setup the deleteTimer. (Plus we might need to do an immediate delete.)
538
+ //
539
+ // 3. If the deleteInterval increased, then we need to reset the timer so that it fires at the later date.
540
+ //
541
+ // 4. If the deleteInterval decreased, then we need to reset the timer so that it fires at an earlier date.
542
+ // (Plus we might need to do an immediate delete.)
543
+
544
+ if (deleteInterval > 0.0)
545
+ {
546
+ if (deleteTimer == NULL)
547
+ {
548
+ // Handles #2
549
+ //
550
+ // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate,
551
+ // if a delete is needed the timer will fire immediately.
552
+
553
+ [self createAndStartDeleteTimer];
554
+ }
555
+ else
556
+ {
557
+ // Handles #3
558
+ // Handles #4
559
+ //
560
+ // Since the deleteTimer uses the lastDeleteTime to calculate it's first fireDate,
561
+ // if a save is needed the timer will fire immediately.
562
+
563
+ [self updateDeleteTimer];
564
+ }
565
+ }
566
+ else if (deleteTimer)
567
+ {
568
+ // Handles #1
569
+
570
+ [self destroyDeleteTimer];
571
+ }
572
+ }
573
+ }};
574
+
575
+ // The design of the setter logic below is taken from the DDAbstractLogger implementation.
576
+ // For documentation please refer to the DDAbstractLogger implementation.
577
+
578
+ if ([self isOnInternalLoggerQueue])
579
+ {
580
+ block();
581
+ }
582
+ else
583
+ {
584
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
585
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
586
+
587
+ dispatch_async(globalLoggingQueue, ^{
588
+ dispatch_async(loggerQueue, block);
589
+ });
590
+ }
591
+ }
592
+
593
+ - (BOOL)deleteOnEverySave
594
+ {
595
+ // The design of this method is taken from the DDAbstractLogger implementation.
596
+ // For extensive documentation please refer to the DDAbstractLogger implementation.
597
+
598
+ // Note: The internal implementation MUST access the colorsEnabled variable directly,
599
+ // This method is designed explicitly for external access.
600
+ //
601
+ // Using "self." syntax to go through this method will cause immediate deadlock.
602
+ // This is the intended result. Fix it by accessing the ivar directly.
603
+ // Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
604
+
605
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
606
+ NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
607
+
608
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
609
+
610
+ __block BOOL result;
611
+
612
+ dispatch_sync(globalLoggingQueue, ^{
613
+ dispatch_sync(loggerQueue, ^{
614
+ result = deleteOnEverySave;
615
+ });
616
+ });
617
+
618
+ return result;
619
+ }
620
+
621
+ - (void)setDeleteOnEverySave:(BOOL)flag
622
+ {
623
+ dispatch_block_t block = ^{
624
+
625
+ deleteOnEverySave = flag;
626
+ };
627
+
628
+ // The design of the setter logic below is taken from the DDAbstractLogger implementation.
629
+ // For documentation please refer to the DDAbstractLogger implementation.
630
+
631
+ if ([self isOnInternalLoggerQueue])
632
+ {
633
+ block();
634
+ }
635
+ else
636
+ {
637
+ dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
638
+ NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
639
+
640
+ dispatch_async(globalLoggingQueue, ^{
641
+ dispatch_async(loggerQueue, block);
642
+ });
643
+ }
644
+ }
645
+
646
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
647
+ #pragma mark Public API
648
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
649
+
650
+ - (void)savePendingLogEntries
651
+ {
652
+ dispatch_block_t block = ^{ @autoreleasepool {
653
+
654
+ [self performSaveAndSuspendSaveTimer];
655
+ }};
656
+
657
+ if ([self isOnInternalLoggerQueue])
658
+ block();
659
+ else
660
+ dispatch_async(loggerQueue, block);
661
+ }
662
+
663
+ - (void)deleteOldLogEntries
664
+ {
665
+ dispatch_block_t block = ^{ @autoreleasepool {
666
+
667
+ [self performDelete];
668
+ }};
669
+
670
+ if ([self isOnInternalLoggerQueue])
671
+ block();
672
+ else
673
+ dispatch_async(loggerQueue, block);
674
+ }
675
+
676
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
677
+ #pragma mark DDLogger
678
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
679
+
680
+ - (void)didAddLogger
681
+ {
682
+ // If you override me be sure to invoke [super didAddLogger];
683
+
684
+ [self createSuspendedSaveTimer];
685
+
686
+ [self createAndStartDeleteTimer];
687
+ }
688
+
689
+ - (void)willRemoveLogger
690
+ {
691
+ // If you override me be sure to invoke [super willRemoveLogger];
692
+
693
+ [self performSaveAndSuspendSaveTimer];
694
+
695
+ [self destroySaveTimer];
696
+ [self destroyDeleteTimer];
697
+ }
698
+
699
+ - (void)logMessage:(DDLogMessage *)logMessage
700
+ {
701
+ if ([self db_log:logMessage])
702
+ {
703
+ BOOL firstUnsavedEntry = (++unsavedCount == 1);
704
+
705
+ if ((unsavedCount >= saveThreshold) && (saveThreshold > 0))
706
+ {
707
+ [self performSaveAndSuspendSaveTimer];
708
+ }
709
+ else if (firstUnsavedEntry)
710
+ {
711
+ unsavedTime = dispatch_time(DISPATCH_TIME_NOW, 0);
712
+ [self updateAndResumeSaveTimer];
713
+ }
714
+ }
715
+ }
716
+
717
+ - (void)flush
718
+ {
719
+ // This method is invoked by DDLog's flushLog method.
720
+ //
721
+ // It is called automatically when the application quits,
722
+ // or if the developer invokes DDLog's flushLog method prior to crashing or something.
723
+
724
+ [self performSaveAndSuspendSaveTimer];
725
+ }
726
+
727
+ @end