• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

An Objective-C wrapper for Mac OS X’s FSEvents C API.


Commit MetaInfo

修订版d560344d1039c2091252717eb870a45dc81ed1dc (tree)
时间2011-10-25 02:34:06
作者Aron Cedercrantz <aron@cede...>
CommiterAron Cedercrantz

Log Message

Merge branch 'release/1.1.2'

* release/1.1.2: (21 commits)

Bumb version to 1.1.2.
Fix lastEvent not getting set.
compatibility shim, runtime checking example, file-level events ---------------------------------------------------------------
validate project settings, update to xcode 3.2
Fixed "missing base SDK".
Fixed a bug in the CDEventsCallback(...) code which could cause the excludedURLs to be disregarded.
Changed the lastEvent property of the CDEvents class to readonly in public and readwrite in private.
Fixed a bug in the test app which could cause an exception to be raised.
Fixed a lot of small formatting and cross reference errors in the API doc.
Fixed a dup symbols bug properly, thanks to Kirk Kerekes.
Defined MACOSX_DEPLOYMENT_TARGET to 10.5.
Added some Xcode 4 stuff to the git ignore file.
Revert "Changed two "const <type> <name>" constants to macros (they caused duplicate symbol linking errors when the header was included more than once for the same product)."
Fixed small markdown error.
Added still maintained image.
Changed two "const <type> <name>" constants to macros (they caused duplicate symbol linking errors when the header was included more than once for the same product).
Changed test application to use full CDEvents init method.
Fixed missing weak code mark in the delegate property declaration.
Changed the compiler to LLVM 1.5.
Marked CDEventsDelegate pointer as a weak pointer (for GC).
...

Conflicts:
CDEvents.xcodeproj/project.pbxproj

更改概述

差异

--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,13 @@
1+.svn
2+
3+*.swp
4+*.o
5+*.lo
6+.libs
7+*.la
8+
9+.DS_Store
10+
111 build
212
313 *.perspectivev3
@@ -6,6 +16,8 @@ build
616 *.mode1v3
717 *.mode2v3
818 *.tm_build_errors
19+*.xcodeproj/xcuserdata
20+*.xcodeproj/project.xcworkspace
921 !default.pbxuser
1022 !default.perspectivev3
1123 !default.mode1v3
@@ -14,6 +26,4 @@ build
1426 *~.nib
1527 *~.xib
1628
17-.DS_Store
18-
1929 api
--- a/CDEvent.h
+++ b/CDEvent.h
@@ -38,7 +38,6 @@
3838 #import <Foundation/Foundation.h>
3939 #import <CoreServices/CoreServices.h>
4040
41-
4241 #pragma mark -
4342 #pragma mark CDEvent types
4443 /**
@@ -77,6 +76,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
7776 }
7877
7978 #pragma mark Properties
79+/** @name Getting Event Properties */
8080 /**
8181 * The event identifier.
8282 *
@@ -106,6 +106,8 @@ typedef FSEventStreamEventFlags CDEventFlags;
106106 */
107107 @property (readonly) NSURL *URL;
108108
109+
110+/** @name Getting Event Flags */
109111 /**
110112 * The flags of the event.
111113 *
@@ -119,18 +121,26 @@ typedef FSEventStreamEventFlags CDEventFlags;
119121 */
120122 @property (readonly) CDEventFlags flags;
121123
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+
122132 #pragma mark Specific flag properties
123133 /**
124134 * Wheter there was some change in the directory at the specific path supplied in this event.
125135 *
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>.
127137 *
128138 * @see kFSEventStreamEventFlagNone
129139 * @see flags
130140 * @see mustRescanSubDirectories
131141 * @see isUserDropped
132142 * @see isKernelDropped
133- * @see isEventIdsWrapped
143+ * @see isEventIdentifiersWrapped
134144 * @see isHistoryDone
135145 * @see isRootChanged
136146 * @see didVolumeMount
@@ -148,19 +158,19 @@ typedef FSEventStreamEventFlags CDEventFlags;
148158 * events were coalesced hierarchically. For example, an event in
149159 * <code>/Users/jsmith/Music</code> and an event in
150160 * <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
152162 * you may be able to get an idea of whether the bottleneck happened in the
153163 * 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>.
155165 *
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>.
157167 *
158168 * @see kFSEventStreamEventFlagMustScanSubDirs
159169 * @see flags
160170 * @see isGenericChange
161171 * @see isUserDropped
162172 * @see isKernelDropped
163- * @see isEventIdsWrapped
173+ * @see isEventIdentifiersWrapped
164174 * @see isHistoryDone
165175 * @see isRootChanged
166176 * @see didVolumeMount
@@ -173,14 +183,14 @@ typedef FSEventStreamEventFlags CDEventFlags;
173183 /**
174184 * Provides some information as to what might have caused the need to rescan the URL including its children.
175185 *
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>.
177187 *
178188 * @see kFSEventStreamEventFlagUserDropped
179189 * @see flags
180190 * @see isGenericChange
181191 * @see mustRescanSubDirectories
182192 * @see isKernelDropped
183- * @see isEventIdsWrapped
193+ * @see isEventIdentifiersWrapped
184194 * @see isHistoryDone
185195 * @see isRootChanged
186196 * @see didVolumeMount
@@ -193,14 +203,14 @@ typedef FSEventStreamEventFlags CDEventFlags;
193203 /**
194204 * Provides some information as to what might have caused the need to rescan the URL including its children.
195205 *
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>.
197207 *
198208 * @see kFSEventStreamEventFlagKernelDropped
199209 * @see flags
200210 * @see isGenericChange
201211 * @see mustRescanSubDirectories
202212 * @see isUserDropped
203- * @see isEventIdsWrapped
213+ * @see isEventIdentifiersWrapped
204214 * @see isHistoryDone
205215 * @see isRootChanged
206216 * @see didVolumeMount
@@ -217,7 +227,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
217227 * previously-issued event identifiers are no longer valid arguments for the
218228 * sinceEventIdentifier parameter of the CDEvents init methods.
219229 *
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>.
221231 *
222232 * @see kFSEventStreamEventFlagEventIdsWrapped
223233 * @see flags
@@ -241,7 +251,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
241251 * as a result of specifying a <i>sinceEventIdentifier</i> argument other than
242252 * kCDEventsSinceEventNow with the CDEvents init methods.
243253 *
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>.
245255 *
246256 * @see kFSEventStreamEventFlagHistoryDone
247257 * @see flags
@@ -249,7 +259,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
249259 * @see mustRescanSubDirectories
250260 * @see isUserDropped
251261 * @see isKernelDropped
252- * @see isEventIdsWrapped
262+ * @see isEventIdentifiersWrapped
253263 * @see isRootChanged
254264 * @see didVolumeMount
255265 * @see didVolumeUnmount
@@ -271,7 +281,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
271281 * with this flag set will only be sent if you passed the flag
272282 * <code>kFSEventStreamCreateFlagWatchRoot</code> to the CDEvents.
273283 *
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>.
275285 *
276286 * @see kFSEventStreamEventFlagRootChanged
277287 * @see flags
@@ -279,7 +289,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
279289 * @see mustRescanSubDirectories
280290 * @see isUserDropped
281291 * @see isKernelDropped
282- * @see isEventIdsWrapped
292+ * @see isEventIdentifiersWrapped
283293 * @see isHistoryDone
284294 * @see didVolumeMount
285295 * @see didVolumeUnmount
@@ -304,7 +314,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
304314 * Also be aware of the <code>MNT_DONTBROWSE</code> flag that is set for volumes
305315 * which should not be displayed by user interface elements.
306316 *
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>.
308318 *
309319 * @see kFSEventStreamEventFlagMount
310320 * @see flags
@@ -312,7 +322,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
312322 * @see mustRescanSubDirectories
313323 * @see isUserDropped
314324 * @see isKernelDropped
315- * @see isEventIdsWrapped
325+ * @see isEventIdentifiersWrapped
316326 * @see isHistoryDone
317327 * @see isRootChanged
318328 * @see didVolumeUnmount
@@ -333,7 +343,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
333343 * could uncover an arbitrarily large directory hierarchy, although Mac OS X
334344 * never does that.
335345 *
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>.
337347 *
338348 * @see kFSEventStreamEventFlagUnmount
339349 * @see flags
@@ -341,7 +351,7 @@ typedef FSEventStreamEventFlags CDEventFlags;
341351 * @see mustRescanSubDirectories
342352 * @see isUserDropped
343353 * @see isKernelDropped
344- * @see isEventIdsWrapped
354+ * @see isEventIdentifiersWrapped
345355 * @see isHistoryDone
346356 * @see isRootChanged
347357 * @see didVolumeMount
@@ -351,8 +361,26 @@ typedef FSEventStreamEventFlags CDEventFlags;
351361 @property (readonly) BOOL didVolumeUnmount;
352362
353363
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;
355381
382+#pragma mark Class object creators
383+/** @name Creating CDEvent Objects */
356384 /**
357385 * Returns an <code>CDEvent</code> created with the given identifier, date, URL and flags.
358386 *
--- a/CDEvent.m
+++ b/CDEvent.m
@@ -27,7 +27,7 @@
2727 */
2828
2929 #import "CDEvent.h"
30-
30+#import "compat.h"
3131
3232 @implementation CDEvent
3333
@@ -104,52 +104,33 @@
104104 return [self retain];
105105 }
106106
107-
108107 #pragma mark Specific flag properties
109108 - (BOOL)isGenericChange
110109 {
111110 return (kFSEventStreamEventFlagNone == _flags);
112111 }
113112
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)
153134
154135 #pragma mark Misc
155136 - (NSString *)description
--- a/CDEvents.h
+++ b/CDEvents.h
@@ -70,7 +70,7 @@ extern NSString *const CDEventsEventStreamCreationFailureException;
7070 *
7171 * @since 1.0.0
7272 */
73-#define CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY (NSTimeInterval)3.0
73+#define CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY ((NSTimeInterval)3.0)
7474
7575 /**
7676 * The default value wheter events from sub directories should be ignored or not.
@@ -84,16 +84,14 @@ extern NSString *const CDEventsEventStreamCreationFailureException;
8484 *
8585 * @since 1.0.0
8686 */
87-const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags =
88- (kFSEventStreamCreateFlagUseCFTypes |
89- kFSEventStreamCreateFlagWatchRoot);
87+extern const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags;
9088
9189 /**
9290 * Use this to get all event since now when initializing a CDEvents object.
9391 *
9492 * @since 1.1.0
9593 */
96-const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
94+extern const CDEventIdentifier kCDEventsSinceEventNow;
9795
9896
9997 #pragma mark -
@@ -109,7 +107,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
109107 */
110108 @interface CDEvents : NSObject <NSCopying> {
111109 @private
112- id<CDEventsDelegate> _delegate;
110+ __weak id<CDEventsDelegate> _delegate;
113111
114112 FSEventStreamRef _eventStream;
115113 CFTimeInterval _notificationLatency;
@@ -126,16 +124,20 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
126124 }
127125
128126 #pragma mark Properties
127+/** @name Managing the Delegate */
129128 /**
130129 * The delegate object the <code>CDEvents</code> object calls when it recieves an event.
131130 *
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.
133132 * @return The events's delegate.
134133 *
134+ * @see CDEventsDelegate
135+ *
135136 * @since 1.0.0
136137 */
137-@property (assign) id<CDEventsDelegate> delegate;
138+@property (assign) __weak id<CDEventsDelegate> delegate;
138139
140+/** @name Getting Event Watcher Properties */
139141 /**
140142 * The (approximate) time intervall between notifications sent to the delegate.
141143 *
@@ -143,7 +145,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
143145 *
144146 * @since 1.0.0
145147 */
146-@property (readonly) CFTimeInterval notificationLatency;
148+@property (readonly) CFTimeInterval notificationLatency;
147149
148150 /**
149151 * The event identifier from which events will be supplied to the delegate.
@@ -152,17 +154,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
152154 *
153155 * @since 1.0.0
154156 */
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;
166158
167159 /**
168160 * The last event that occured and thas has been delivered to the delegate.
@@ -171,7 +163,7 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
171163 *
172164 * @since 1.0.0
173165 */
174-@property (retain) CDEvent *lastEvent;
166+@property (retain, readonly) CDEvent *lastEvent;
175167
176168 /**
177169 * The URLs that we watch for events.
@@ -180,8 +172,10 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
180172 *
181173 * @since 1.0.0
182174 */
183-@property (readonly) NSArray *watchedURLs;
175+@property (readonly) NSArray *watchedURLs;
184176
177+
178+/** @name Configuring the Event watcher */
185179 /**
186180 * The URLs that we should ignore events from.
187181 *
@@ -190,10 +184,21 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
190184 *
191185 * @since 1.0.0
192186 */
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;
194198
195199
196200 #pragma mark Event identifier class methods
201+/** @name Current Event Identifier */
197202 /**
198203 * The current event identifier.
199204 *
@@ -207,28 +212,30 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
207212
208213
209214 #pragma mark Init methods
215+/** @name Creating CDEvents Objects */
210216 /**
211217 * Returns an <code>CDEvents</code> object initialized with the given URLs to watch.
212218 *
213219 * @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.
216222 * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>.
217223 * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>.
218224 * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream.
219225 *
220226 * @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
222229 * @see kCDEventsDefaultEventStreamFlags
223230 * @see kCDEventsSinceEventNow
224231 *
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.
232239 *
233240 * @since 1.0.0
234241 */
@@ -238,24 +245,25 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
238245 * Returns an <code>CDEvents</code> object initialized with the given URLs to watch and schedules the watcher on the given run loop.
239246 *
240247 * @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.
244251 * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>.
245252 * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>.
246253 * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream.
247254 *
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
250258 * @see kCDEventsDefaultEventStreamFlags
251259 * @see kCDEventsSinceEventNow
252260 *
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>.
259267 *
260268 * @since 1.0.0
261269 */
@@ -263,30 +271,33 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
263271 delegate:(id<CDEventsDelegate>)delegate
264272 onRunLoop:(NSRunLoop *)runLoop;
265273
274+
275+
266276 /**
267277 * 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.
268278 *
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.
271281 * @param runLoop The run loop which the which the watcher should be schedueled on.
272282 * @param sinceEventIdentifier Events that have happened after the given event identifier will be supplied.
273283 * @param notificationLatency The (approximate) time intervall between notifications sent to the delegate.
274284 * @param ignoreEventsFromSubDirs Wheter events from sub-directories of the watched URLs should be ignored or not.
275285 * @param exludeURLs An array of URLs that we should ignore events from. Pass <code>nil</code> if none should be excluded.
276286 * @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.
278288 * @throws NSInvalidArgumentException if the parameter URLs is empty or points to <code>nil</code>.
279289 * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>.
280290 * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream.
281291 *
282- * @see initWithURLs:
283- * @see initWithURLs:onRunLoop:
292+ * @see initWithURLs:delegate:
293+ * @see initWithURLs:delegate:onRunLoop:
284294 * @see ignoreEventsFromSubDirectories
285295 * @see excludedURLs
296+ * @see CDEventsDelegate
286297 * @see FSEventStreamCreateFlags
287298 *
288299 * @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>.
290301 * CDEventStreamCreationFailureException should be extremely rare.
291302 *
292303 * @since 1.0.0
@@ -301,7 +312,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs
301312 streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags;
302313
303314 #pragma mark Flush methods
304-
315+/** @name Flushing Events */
305316 /**
306317 * Flushes the event stream synchronously.
307318 *
@@ -325,6 +336,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs
325336 - (void)flushAsynchronously;
326337
327338 #pragma mark Misc methods
339+/** @name Events Description */
328340 /**
329341 * Returns a NSString containing the description of the current event stream.
330342 *
--- a/CDEvents.m
+++ b/CDEvents.m
@@ -13,12 +13,22 @@
1313 #pragma mark CDEvents custom exceptions
1414 NSString *const CDEventsEventStreamCreationFailureException = @"CDEventsEventStreamCreationFailureException";
1515
16+#pragma -
17+#pragma mark Default values
18+const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags =
19+ (kFSEventStreamCreateFlagUseCFTypes |
20+ kFSEventStreamCreateFlagWatchRoot);
21+
22+const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow;
23+
1624
1725 #pragma mark -
1826 #pragma mark Private API
1927 // Private API
2028 @interface CDEvents ()
2129
30+@property (retain, readwrite) CDEvent *lastEvent;
31+
2232 // The FSEvents callback function
2333 static void CDEventsCallback(
2434 ConstFSEventStreamRef streamRef,
@@ -236,9 +246,11 @@ static void CDEventsCallback(
236246 {
237247 CDEvents *watcher = (CDEvents *)callbackCtxInfo;
238248
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;
242254
243255 for (NSUInteger i = 0; i < numEvents; ++i) {
244256 shouldIgnore = NO;
@@ -246,10 +258,19 @@ static void CDEventsCallback(
246258 NSString *eventPath = [[eventPathsArray objectAtIndex:i]
247259 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
248260 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];
249264
250- if ([excludedURLs containsObject:eventURL]) {
265+ if ([watcher ignoreEventsFromSubDirectories]) {
251266 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) {
253274 for (NSURL *URL in excludedURLs) {
254275 if ([eventPath hasPrefix:[URL path]]) {
255276 shouldIgnore = YES;
@@ -263,6 +284,9 @@ static void CDEventsCallback(
263284 date:[NSDate date]
264285 URL:eventURL
265286 flags:eventFlags[i]];
287+ // Dispose of old lastEvent and retain the currently last
288+ [lastEvent release];
289+ lastEvent = [event retain];
266290
267291 if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) {
268292 [[watcher delegate] URLWatcher:watcher eventOccurred:event];
@@ -277,7 +301,10 @@ static void CDEventsCallback(
277301 }
278302 }
279303
280-
304+ if (lastEvent) {
305+ [watcher setLastEvent:lastEvent];
306+ [lastEvent release];
307+ }
281308 }
282309
283310 @end
--- a/CDEvents.xcodeproj/project.pbxproj
+++ b/CDEvents.xcodeproj/project.pbxproj
@@ -3,10 +3,11 @@
33 archiveVersion = 1;
44 classes = {
55 };
6- objectVersion = 45;
6+ objectVersion = 46;
77 objects = {
88
99 /* Begin PBXBuildFile section */
10+ 6A05775A1400F49900BF73C4 /* compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A0577591400F49900BF73C4 /* compat.h */; };
1011 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
1112 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C6D03011166AFFA00343E46 /* CDEvent.h */; settings = {ATTRIBUTES = (Public, ); }; };
1213 9C6D03041166AFFA00343E46 /* CDEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6D03021166AFFA00343E46 /* CDEvent.m */; };
@@ -50,6 +51,7 @@
5051 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5152 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
5253 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>"; };
5355 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5456 8DC2EF5B0486A6940098B216 /* CDEvents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CDEvents.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5557 9C6D03011166AFFA00343E46 /* CDEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDEvent.h; sourceTree = "<group>"; };
@@ -163,6 +165,7 @@
163165 32C88DFF0371C24200C91783 /* Other Sources */ = {
164166 isa = PBXGroup;
165167 children = (
168+ 6A0577591400F49900BF73C4 /* compat.h */,
166169 32DBCF5E0370ADEE00C91783 /* CDEvents_Prefix.pch */,
167170 );
168171 name = "Other Sources";
@@ -188,6 +191,7 @@
188191 9C6D03031166AFFA00343E46 /* CDEvent.h in Headers */,
189192 9C6D051D1166BD5800343E46 /* CDEventsDelegate.h in Headers */,
190193 9C6D05241166BF5300343E46 /* CDEvents.h in Headers */,
194+ 6A05775A1400F49900BF73C4 /* compat.h in Headers */,
191195 );
192196 runOnlyForDeploymentPostprocessing = 0;
193197 };
@@ -237,9 +241,19 @@
237241 /* Begin PBXProject section */
238242 0867D690FE84028FC02AAC07 /* Project object */ = {
239243 isa = PBXProject;
244+ attributes = {
245+ LastUpgradeCheck = 0420;
246+ };
240247 buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */;
241- compatibilityVersion = "Xcode 3.1";
248+ compatibilityVersion = "Xcode 3.2";
249+ developmentRegion = English;
242250 hasScannedForEncodings = 1;
251+ knownRegions = (
252+ English,
253+ Japanese,
254+ French,
255+ German,
256+ );
243257 mainGroup = 0867D691FE84028FC02AAC07 /* CDEvents */;
244258 productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
245259 projectDirPath = "";
@@ -319,14 +333,12 @@
319333 DYLIB_CURRENT_VERSION = 1;
320334 FRAMEWORK_VERSION = A;
321335 GCC_DYNAMIC_NO_PIC = NO;
322- GCC_ENABLE_FIX_AND_CONTINUE = YES;
323336 GCC_ENABLE_OBJC_GC = supported;
324337 GCC_MODEL_TUNING = G5;
325338 GCC_OPTIMIZATION_LEVEL = 0;
326339 GCC_PRECOMPILE_PREFIX_HEADER = YES;
327340 GCC_PREFIX_HEADER = CDEvents_Prefix.pch;
328341 GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64;
329- GCC_VERSION = "";
330342 INFOPLIST_FILE = Info.plist;
331343 INSTALL_PATH = "@loader_path/../Frameworks";
332344 PRODUCT_NAME = CDEvents;
@@ -347,7 +359,6 @@
347359 GCC_PRECOMPILE_PREFIX_HEADER = YES;
348360 GCC_PREFIX_HEADER = CDEvents_Prefix.pch;
349361 GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64;
350- GCC_VERSION = "";
351362 INFOPLIST_FILE = Info.plist;
352363 INSTALL_PATH = "@loader_path/../Frameworks";
353364 PRODUCT_NAME = CDEvents;
@@ -364,13 +375,13 @@
364375 );
365376 GCC_C_LANGUAGE_STANDARD = gnu99;
366377 GCC_OPTIMIZATION_LEVEL = 0;
367- GCC_VERSION = "";
378+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
368379 GCC_WARN_ABOUT_RETURN_TYPE = YES;
369380 GCC_WARN_UNUSED_VARIABLE = YES;
381+ MACOSX_DEPLOYMENT_TARGET = 10.5;
370382 ONLY_ACTIVE_ARCH = YES;
371- PREBINDING = NO;
372383 RUN_CLANG_STATIC_ANALYZER = YES;
373- SDKROOT = macosx10.5;
384+ SDKROOT = macosx;
374385 };
375386 name = Debug;
376387 };
@@ -382,12 +393,12 @@
382393 i386,
383394 );
384395 GCC_C_LANGUAGE_STANDARD = gnu99;
385- GCC_VERSION = "";
396+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
386397 GCC_WARN_ABOUT_RETURN_TYPE = YES;
387398 GCC_WARN_UNUSED_VARIABLE = YES;
388- PREBINDING = NO;
399+ MACOSX_DEPLOYMENT_TARGET = 10.5;
389400 RUN_CLANG_STATIC_ANALYZER = YES;
390- SDKROOT = macosx10.5;
401+ SDKROOT = macosx;
391402 };
392403 name = Release;
393404 };
@@ -397,8 +408,7 @@
397408 ALWAYS_SEARCH_USER_PATHS = NO;
398409 COPY_PHASE_STRIP = NO;
399410 GCC_DYNAMIC_NO_PIC = NO;
400- GCC_ENABLE_FIX_AND_CONTINUE = YES;
401- GCC_ENABLE_OBJC_GC = supported;
411+ GCC_ENABLE_OBJC_GC = unsupported;
402412 GCC_MODEL_TUNING = G5;
403413 GCC_OPTIMIZATION_LEVEL = 0;
404414 GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -406,13 +416,13 @@
406416 GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64;
407417 INFOPLIST_FILE = "CDEventsTestApp-Info.plist";
408418 INSTALL_PATH = "$(HOME)/Applications";
419+ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
409420 OTHER_LDFLAGS = (
410421 "-framework",
411422 Foundation,
412423 "-framework",
413424 AppKit,
414425 );
415- PREBINDING = NO;
416426 PRODUCT_NAME = CDEventsTestApp;
417427 };
418428 name = Debug;
@@ -423,7 +433,6 @@
423433 ALWAYS_SEARCH_USER_PATHS = NO;
424434 COPY_PHASE_STRIP = YES;
425435 DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
426- GCC_ENABLE_FIX_AND_CONTINUE = NO;
427436 GCC_ENABLE_OBJC_GC = unsupported;
428437 GCC_MODEL_TUNING = G5;
429438 GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -431,13 +440,13 @@
431440 GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64;
432441 INFOPLIST_FILE = "CDEventsTestApp-Info.plist";
433442 INSTALL_PATH = "$(HOME)/Applications";
443+ LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
434444 OTHER_LDFLAGS = (
435445 "-framework",
436446 Foundation,
437447 "-framework",
438448 AppKit,
439449 );
440- PREBINDING = NO;
441450 PRODUCT_NAME = CDEventsTestApp;
442451 ZERO_LINK = NO;
443452 };
--- a/CDEventsDelegate.h
+++ b/CDEventsDelegate.h
@@ -43,7 +43,7 @@
4343 * The CDEventsDelegate protocol defines the required methods implemented by delegates of CDEvents objects.
4444 *
4545 * @see CDEvents
46- * @see CDevent
46+ * @see CDEvent
4747 *
4848 * @since 1.0.0
4949 */
@@ -57,7 +57,7 @@
5757 * @param event The event data.
5858 *
5959 * @see CDEvents
60- * @see CDevent
60+ * @see CDEvent
6161 *
6262 * @discussion Conforming objects' implementation of this method will be called
6363 * whenever an event occurs. The instance of CDEvents which received the event
--- a/Info.plist
+++ b/Info.plist
@@ -17,11 +17,11 @@
1717 <key>CFBundlePackageType</key>
1818 <string>FMWK</string>
1919 <key>CFBundleShortVersionString</key>
20- <string>1.0</string>
20+ <string>1.1.2</string>
2121 <key>CFBundleSignature</key>
2222 <string>????</string>
2323 <key>CFBundleVersion</key>
24- <string>1.1.1</string>
24+ <string>1.1.2</string>
2525 <key>NSPrincipalClass</key>
2626 <string></string>
2727 </dict>
--- a/README.mdown
+++ b/README.mdown
@@ -1,4 +1,4 @@
1-# CDEvents #
1+# CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) #
22
33 ## What is this? ##
44 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
77 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.
88
99 ## 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.
1111
1212 Another difference between `CDEvents` and `SCEvents` is that `CDEvents` is available for both manual memory management and environments using garbage collection.
1313
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`.
1515
1616 ## API documentation ##
1717 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.
--- a/TestApp/CDEventsTestAppController.m
+++ b/TestApp/CDEventsTestAppController.m
@@ -31,20 +31,53 @@
3131 #import <CDEvents/CDEvents.h>
3232
3333
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+
3451 @implementation CDEventsTestAppController
3552
3653 - (void)run
37-{
54+{
3855 NSArray *watchedURLs = [NSArray arrayWithObject:
3956 [NSURL URLWithString:[NSHomeDirectory()
4057 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
4158 NSArray *excludeURLs = [NSMutableArray arrayWithObject:
42- [[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"]
43- stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
59+ [NSURL URLWithString:[[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"]
60+ stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
4461
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+
4572 _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];
4881
4982 NSLog(@"-[CDEventsTestAppController run]:\n%@\n------\n%@",
5083 _events,
--- /dev/null
+++ b/compat.h
@@ -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