An Objective-C wrapper for Mac OS X’s FSEvents C API.
Revision | d560344d1039c2091252717eb870a45dc81ed1dc (tree) |
---|---|
Time | 2011-10-25 02:34:06 |
Author | Aron Cedercrantz <aron@cede...> |
Commiter | Aron Cedercrantz |
Merge branch 'release/1.1.2'
* release/1.1.2: (21 commits)
Conflicts:
CDEvents.xcodeproj/project.pbxproj
@@ -1,3 +1,13 @@ | ||
1 | +.svn | |
2 | + | |
3 | +*.swp | |
4 | +*.o | |
5 | +*.lo | |
6 | +.libs | |
7 | +*.la | |
8 | + | |
9 | +.DS_Store | |
10 | + | |
1 | 11 | build |
2 | 12 | |
3 | 13 | *.perspectivev3 |
@@ -6,6 +16,8 @@ build | ||
6 | 16 | *.mode1v3 |
7 | 17 | *.mode2v3 |
8 | 18 | *.tm_build_errors |
19 | +*.xcodeproj/xcuserdata | |
20 | +*.xcodeproj/project.xcworkspace | |
9 | 21 | !default.pbxuser |
10 | 22 | !default.perspectivev3 |
11 | 23 | !default.mode1v3 |
@@ -14,6 +26,4 @@ build | ||
14 | 26 | *~.nib |
15 | 27 | *~.xib |
16 | 28 | |
17 | -.DS_Store | |
18 | - | |
19 | 29 | api |
@@ -38,7 +38,6 @@ | ||
38 | 38 | #import <Foundation/Foundation.h> |
39 | 39 | #import <CoreServices/CoreServices.h> |
40 | 40 | |
41 | - | |
42 | 41 | #pragma mark - |
43 | 42 | #pragma mark CDEvent types |
44 | 43 | /** |
@@ -77,6 +76,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
77 | 76 | } |
78 | 77 | |
79 | 78 | #pragma mark Properties |
79 | +/** @name Getting Event Properties */ | |
80 | 80 | /** |
81 | 81 | * The event identifier. |
82 | 82 | * |
@@ -106,6 +106,8 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
106 | 106 | */ |
107 | 107 | @property (readonly) NSURL *URL; |
108 | 108 | |
109 | + | |
110 | +/** @name Getting Event Flags */ | |
109 | 111 | /** |
110 | 112 | * The flags of the event. |
111 | 113 | * |
@@ -119,18 +121,26 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
119 | 121 | */ |
120 | 122 | @property (readonly) CDEventFlags flags; |
121 | 123 | |
124 | +#pragma mark flag macros | |
125 | + | |
126 | +#define FLAG_CHECK(flags, flag) ((flags) & (flag)) | |
127 | + | |
128 | +#define FLAG_PROPERTY(name, flag) \ | |
129 | +- (BOOL)name \ | |
130 | +{ return (FLAG_CHECK(_flags, flag) ? YES : NO); } | |
131 | + | |
122 | 132 | #pragma mark Specific flag properties |
123 | 133 | /** |
124 | 134 | * Wheter there was some change in the directory at the specific path supplied in this event. |
125 | 135 | * |
126 | - * @return <code>YES</code> if there was some change in the directory, otherwise <code>NO</code> | |
136 | + * @return <code>YES</code> if there was some change in the directory, otherwise <code>NO</code>. | |
127 | 137 | * |
128 | 138 | * @see kFSEventStreamEventFlagNone |
129 | 139 | * @see flags |
130 | 140 | * @see mustRescanSubDirectories |
131 | 141 | * @see isUserDropped |
132 | 142 | * @see isKernelDropped |
133 | - * @see isEventIdsWrapped | |
143 | + * @see isEventIdentifiersWrapped | |
134 | 144 | * @see isHistoryDone |
135 | 145 | * @see isRootChanged |
136 | 146 | * @see didVolumeMount |
@@ -148,19 +158,19 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
148 | 158 | * events were coalesced hierarchically. For example, an event in |
149 | 159 | * <code>/Users/jsmith/Music</code> and an event in |
150 | 160 | * <code>/Users/jsmith/Pictures</code> might be coalesced into an event with |
151 | - * this flag set and <i>URL</i><code>=/Users/jsmith</code>. If this flag is set | |
161 | + * this flag set and URL <code>= /Users/jsmith</code>. If this flag is set | |
152 | 162 | * you may be able to get an idea of whether the bottleneck happened in the |
153 | 163 | * kernel (less likely) or in your client (more likely) by checking if |
154 | - * flagUserDropped or flagKernelDropped returns <code>YES</code>. | |
164 | + * isUserDropped or isKernelDropped returns <code>YES</code>. | |
155 | 165 | * |
156 | - * @return <code>YES</code> if you must rescan the whole directory including its children, otherwise <code>NO</code> | |
166 | + * @return <code>YES</code> if you must rescan the whole directory including its children, otherwise <code>NO</code>. | |
157 | 167 | * |
158 | 168 | * @see kFSEventStreamEventFlagMustScanSubDirs |
159 | 169 | * @see flags |
160 | 170 | * @see isGenericChange |
161 | 171 | * @see isUserDropped |
162 | 172 | * @see isKernelDropped |
163 | - * @see isEventIdsWrapped | |
173 | + * @see isEventIdentifiersWrapped | |
164 | 174 | * @see isHistoryDone |
165 | 175 | * @see isRootChanged |
166 | 176 | * @see didVolumeMount |
@@ -173,14 +183,14 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
173 | 183 | /** |
174 | 184 | * Provides some information as to what might have caused the need to rescan the URL including its children. |
175 | 185 | * |
176 | - * @return <code>YES</code> if mustRescanSubDirectories returns <code>YES</code> and the cause were in userland, otherwise <code>NO</code> | |
186 | + * @return <code>YES</code> if mustRescanSubDirectories returns <code>YES</code> and the cause were in userland, otherwise <code>NO</code>. | |
177 | 187 | * |
178 | 188 | * @see kFSEventStreamEventFlagUserDropped |
179 | 189 | * @see flags |
180 | 190 | * @see isGenericChange |
181 | 191 | * @see mustRescanSubDirectories |
182 | 192 | * @see isKernelDropped |
183 | - * @see isEventIdsWrapped | |
193 | + * @see isEventIdentifiersWrapped | |
184 | 194 | * @see isHistoryDone |
185 | 195 | * @see isRootChanged |
186 | 196 | * @see didVolumeMount |
@@ -193,14 +203,14 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
193 | 203 | /** |
194 | 204 | * Provides some information as to what might have caused the need to rescan the URL including its children. |
195 | 205 | * |
196 | - * @return <code>YES</code> if mustRescanSubDirectories returns <code>YES</code> and the cause were in kernelspace, otherwise <code>NO</code> | |
206 | + * @return <code>YES</code> if mustRescanSubDirectories returns <code>YES</code> and the cause were in kernelspace, otherwise <code>NO</code>. | |
197 | 207 | * |
198 | 208 | * @see kFSEventStreamEventFlagKernelDropped |
199 | 209 | * @see flags |
200 | 210 | * @see isGenericChange |
201 | 211 | * @see mustRescanSubDirectories |
202 | 212 | * @see isUserDropped |
203 | - * @see isEventIdsWrapped | |
213 | + * @see isEventIdentifiersWrapped | |
204 | 214 | * @see isHistoryDone |
205 | 215 | * @see isRootChanged |
206 | 216 | * @see didVolumeMount |
@@ -217,7 +227,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
217 | 227 | * previously-issued event identifiers are no longer valid arguments for the |
218 | 228 | * sinceEventIdentifier parameter of the CDEvents init methods. |
219 | 229 | * |
220 | - * @return <code>YES</code> if the 64-bit event identifier counter has wrapped around, otherwise <code>NO</code> | |
230 | + * @return <code>YES</code> if the 64-bit event identifier counter has wrapped around, otherwise <code>NO</code>. | |
221 | 231 | * |
222 | 232 | * @see kFSEventStreamEventFlagEventIdsWrapped |
223 | 233 | * @see flags |
@@ -241,7 +251,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
241 | 251 | * as a result of specifying a <i>sinceEventIdentifier</i> argument other than |
242 | 252 | * kCDEventsSinceEventNow with the CDEvents init methods. |
243 | 253 | * |
244 | - * @return <code>YES</code> if if the event is sent to mark the end of the "historical" events sent, otherwise <code>NO</code> | |
254 | + * @return <code>YES</code> if if the event is sent to mark the end of the "historical" events sent, otherwise <code>NO</code>. | |
245 | 255 | * |
246 | 256 | * @see kFSEventStreamEventFlagHistoryDone |
247 | 257 | * @see flags |
@@ -249,7 +259,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
249 | 259 | * @see mustRescanSubDirectories |
250 | 260 | * @see isUserDropped |
251 | 261 | * @see isKernelDropped |
252 | - * @see isEventIdsWrapped | |
262 | + * @see isEventIdentifiersWrapped | |
253 | 263 | * @see isRootChanged |
254 | 264 | * @see didVolumeMount |
255 | 265 | * @see didVolumeUnmount |
@@ -271,7 +281,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
271 | 281 | * with this flag set will only be sent if you passed the flag |
272 | 282 | * <code>kFSEventStreamCreateFlagWatchRoot</code> to the CDEvents. |
273 | 283 | * |
274 | - * @return <code>YES</code> if there is a change to one of the URLs you asked to watch, otherwise <code>NO</code> | |
284 | + * @return <code>YES</code> if there is a change to one of the URLs you asked to watch, otherwise <code>NO</code>. | |
275 | 285 | * |
276 | 286 | * @see kFSEventStreamEventFlagRootChanged |
277 | 287 | * @see flags |
@@ -279,7 +289,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
279 | 289 | * @see mustRescanSubDirectories |
280 | 290 | * @see isUserDropped |
281 | 291 | * @see isKernelDropped |
282 | - * @see isEventIdsWrapped | |
292 | + * @see isEventIdentifiersWrapped | |
283 | 293 | * @see isHistoryDone |
284 | 294 | * @see didVolumeMount |
285 | 295 | * @see didVolumeUnmount |
@@ -304,7 +314,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
304 | 314 | * Also be aware of the <code>MNT_DONTBROWSE</code> flag that is set for volumes |
305 | 315 | * which should not be displayed by user interface elements. |
306 | 316 | * |
307 | - * @return <code>YES</code> if a volumen is mounted underneath one of the URLs being watched, otherwise <code>NO</code> | |
317 | + * @return <code>YES</code> if a volumen is mounted underneath one of the URLs being watched, otherwise <code>NO</code>. | |
308 | 318 | * |
309 | 319 | * @see kFSEventStreamEventFlagMount |
310 | 320 | * @see flags |
@@ -312,7 +322,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
312 | 322 | * @see mustRescanSubDirectories |
313 | 323 | * @see isUserDropped |
314 | 324 | * @see isKernelDropped |
315 | - * @see isEventIdsWrapped | |
325 | + * @see isEventIdentifiersWrapped | |
316 | 326 | * @see isHistoryDone |
317 | 327 | * @see isRootChanged |
318 | 328 | * @see didVolumeUnmount |
@@ -333,7 +343,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
333 | 343 | * could uncover an arbitrarily large directory hierarchy, although Mac OS X |
334 | 344 | * never does that. |
335 | 345 | * |
336 | - * @return <code>YES</code> if a volume is unmounted underneath one of the URLs being watched, otherwise <code>NO</code> | |
346 | + * @return <code>YES</code> if a volume is unmounted underneath one of the URLs being watched, otherwise <code>NO</code>. | |
337 | 347 | * |
338 | 348 | * @see kFSEventStreamEventFlagUnmount |
339 | 349 | * @see flags |
@@ -341,7 +351,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
341 | 351 | * @see mustRescanSubDirectories |
342 | 352 | * @see isUserDropped |
343 | 353 | * @see isKernelDropped |
344 | - * @see isEventIdsWrapped | |
354 | + * @see isEventIdentifiersWrapped | |
345 | 355 | * @see isHistoryDone |
346 | 356 | * @see isRootChanged |
347 | 357 | * @see didVolumeMount |
@@ -351,8 +361,26 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
351 | 361 | @property (readonly) BOOL didVolumeUnmount; |
352 | 362 | |
353 | 363 | |
354 | -#pragma mark Class object creators | |
364 | +/** | |
365 | + * The entirety of the documentation on file level events in lion is 3 sentences | |
366 | + * long. Rename behavior is odd, making the combination of events and flags | |
367 | + * somewhat confusing for atomic writes. It also appears possible to get a | |
368 | + * singular event where a file has been created, modified, and removed. | |
369 | + */ | |
370 | +@property (readonly) BOOL isCreated; | |
371 | +@property (readonly) BOOL isRemoved; | |
372 | +@property (readonly) BOOL isInodeMetadataModified; | |
373 | +@property (readonly) BOOL isRenamed; | |
374 | +@property (readonly) BOOL isModified; | |
375 | +@property (readonly) BOOL isFinderInfoModified; | |
376 | +@property (readonly) BOOL didChangeOwner; | |
377 | +@property (readonly) BOOL isXattrModified; | |
378 | +@property (readonly) BOOL isFile; | |
379 | +@property (readonly) BOOL isDir; | |
380 | +@property (readonly) BOOL isSymlink; | |
355 | 381 | |
382 | +#pragma mark Class object creators | |
383 | +/** @name Creating CDEvent Objects */ | |
356 | 384 | /** |
357 | 385 | * Returns an <code>CDEvent</code> created with the given identifier, date, URL and flags. |
358 | 386 | * |
@@ -27,7 +27,7 @@ | ||
27 | 27 | */ |
28 | 28 | |
29 | 29 | #import "CDEvent.h" |
30 | - | |
30 | +#import "compat.h" | |
31 | 31 | |
32 | 32 | @implementation CDEvent |
33 | 33 |
@@ -104,52 +104,33 @@ | ||
104 | 104 | return [self retain]; |
105 | 105 | } |
106 | 106 | |
107 | - | |
108 | 107 | #pragma mark Specific flag properties |
109 | 108 | - (BOOL)isGenericChange |
110 | 109 | { |
111 | 110 | return (kFSEventStreamEventFlagNone == _flags); |
112 | 111 | } |
113 | 112 | |
114 | -- (BOOL)mustRescanSubDirectories | |
115 | -{ | |
116 | - return (_flags & kFSEventStreamEventFlagMustScanSubDirs); | |
117 | -} | |
118 | - | |
119 | -- (BOOL)isUserDropped | |
120 | -{ | |
121 | - return (_flags & kFSEventStreamEventFlagUserDropped); | |
122 | -} | |
123 | - | |
124 | -- (BOOL)isKernelDropped | |
125 | -{ | |
126 | - return (_flags & kFSEventStreamEventFlagKernelDropped); | |
127 | -} | |
128 | - | |
129 | -- (BOOL)isEventIdentifiersWrapped | |
130 | -{ | |
131 | - return (_flags & kFSEventStreamEventFlagEventIdsWrapped); | |
132 | -} | |
133 | - | |
134 | -- (BOOL)isHistoryDone | |
135 | -{ | |
136 | - return (_flags & kFSEventStreamEventFlagHistoryDone); | |
137 | -} | |
138 | - | |
139 | -- (BOOL)isRootChanged | |
140 | -{ | |
141 | - return (_flags & kFSEventStreamEventFlagRootChanged); | |
142 | -} | |
143 | - | |
144 | -- (BOOL)didVolumeMount | |
145 | -{ | |
146 | - return (_flags & kFSEventStreamEventFlagMount); | |
147 | -} | |
148 | - | |
149 | -- (BOOL)didVolumeUnmount | |
150 | -{ | |
151 | - return (_flags & kFSEventStreamEventFlagUnmount); | |
152 | -} | |
113 | +FLAG_PROPERTY(mustRescanSubDirectories, kFSEventStreamEventFlagMustScanSubDirs) | |
114 | +FLAG_PROPERTY(isUserDropped, kFSEventStreamEventFlagUserDropped) | |
115 | +FLAG_PROPERTY(isKernelDropped, kFSEventStreamEventFlagKernelDropped) | |
116 | +FLAG_PROPERTY(isEventIdentifiersWrapped, kFSEventStreamEventFlagEventIdsWrapped) | |
117 | +FLAG_PROPERTY(isHistoryDone, kFSEventStreamEventFlagHistoryDone) | |
118 | +FLAG_PROPERTY(isRootChanged, kFSEventStreamEventFlagRootChanged) | |
119 | +FLAG_PROPERTY(didVolumeMount, kFSEventStreamEventFlagMount) | |
120 | +FLAG_PROPERTY(didVolumeUnmount, kFSEventStreamEventFlagUnmount) | |
121 | + | |
122 | +// file-level events introduced in 10.7 | |
123 | +FLAG_PROPERTY(isCreated, kFSEventStreamEventFlagItemCreated) | |
124 | +FLAG_PROPERTY(isRemoved, kFSEventStreamEventFlagItemRemoved) | |
125 | +FLAG_PROPERTY(isInodeMetadataModified, kFSEventStreamEventFlagItemInodeMetaMod) | |
126 | +FLAG_PROPERTY(isRenamed, kFSEventStreamEventFlagItemRenamed) | |
127 | +FLAG_PROPERTY(isModified, kFSEventStreamEventFlagItemModified) | |
128 | +FLAG_PROPERTY(isFinderInfoModified, kFSEventStreamEventFlagItemFinderInfoMod) | |
129 | +FLAG_PROPERTY(didChangeOwner, kFSEventStreamEventFlagItemChangeOwner) | |
130 | +FLAG_PROPERTY(isXattrModified, kFSEventStreamEventFlagItemXattrMod) | |
131 | +FLAG_PROPERTY(isFile, kFSEventStreamEventFlagItemIsFile) | |
132 | +FLAG_PROPERTY(isDir, kFSEventStreamEventFlagItemIsDir) | |
133 | +FLAG_PROPERTY(isSymlink, kFSEventStreamEventFlagItemIsSymlink) | |
153 | 134 | |
154 | 135 | #pragma mark Misc |
155 | 136 | - (NSString *)description |
@@ -70,7 +70,7 @@ extern NSString *const CDEventsEventStreamCreationFailureException; | ||
70 | 70 | * |
71 | 71 | * @since 1.0.0 |
72 | 72 | */ |
73 | -#define CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY (NSTimeInterval)3.0 | |
73 | +#define CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY ((NSTimeInterval)3.0) | |
74 | 74 | |
75 | 75 | /** |
76 | 76 | * The default value wheter events from sub directories should be ignored or not. |
@@ -84,16 +84,14 @@ extern NSString *const CDEventsEventStreamCreationFailureException; | ||
84 | 84 | * |
85 | 85 | * @since 1.0.0 |
86 | 86 | */ |
87 | -const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags = | |
88 | - (kFSEventStreamCreateFlagUseCFTypes | | |
89 | - kFSEventStreamCreateFlagWatchRoot); | |
87 | +extern const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags; | |
90 | 88 | |
91 | 89 | /** |
92 | 90 | * Use this to get all event since now when initializing a CDEvents object. |
93 | 91 | * |
94 | 92 | * @since 1.1.0 |
95 | 93 | */ |
96 | -const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | |
94 | +extern const CDEventIdentifier kCDEventsSinceEventNow; | |
97 | 95 | |
98 | 96 | |
99 | 97 | #pragma mark - |
@@ -109,7 +107,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
109 | 107 | */ |
110 | 108 | @interface CDEvents : NSObject <NSCopying> { |
111 | 109 | @private |
112 | - id<CDEventsDelegate> _delegate; | |
110 | + __weak id<CDEventsDelegate> _delegate; | |
113 | 111 | |
114 | 112 | FSEventStreamRef _eventStream; |
115 | 113 | CFTimeInterval _notificationLatency; |
@@ -126,16 +124,20 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
126 | 124 | } |
127 | 125 | |
128 | 126 | #pragma mark Properties |
127 | +/** @name Managing the Delegate */ | |
129 | 128 | /** |
130 | 129 | * The delegate object the <code>CDEvents</code> object calls when it recieves an event. |
131 | 130 | * |
132 | - * @param delegate Delegate for the events object. <code>nil</code> removed the delegate. | |
131 | + * @param delegate Delegate for the events object. <code>nil</code> removes the delegate. | |
133 | 132 | * @return The events's delegate. |
134 | 133 | * |
134 | + * @see CDEventsDelegate | |
135 | + * | |
135 | 136 | * @since 1.0.0 |
136 | 137 | */ |
137 | -@property (assign) id<CDEventsDelegate> delegate; | |
138 | +@property (assign) __weak id<CDEventsDelegate> delegate; | |
138 | 139 | |
140 | +/** @name Getting Event Watcher Properties */ | |
139 | 141 | /** |
140 | 142 | * The (approximate) time intervall between notifications sent to the delegate. |
141 | 143 | * |
@@ -143,7 +145,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
143 | 145 | * |
144 | 146 | * @since 1.0.0 |
145 | 147 | */ |
146 | -@property (readonly) CFTimeInterval notificationLatency; | |
148 | +@property (readonly) CFTimeInterval notificationLatency; | |
147 | 149 | |
148 | 150 | /** |
149 | 151 | * The event identifier from which events will be supplied to the delegate. |
@@ -152,17 +154,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
152 | 154 | * |
153 | 155 | * @since 1.0.0 |
154 | 156 | */ |
155 | -@property (readonly) CDEventIdentifier sinceEventIdentifier; | |
156 | - | |
157 | -/** | |
158 | - * Wheter events from sub-directories of the watched URLs should be ignored or not. | |
159 | - * | |
160 | - * @param flag Wheter events from sub-directories of the watched URLs shouled be ignored or not. | |
161 | - * @return <code>YES</code> if events from sub-directories should be ignored, otherwise <code>NO</code>. | |
162 | - * | |
163 | - * @since 1.0.0 | |
164 | - */ | |
165 | -@property (assign) BOOL ignoreEventsFromSubDirectories; | |
157 | +@property (readonly) CDEventIdentifier sinceEventIdentifier; | |
166 | 158 | |
167 | 159 | /** |
168 | 160 | * The last event that occured and thas has been delivered to the delegate. |
@@ -171,7 +163,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
171 | 163 | * |
172 | 164 | * @since 1.0.0 |
173 | 165 | */ |
174 | -@property (retain) CDEvent *lastEvent; | |
166 | +@property (retain, readonly) CDEvent *lastEvent; | |
175 | 167 | |
176 | 168 | /** |
177 | 169 | * The URLs that we watch for events. |
@@ -180,8 +172,10 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
180 | 172 | * |
181 | 173 | * @since 1.0.0 |
182 | 174 | */ |
183 | -@property (readonly) NSArray *watchedURLs; | |
175 | +@property (readonly) NSArray *watchedURLs; | |
184 | 176 | |
177 | + | |
178 | +/** @name Configuring the Event watcher */ | |
185 | 179 | /** |
186 | 180 | * The URLs that we should ignore events from. |
187 | 181 | * |
@@ -190,10 +184,21 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
190 | 184 | * |
191 | 185 | * @since 1.0.0 |
192 | 186 | */ |
193 | -@property (copy) NSArray *excludedURLs; | |
187 | +@property (copy) NSArray *excludedURLs; | |
188 | + | |
189 | +/** | |
190 | + * Wheter events from sub-directories of the watched URLs should be ignored or not. | |
191 | + * | |
192 | + * @param flag Wheter events from sub-directories of the watched URLs shouled be ignored or not. | |
193 | + * @return <code>YES</code> if events from sub-directories should be ignored, otherwise <code>NO</code>. | |
194 | + * | |
195 | + * @since 1.0.0 | |
196 | + */ | |
197 | +@property (assign) BOOL ignoreEventsFromSubDirectories; | |
194 | 198 | |
195 | 199 | |
196 | 200 | #pragma mark Event identifier class methods |
201 | +/** @name Current Event Identifier */ | |
197 | 202 | /** |
198 | 203 | * The current event identifier. |
199 | 204 | * |
@@ -207,28 +212,30 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
207 | 212 | |
208 | 213 | |
209 | 214 | #pragma mark Init methods |
215 | +/** @name Creating CDEvents Objects */ | |
210 | 216 | /** |
211 | 217 | * Returns an <code>CDEvents</code> object initialized with the given URLs to watch. |
212 | 218 | * |
213 | 219 | * @param URLs An array of URLs we want to watch. |
214 | - * @param delegate The delegate object the <code>CDEvents</code> object calls when it recieves an event. | |
215 | - * @return An <code>CDEvents</code> object initialized with the given URLs to watch. | |
220 | + * @param delegate The delegate object the CDEvents object calls when it recieves an event. | |
221 | + * @return An CDEvents object initialized with the given URLs to watch. | |
216 | 222 | * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>. |
217 | 223 | * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. |
218 | 224 | * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. |
219 | 225 | * |
220 | 226 | * @see initWithURLs:delegate:onRunLoop: |
221 | - * @see initWithURLs:delegate:onRunLoop:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
227 | + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
228 | + * @see CDEventsDelegate | |
222 | 229 | * @see kCDEventsDefaultEventStreamFlags |
223 | 230 | * @see kCDEventsSinceEventNow |
224 | 231 | * |
225 | - * @discussion Calls startWatchingURLs:onRunLoop:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
226 | - * with <em>sinceEventIdentifier</em> with the event identifier for "event since | |
227 | - * now", <em>notificationLatency</em> set to 3.0 seconds, | |
228 | - * <em>ignoreEventsFromSubDirectories</em> set to <code>NO</code>, | |
229 | - * <em>excludedURLs</em> to no URLs, the event stream creation flags will be set | |
230 | - * to <code>kCDEventsDefaultEventStreamFlags</code> and schedueled on the | |
231 | - * current run loop. | |
232 | + * @discussion Calls initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
233 | + * with <code>sinceEventIdentifier</code> with the event identifier for "event | |
234 | + * since now", <code>notificationLatency</code> set to 3.0 seconds, | |
235 | + * <code>ignoreEventsFromSubDirectories</code> set to <code>NO</code>, | |
236 | + * <code>excludedURLs</code> to <code>nil</code>, the event stream creation | |
237 | + * flags will be set to <code>kCDEventsDefaultEventStreamFlags</code> and | |
238 | + * schedueled on the current run loop. | |
232 | 239 | * |
233 | 240 | * @since 1.0.0 |
234 | 241 | */ |
@@ -238,24 +245,25 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
238 | 245 | * Returns an <code>CDEvents</code> object initialized with the given URLs to watch and schedules the watcher on the given run loop. |
239 | 246 | * |
240 | 247 | * @param URLs An array of URLs we want to watch. |
241 | - * @param delegate The delegate object the <code>CDEvents</code> object calls when it recieves an event. | |
242 | - * @param The run loop which the which the watcher should be schedueled on. | |
243 | - * @return An <code>CDEvents</code> object initialized with the given URLs to watch. | |
248 | + * @param delegate The delegate object the CDEvents object calls when it recieves an event. | |
249 | + * @param runLoop The run loop which the which the watcher should be schedueled on. | |
250 | + * @return An CDEvents object initialized with the given URLs to watch. | |
244 | 251 | * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>. |
245 | 252 | * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. |
246 | 253 | * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. |
247 | 254 | * |
248 | - * @see initWithURLs: | |
249 | - * @see initWithURLs:onRunLoop:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
255 | + * @see initWithURLs:delegate: | |
256 | + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
257 | + * @see CDEventsDelegate | |
250 | 258 | * @see kCDEventsDefaultEventStreamFlags |
251 | 259 | * @see kCDEventsSinceEventNow |
252 | 260 | * |
253 | - * @discussion Calls startWatchingURLs:onRunLoop:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
254 | - * with <em>runLoop</em> set to the current run loop, <em>sinceEventIdentifier</em> | |
255 | - * with the event identifier for "event since now", <em>notificationLatency</em> | |
256 | - * set to 3.0 seconds, <em>ignoreEventsFromSubDirectories</em> set to | |
257 | - * <code>NO</code>, <em>excludedURLs</em> to no URLs and the event stream | |
258 | - * creation flags will be set to <code>kCDEventsDefaultEventStreamFlags</code>. | |
261 | + * @discussion Calls initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
262 | + * with <code>sinceEventIdentifier</code> with the event identifier for "event | |
263 | + * since now", <code>notificationLatency</code> set to 3.0 seconds, | |
264 | + * <code>ignoreEventsFromSubDirectories</code> set to <code>NO</code>, | |
265 | + * <code>excludedURLs</code> to <code>nil</code> and the event stream creation | |
266 | + * flags will be set to <code>kCDEventsDefaultEventStreamFlags</code>. | |
259 | 267 | * |
260 | 268 | * @since 1.0.0 |
261 | 269 | */ |
@@ -263,30 +271,33 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
263 | 271 | delegate:(id<CDEventsDelegate>)delegate |
264 | 272 | onRunLoop:(NSRunLoop *)runLoop; |
265 | 273 | |
274 | + | |
275 | + | |
266 | 276 | /** |
267 | 277 | * Returns an <code>CDEvents</code> object initialized with the given URLs to watch, URLs to exclude, wheter events from sub-directories are ignored or not and schedules the watcher on the given run loop. |
268 | 278 | * |
269 | - * @param URLs An array of URLs we want to watch. | |
270 | - * @param delegate The delegate object the <code>CDEvents</code> object calls when it recieves an event. | |
279 | + * @param URLs An array of URLs (<code>NSURL</code>) we want to watch. | |
280 | + * @param delegate The delegate object the CDEvents object calls when it recieves an event. | |
271 | 281 | * @param runLoop The run loop which the which the watcher should be schedueled on. |
272 | 282 | * @param sinceEventIdentifier Events that have happened after the given event identifier will be supplied. |
273 | 283 | * @param notificationLatency The (approximate) time intervall between notifications sent to the delegate. |
274 | 284 | * @param ignoreEventsFromSubDirs Wheter events from sub-directories of the watched URLs should be ignored or not. |
275 | 285 | * @param exludeURLs An array of URLs that we should ignore events from. Pass <code>nil</code> if none should be excluded. |
276 | 286 | * @param streamCreationFlags The event stream creation flags. |
277 | - * @return An <code>CDEvents</code> object initialized with the given URLs to watch, URLs to exclude, wheter events from sub-directories are ignored or not and run on the given run loop. | |
287 | + * @return An CDEvents object initialized with the given URLs to watch, URLs to exclude, wheter events from sub-directories are ignored or not and run on the given run loop. | |
278 | 288 | * @throws NSInvalidArgumentException if the parameter URLs is empty or points to <code>nil</code>. |
279 | 289 | * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. |
280 | 290 | * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. |
281 | 291 | * |
282 | - * @see initWithURLs: | |
283 | - * @see initWithURLs:onRunLoop: | |
292 | + * @see initWithURLs:delegate: | |
293 | + * @see initWithURLs:delegate:onRunLoop: | |
284 | 294 | * @see ignoreEventsFromSubDirectories |
285 | 295 | * @see excludedURLs |
296 | + * @see CDEventsDelegate | |
286 | 297 | * @see FSEventStreamCreateFlags |
287 | 298 | * |
288 | 299 | * @discussion To ask for events "since now" pass the return value of |
289 | - * currentEventIdentifier as the parameter sinceEventIdentifier. | |
300 | + * currentEventIdentifier as the parameter <code>sinceEventIdentifier</code>. | |
290 | 301 | * CDEventStreamCreationFailureException should be extremely rare. |
291 | 302 | * |
292 | 303 | * @since 1.0.0 |
@@ -301,7 +312,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
301 | 312 | streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags; |
302 | 313 | |
303 | 314 | #pragma mark Flush methods |
304 | - | |
315 | +/** @name Flushing Events */ | |
305 | 316 | /** |
306 | 317 | * Flushes the event stream synchronously. |
307 | 318 | * |
@@ -325,6 +336,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
325 | 336 | - (void)flushAsynchronously; |
326 | 337 | |
327 | 338 | #pragma mark Misc methods |
339 | +/** @name Events Description */ | |
328 | 340 | /** |
329 | 341 | * Returns a NSString containing the description of the current event stream. |
330 | 342 | * |
@@ -13,12 +13,22 @@ | ||
13 | 13 | #pragma mark CDEvents custom exceptions |
14 | 14 | NSString *const CDEventsEventStreamCreationFailureException = @"CDEventsEventStreamCreationFailureException"; |
15 | 15 | |
16 | +#pragma - | |
17 | +#pragma mark Default values | |
18 | +const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags = | |
19 | + (kFSEventStreamCreateFlagUseCFTypes | | |
20 | + kFSEventStreamCreateFlagWatchRoot); | |
21 | + | |
22 | +const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | |
23 | + | |
16 | 24 | |
17 | 25 | #pragma mark - |
18 | 26 | #pragma mark Private API |
19 | 27 | // Private API |
20 | 28 | @interface CDEvents () |
21 | 29 | |
30 | +@property (retain, readwrite) CDEvent *lastEvent; | |
31 | + | |
22 | 32 | // The FSEvents callback function |
23 | 33 | static void CDEventsCallback( |
24 | 34 | ConstFSEventStreamRef streamRef, |
@@ -236,9 +246,11 @@ static void CDEventsCallback( | ||
236 | 246 | { |
237 | 247 | CDEvents *watcher = (CDEvents *)callbackCtxInfo; |
238 | 248 | |
239 | - NSArray *excludedURLs = [watcher excludedURLs]; | |
240 | - NSArray *eventPathsArray = (NSArray *)eventPaths; | |
241 | - BOOL shouldIgnore; | |
249 | + NSArray *watchedURLs = [watcher watchedURLs]; | |
250 | + NSArray *excludedURLs = [watcher excludedURLs]; | |
251 | + NSArray *eventPathsArray = (NSArray *)eventPaths; | |
252 | + BOOL shouldIgnore = NO; | |
253 | + CDEvent *lastEvent = nil; | |
242 | 254 | |
243 | 255 | for (NSUInteger i = 0; i < numEvents; ++i) { |
244 | 256 | shouldIgnore = NO; |
@@ -246,10 +258,19 @@ static void CDEventsCallback( | ||
246 | 258 | NSString *eventPath = [[eventPathsArray objectAtIndex:i] |
247 | 259 | stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; |
248 | 260 | NSURL *eventURL = [NSURL URLWithString:eventPath]; |
261 | + // We do this hackery to ensure that the eventPath string doesn't | |
262 | + // contain any trailing slash. | |
263 | + eventPath = [eventURL path]; | |
249 | 264 | |
250 | - if ([excludedURLs containsObject:eventURL]) { | |
265 | + if ([watcher ignoreEventsFromSubDirectories]) { | |
251 | 266 | shouldIgnore = YES; |
252 | - } else if (excludedURLs != nil && [watcher ignoreEventsFromSubDirectories]) { | |
267 | + for (NSURL *URL in watchedURLs) { | |
268 | + if ([[URL path] isEqualToString:eventPath]) { | |
269 | + shouldIgnore = NO; | |
270 | + break; | |
271 | + } | |
272 | + } | |
273 | + } else if (excludedURLs != nil) { | |
253 | 274 | for (NSURL *URL in excludedURLs) { |
254 | 275 | if ([eventPath hasPrefix:[URL path]]) { |
255 | 276 | shouldIgnore = YES; |
@@ -263,6 +284,9 @@ static void CDEventsCallback( | ||
263 | 284 | date:[NSDate date] |
264 | 285 | URL:eventURL |
265 | 286 | flags:eventFlags[i]]; |
287 | + // Dispose of old lastEvent and retain the currently last | |
288 | + [lastEvent release]; | |
289 | + lastEvent = [event retain]; | |
266 | 290 | |
267 | 291 | if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) { |
268 | 292 | [[watcher delegate] URLWatcher:watcher eventOccurred:event]; |
@@ -277,7 +301,10 @@ static void CDEventsCallback( | ||
277 | 301 | } |
278 | 302 | } |
279 | 303 | |
280 | - | |
304 | + if (lastEvent) { | |
305 | + [watcher setLastEvent:lastEvent]; | |
306 | + [lastEvent release]; | |
307 | + } | |
281 | 308 | } |
282 | 309 | |
283 | 310 | @end |
@@ -3,10 +3,11 @@ | ||
3 | 3 | archiveVersion = 1; |
4 | 4 | classes = { |
5 | 5 | }; |
6 | - objectVersion = 45; | |
6 | + objectVersion = 46; | |
7 | 7 | objects = { |
8 | 8 | |
9 | 9 | /* Begin PBXBuildFile section */ |
10 | + 6A05775A1400F49900BF73C4 /* compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A0577591400F49900BF73C4 /* compat.h */; }; | |
10 | 11 | 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; |
11 | 12 | 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6D03011166AFFA00343E46 /* CDEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; |
12 | 13 | 9C6D03041166AFFA00343E46 /* CDEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6D03021166AFFA00343E46 /* CDEvent.m */; }; |
@@ -50,6 +51,7 @@ | ||
50 | 51 | 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; |
51 | 52 | 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; }; |
52 | 53 | 32DBCF5E0370ADEE00C91783 /* CDEvents_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEvents_Prefix.pch; sourceTree = "<group>"; }; |
54 | + 6A0577591400F49900BF73C4 /* compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compat.h; sourceTree = "<group>"; }; | |
53 | 55 | 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
54 | 56 | 8DC2EF5B0486A6940098B216 /* CDEvents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CDEvents.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
55 | 57 | 9C6D03011166AFFA00343E46 /* CDEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEvent.h; sourceTree = "<group>"; }; |
@@ -163,6 +165,7 @@ | ||
163 | 165 | 32C88DFF0371C24200C91783 /* Other Sources */ = { |
164 | 166 | isa = PBXGroup; |
165 | 167 | children = ( |
168 | + 6A0577591400F49900BF73C4 /* compat.h */, | |
166 | 169 | 32DBCF5E0370ADEE00C91783 /* CDEvents_Prefix.pch */, |
167 | 170 | ); |
168 | 171 | name = "Other Sources"; |
@@ -188,6 +191,7 @@ | ||
188 | 191 | 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */, |
189 | 192 | 9C6D051D1166BD5800343E46 /* CDEventsDelegate.h in Headers */, |
190 | 193 | 9C6D05241166BF5300343E46 /* CDEvents.h in Headers */, |
194 | + 6A05775A1400F49900BF73C4 /* compat.h in Headers */, | |
191 | 195 | ); |
192 | 196 | runOnlyForDeploymentPostprocessing = 0; |
193 | 197 | }; |
@@ -237,9 +241,19 @@ | ||
237 | 241 | /* Begin PBXProject section */ |
238 | 242 | 0867D690FE84028FC02AAC07 /* Project object */ = { |
239 | 243 | isa = PBXProject; |
244 | + attributes = { | |
245 | + LastUpgradeCheck = 0420; | |
246 | + }; | |
240 | 247 | buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */; |
241 | - compatibilityVersion = "Xcode 3.1"; | |
248 | + compatibilityVersion = "Xcode 3.2"; | |
249 | + developmentRegion = English; | |
242 | 250 | hasScannedForEncodings = 1; |
251 | + knownRegions = ( | |
252 | + English, | |
253 | + Japanese, | |
254 | + French, | |
255 | + German, | |
256 | + ); | |
243 | 257 | mainGroup = 0867D691FE84028FC02AAC07 /* CDEvents */; |
244 | 258 | productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; |
245 | 259 | projectDirPath = ""; |
@@ -319,14 +333,12 @@ | ||
319 | 333 | DYLIB_CURRENT_VERSION = 1; |
320 | 334 | FRAMEWORK_VERSION = A; |
321 | 335 | GCC_DYNAMIC_NO_PIC = NO; |
322 | - GCC_ENABLE_FIX_AND_CONTINUE = YES; | |
323 | 336 | GCC_ENABLE_OBJC_GC = supported; |
324 | 337 | GCC_MODEL_TUNING = G5; |
325 | 338 | GCC_OPTIMIZATION_LEVEL = 0; |
326 | 339 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
327 | 340 | GCC_PREFIX_HEADER = CDEvents_Prefix.pch; |
328 | 341 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; |
329 | - GCC_VERSION = ""; | |
330 | 342 | INFOPLIST_FILE = Info.plist; |
331 | 343 | INSTALL_PATH = "@loader_path/../Frameworks"; |
332 | 344 | PRODUCT_NAME = CDEvents; |
@@ -347,7 +359,6 @@ | ||
347 | 359 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
348 | 360 | GCC_PREFIX_HEADER = CDEvents_Prefix.pch; |
349 | 361 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; |
350 | - GCC_VERSION = ""; | |
351 | 362 | INFOPLIST_FILE = Info.plist; |
352 | 363 | INSTALL_PATH = "@loader_path/../Frameworks"; |
353 | 364 | PRODUCT_NAME = CDEvents; |
@@ -364,13 +375,13 @@ | ||
364 | 375 | ); |
365 | 376 | GCC_C_LANGUAGE_STANDARD = gnu99; |
366 | 377 | GCC_OPTIMIZATION_LEVEL = 0; |
367 | - GCC_VERSION = ""; | |
378 | + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |
368 | 379 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
369 | 380 | GCC_WARN_UNUSED_VARIABLE = YES; |
381 | + MACOSX_DEPLOYMENT_TARGET = 10.5; | |
370 | 382 | ONLY_ACTIVE_ARCH = YES; |
371 | - PREBINDING = NO; | |
372 | 383 | RUN_CLANG_STATIC_ANALYZER = YES; |
373 | - SDKROOT = macosx10.5; | |
384 | + SDKROOT = macosx; | |
374 | 385 | }; |
375 | 386 | name = Debug; |
376 | 387 | }; |
@@ -382,12 +393,12 @@ | ||
382 | 393 | i386, |
383 | 394 | ); |
384 | 395 | GCC_C_LANGUAGE_STANDARD = gnu99; |
385 | - GCC_VERSION = ""; | |
396 | + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; | |
386 | 397 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
387 | 398 | GCC_WARN_UNUSED_VARIABLE = YES; |
388 | - PREBINDING = NO; | |
399 | + MACOSX_DEPLOYMENT_TARGET = 10.5; | |
389 | 400 | RUN_CLANG_STATIC_ANALYZER = YES; |
390 | - SDKROOT = macosx10.5; | |
401 | + SDKROOT = macosx; | |
391 | 402 | }; |
392 | 403 | name = Release; |
393 | 404 | }; |
@@ -397,8 +408,7 @@ | ||
397 | 408 | ALWAYS_SEARCH_USER_PATHS = NO; |
398 | 409 | COPY_PHASE_STRIP = NO; |
399 | 410 | GCC_DYNAMIC_NO_PIC = NO; |
400 | - GCC_ENABLE_FIX_AND_CONTINUE = YES; | |
401 | - GCC_ENABLE_OBJC_GC = supported; | |
411 | + GCC_ENABLE_OBJC_GC = unsupported; | |
402 | 412 | GCC_MODEL_TUNING = G5; |
403 | 413 | GCC_OPTIMIZATION_LEVEL = 0; |
404 | 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
@@ -406,13 +416,13 @@ | ||
406 | 416 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; |
407 | 417 | INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; |
408 | 418 | INSTALL_PATH = "$(HOME)/Applications"; |
419 | + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; | |
409 | 420 | OTHER_LDFLAGS = ( |
410 | 421 | "-framework", |
411 | 422 | Foundation, |
412 | 423 | "-framework", |
413 | 424 | AppKit, |
414 | 425 | ); |
415 | - PREBINDING = NO; | |
416 | 426 | PRODUCT_NAME = CDEventsTestApp; |
417 | 427 | }; |
418 | 428 | name = Debug; |
@@ -423,7 +433,6 @@ | ||
423 | 433 | ALWAYS_SEARCH_USER_PATHS = NO; |
424 | 434 | COPY_PHASE_STRIP = YES; |
425 | 435 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
426 | - GCC_ENABLE_FIX_AND_CONTINUE = NO; | |
427 | 436 | GCC_ENABLE_OBJC_GC = unsupported; |
428 | 437 | GCC_MODEL_TUNING = G5; |
429 | 438 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
@@ -431,13 +440,13 @@ | ||
431 | 440 | GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; |
432 | 441 | INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; |
433 | 442 | INSTALL_PATH = "$(HOME)/Applications"; |
443 | + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; | |
434 | 444 | OTHER_LDFLAGS = ( |
435 | 445 | "-framework", |
436 | 446 | Foundation, |
437 | 447 | "-framework", |
438 | 448 | AppKit, |
439 | 449 | ); |
440 | - PREBINDING = NO; | |
441 | 450 | PRODUCT_NAME = CDEventsTestApp; |
442 | 451 | ZERO_LINK = NO; |
443 | 452 | }; |
@@ -43,7 +43,7 @@ | ||
43 | 43 | * The CDEventsDelegate protocol defines the required methods implemented by delegates of CDEvents objects. |
44 | 44 | * |
45 | 45 | * @see CDEvents |
46 | - * @see CDevent | |
46 | + * @see CDEvent | |
47 | 47 | * |
48 | 48 | * @since 1.0.0 |
49 | 49 | */ |
@@ -57,7 +57,7 @@ | ||
57 | 57 | * @param event The event data. |
58 | 58 | * |
59 | 59 | * @see CDEvents |
60 | - * @see CDevent | |
60 | + * @see CDEvent | |
61 | 61 | * |
62 | 62 | * @discussion Conforming objects' implementation of this method will be called |
63 | 63 | * whenever an event occurs. The instance of CDEvents which received the event |
@@ -17,11 +17,11 @@ | ||
17 | 17 | <key>CFBundlePackageType</key> |
18 | 18 | <string>FMWK</string> |
19 | 19 | <key>CFBundleShortVersionString</key> |
20 | - <string>1.0</string> | |
20 | + <string>1.1.2</string> | |
21 | 21 | <key>CFBundleSignature</key> |
22 | 22 | <string>????</string> |
23 | 23 | <key>CFBundleVersion</key> |
24 | - <string>1.1.1</string> | |
24 | + <string>1.1.2</string> | |
25 | 25 | <key>NSPrincipalClass</key> |
26 | 26 | <string></string> |
27 | 27 | </dict> |
@@ -1,4 +1,4 @@ | ||
1 | -# CDEvents # | |
1 | +# CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # | |
2 | 2 | |
3 | 3 | ## What is this? ## |
4 | 4 | It's an Objective-C wrapper for Mac OS X's [FSEvents C API](http://developer.apple.com/mac/library/documentation/Darwin/Reference/FSEvents_Ref/FSEvents_h/index.html). Inspired and based upon the ([MIT-licensed](http://www.opensource.org/licenses/mit-license.php)) open source project [SCEvents](http://stuconnolly.com/projects/code/) created by [Stuart Connolly](http://stuconnolly.com/). |
@@ -7,11 +7,11 @@ It's an Objective-C wrapper for Mac OS X's [FSEvents C API](http://developer.app | ||
7 | 7 | Requires Mac OS X 10.5, since FSEvents were introduced in 10.5, and an Intel CPU. Supports both manual memory management and garbage collection. |
8 | 8 | |
9 | 9 | ## What differentiates CDEvents from SCEvents then? ## |
10 | -Not all that much but a litle. First of all all classes and protocols are prefixed with `CD` instead of `SC`, I hope that won't be to hard to remember? Secondly `CDEvent` (the event data wrapper-class) is immutable in contrast to `SCEvent` which is mutable. The next difference, which were the initial reason why I decided to rewrite `SCEvents`, is that the class `SCEvents`' is a singleton something `CDEvents` isn't. I couldn't find a good reason as to why `SCEvents` had been designed that way and for my project a "normal" non-singleton class would be and is better. | |
10 | +Not all that much but a few things differentiate the two. The (event data wrapper) class `CDEvent` is immutable in contrast to `SCEvent` which is mutable. The next difference, which were the initial reason why I decided to rewrite `SCEvents` is that the class `SCEvents`' is a singleton class, where's `CDEvents` is a "normal" class. I couldn't find a good reason as to why `SCEvents` had been designed that way and for my project a "normal" non-singleton class would be and is better. | |
11 | 11 | |
12 | 12 | Another difference between `CDEvents` and `SCEvents` is that `CDEvents` is available for both manual memory management and environments using garbage collection. |
13 | 13 | |
14 | -So I've written some of the code from scratch and "taken" some from `SCEvents`. | |
14 | +So I've written some of the code from scratch and "borrowed" some from `SCEvents`. | |
15 | 15 | |
16 | 16 | ## API documentation ## |
17 | 17 | You can generate API documentation with the help of [Doxygen](http://www.stack.nl/~dimitri/doxygen/). In Doxygen open the file `api.doxygen`, click the `Run` tab and then the `Run doxygen` button. When it's done you should have a directory (ignored by git) in the root of the project named `api` with a sub-directory `html` in which you will find `index.html` double-click and enjoy. |
@@ -31,20 +31,53 @@ | ||
31 | 31 | #import <CDEvents/CDEvents.h> |
32 | 32 | |
33 | 33 | |
34 | +bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) | |
35 | +{ | |
36 | + static SInt32 versionMajor = 0, versionMinor = 0; | |
37 | + | |
38 | + if (versionMajor == 0) { | |
39 | + Gestalt(gestaltSystemVersionMajor, &versionMajor); | |
40 | + } | |
41 | + | |
42 | + if (versionMinor == 0) { | |
43 | + Gestalt(gestaltSystemVersionMinor, &versionMinor); | |
44 | + } | |
45 | + | |
46 | + return ((versionMajor > major) || | |
47 | + ((versionMajor == major) && (versionMinor >= minor))); | |
48 | +} | |
49 | + | |
50 | + | |
34 | 51 | @implementation CDEventsTestAppController |
35 | 52 | |
36 | 53 | - (void)run |
37 | -{ | |
54 | +{ | |
38 | 55 | NSArray *watchedURLs = [NSArray arrayWithObject: |
39 | 56 | [NSURL URLWithString:[NSHomeDirectory() |
40 | 57 | stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; |
41 | 58 | NSArray *excludeURLs = [NSMutableArray arrayWithObject: |
42 | - [[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"] | |
43 | - stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; | |
59 | + [NSURL URLWithString:[[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"] | |
60 | + stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]; | |
44 | 61 | |
62 | + CDEventsEventStreamCreationFlags creationFlags = kCDEventsDefaultEventStreamFlags; | |
63 | + | |
64 | + if (systemVersionIsAtLeast(10,6)) { | |
65 | + creationFlags |= kFSEventStreamCreateFlagIgnoreSelf; | |
66 | + } | |
67 | + | |
68 | + if (systemVersionIsAtLeast(10,7)) { | |
69 | + creationFlags |= kFSEventStreamCreateFlagFileEvents; | |
70 | + } | |
71 | + | |
45 | 72 | _events = [[CDEvents alloc] initWithURLs:watchedURLs |
46 | - delegate:self]; | |
47 | - [_events setExcludedURLs:excludeURLs]; | |
73 | + delegate:self | |
74 | + onRunLoop:[NSRunLoop currentRunLoop] | |
75 | + sinceEventIdentifier:kCDEventsSinceEventNow | |
76 | + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY | |
77 | + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS | |
78 | + excludeURLs:excludeURLs | |
79 | + streamCreationFlags:creationFlags]; | |
80 | + //[_events setIgnoreEventsFromSubDirectories:YES]; | |
48 | 81 | |
49 | 82 | NSLog(@"-[CDEventsTestAppController run]:\n%@\n------\n%@", |
50 | 83 | _events, |
@@ -0,0 +1,32 @@ | ||
1 | +/** | |
2 | + * @headerfile compat.h | |
3 | + * FSEventStream flag compatibility shim | |
4 | + * | |
5 | + * In order to compile a binary against an older SDK yet still support the | |
6 | + * features present in later OS releases, we need to define any missing enum | |
7 | + * constants not present in the older SDK. This allows us to safely defer | |
8 | + * feature detection to runtime (and avoid recompilation). | |
9 | + */ | |
10 | + | |
11 | +#import <CoreServices/CoreServices.h> | |
12 | + | |
13 | +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060 | |
14 | +// ignoring events originating from the current process introduced in 10.6 | |
15 | +FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf = 0x00000008; | |
16 | +#endif | |
17 | + | |
18 | +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 | |
19 | +// file-level events introduced in 10.7 | |
20 | +FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents = 0x00000010; | |
21 | +FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated = 0x00000100, | |
22 | + kFSEventStreamEventFlagItemRemoved = 0x00000200, | |
23 | + kFSEventStreamEventFlagItemInodeMetaMod = 0x00000400, | |
24 | + kFSEventStreamEventFlagItemRenamed = 0x00000800, | |
25 | + kFSEventStreamEventFlagItemModified = 0x00001000, | |
26 | + kFSEventStreamEventFlagItemFinderInfoMod = 0x00002000, | |
27 | + kFSEventStreamEventFlagItemChangeOwner = 0x00004000, | |
28 | + kFSEventStreamEventFlagItemXattrMod = 0x00008000, | |
29 | + kFSEventStreamEventFlagItemIsFile = 0x00010000, | |
30 | + kFSEventStreamEventFlagItemIsDir = 0x00020000, | |
31 | + kFSEventStreamEventFlagItemIsSymlink = 0x00040000; | |
32 | +#endif |