An Objective-C wrapper for Mac OS X’s FSEvents C API.
Revision | 4eaf17a300a4cb461aeee7d4039480e9ca07892c (tree) |
---|---|
Time | 2013-07-03 04:43:35 |
Author | Aron Cedercrantz <aron@cede...> |
Commiter | Aron Cedercrantz |
Merge tag '1.2.0'
1.2.0 - Requires ARC and blocks. Does not support GC.
* tag '1.2.0': (32 commits)
@@ -1,3 +1,2 @@ | ||
1 | -*.pbxproj binary | |
2 | 1 | *.m diff=objc |
3 | 2 | *.mm diff=objc |
@@ -27,3 +27,4 @@ build | ||
27 | 27 | *~.xib |
28 | 28 | |
29 | 29 | api |
30 | +docs |
@@ -1,7 +1,7 @@ | ||
1 | 1 | /** |
2 | 2 | * CDEvents |
3 | 3 | * |
4 | - * Copyright (c) 2010 Aron Cedercrantz | |
4 | + * Copyright (c) 2010-2012 Aron Cedercrantz | |
5 | 5 | * http://github.com/rastersize/CDEvents/ |
6 | 6 | * |
7 | 7 | * Permission is hereby granted, free of charge, to any person |
@@ -67,13 +67,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
67 | 67 | * |
68 | 68 | * @since 1.0.0 |
69 | 69 | */ |
70 | -@interface CDEvent : NSObject <NSCoding, NSCopying> { | |
71 | -@private | |
72 | - CDEventIdentifier _identifier; | |
73 | - NSDate *_date; | |
74 | - NSURL *_URL; | |
75 | - CDEventFlags _flags; | |
76 | -} | |
70 | +@interface CDEvent : NSObject <NSCoding, NSCopying> {} | |
77 | 71 | |
78 | 72 | #pragma mark Properties |
79 | 73 | /** @name Getting Event Properties */ |
@@ -95,7 +89,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
95 | 89 | * |
96 | 90 | * @since 1.0.0 |
97 | 91 | */ |
98 | -@property (readonly) NSDate *date; | |
92 | +@property (unsafe_unretained, readonly) NSDate *date; | |
99 | 93 | |
100 | 94 | /** |
101 | 95 | * The URL of the item which changed. |
@@ -104,7 +98,7 @@ typedef FSEventStreamEventFlags CDEventFlags; | ||
104 | 98 | * |
105 | 99 | * @since 1.0.0 |
106 | 100 | */ |
107 | -@property (readonly) NSURL *URL; | |
101 | +@property (unsafe_unretained, readonly) NSURL *URL; | |
108 | 102 | |
109 | 103 | |
110 | 104 | /** @name Getting Event Flags */ |
@@ -1,7 +1,7 @@ | ||
1 | 1 | /** |
2 | 2 | * CDEvents |
3 | 3 | * |
4 | - * Copyright (c) 2010 Aron Cedercrantz | |
4 | + * Copyright (c) 2010-2012 Aron Cedercrantz | |
5 | 5 | * http://github.com/rastersize/CDEvents/ |
6 | 6 | * |
7 | 7 | * Permission is hereby granted, free of charge, to any person |
@@ -44,22 +44,14 @@ | ||
44 | 44 | URL:(NSURL *)URL |
45 | 45 | flags:(CDEventFlags)flags |
46 | 46 | { |
47 | - return [[[CDEvent alloc] initWithIdentifier:identifier | |
47 | + return [[CDEvent alloc] initWithIdentifier:identifier | |
48 | 48 | date:date |
49 | 49 | URL:URL |
50 | - flags:flags] | |
51 | - autorelease]; | |
50 | + flags:flags]; | |
52 | 51 | } |
53 | 52 | |
54 | 53 | |
55 | 54 | #pragma mark Init/dealloc methods |
56 | -- (void)dealloc | |
57 | -{ | |
58 | - [_date release]; | |
59 | - [_URL release]; | |
60 | - | |
61 | - [super dealloc]; | |
62 | -} | |
63 | 55 | |
64 | 56 | - (id)initWithIdentifier:(NSUInteger)identifier |
65 | 57 | date:(NSDate *)date |
@@ -69,8 +61,8 @@ | ||
69 | 61 | if ((self = [super init])) { |
70 | 62 | _identifier = identifier; |
71 | 63 | _flags = flags; |
72 | - _date = [date retain]; | |
73 | - _URL = [URL retain]; | |
64 | + _date = date; | |
65 | + _URL = URL; | |
74 | 66 | } |
75 | 67 | |
76 | 68 | return self; |
@@ -101,7 +93,7 @@ | ||
101 | 93 | - (id)copyWithZone:(NSZone *)zone |
102 | 94 | { |
103 | 95 | // We can do this since we are immutable. |
104 | - return [self retain]; | |
96 | + return self; | |
105 | 97 | } |
106 | 98 | |
107 | 99 | #pragma mark Specific flag properties |
@@ -1,7 +1,7 @@ | ||
1 | 1 | /** |
2 | 2 | * CDEvents |
3 | 3 | * |
4 | - * Copyright (c) 2010 Aron Cedercrantz | |
4 | + * Copyright (c) 2010-2012 Aron Cedercrantz | |
5 | 5 | * http://github.com/rastersize/CDEvents/ |
6 | 6 | * |
7 | 7 | * Permission is hereby granted, free of charge, to any person |
@@ -95,6 +95,17 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
95 | 95 | |
96 | 96 | |
97 | 97 | #pragma mark - |
98 | +#pragma mark CDEvents Block Type | |
99 | +@class CDEvents; | |
100 | +/** | |
101 | + * Type of the block which gets called when an event occurs. | |
102 | + * | |
103 | + * @since head | |
104 | + */ | |
105 | +typedef void (^CDEventsEventBlock)(CDEvents *watcher, CDEvent *event); | |
106 | + | |
107 | + | |
108 | +#pragma mark - | |
98 | 109 | #pragma mark CDEvents interface |
99 | 110 | /** |
100 | 111 | * An Objective-C wrapper for the <code>FSEvents</code> C API. |
@@ -105,23 +116,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
105 | 116 | * |
106 | 117 | * @since 1.0.0 |
107 | 118 | */ |
108 | -@interface CDEvents : NSObject <NSCopying> { | |
109 | -@private | |
110 | - __weak id<CDEventsDelegate> _delegate; | |
111 | - | |
112 | - FSEventStreamRef _eventStream; | |
113 | - CFTimeInterval _notificationLatency; | |
114 | - | |
115 | - CDEventIdentifier _sinceEventIdentifier; | |
116 | - NSUInteger _eventStreamCreationFlags; | |
117 | - | |
118 | - BOOL _ignoreEventsFromSubDirectories; | |
119 | - | |
120 | - CDEvent *_lastEvent; | |
121 | - | |
122 | - NSArray *_watchedURLs; | |
123 | - NSArray *_excludedURLs; | |
124 | -} | |
119 | +@interface CDEvents : NSObject <NSCopying> {} | |
125 | 120 | |
126 | 121 | #pragma mark Properties |
127 | 122 | /** @name Managing the Delegate */ |
@@ -135,7 +130,17 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
135 | 130 | * |
136 | 131 | * @since 1.0.0 |
137 | 132 | */ |
138 | -@property (assign) __weak id<CDEventsDelegate> delegate; | |
133 | +@property (unsafe_unretained) id<CDEventsDelegate> delegate; | |
134 | + | |
135 | +/** @name Getting Event Block */ | |
136 | +/** | |
137 | + * The event block. | |
138 | + * | |
139 | + * @return The CDEventsEventBlock block which is executed when an event occurs. | |
140 | + * | |
141 | + * @since head | |
142 | + */ | |
143 | +@property (readonly) CDEventsEventBlock eventBlock; | |
139 | 144 | |
140 | 145 | /** @name Getting Event Watcher Properties */ |
141 | 146 | /** |
@@ -145,7 +150,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
145 | 150 | * |
146 | 151 | * @since 1.0.0 |
147 | 152 | */ |
148 | -@property (readonly) CFTimeInterval notificationLatency; | |
153 | +@property (readonly) CFTimeInterval notificationLatency; | |
149 | 154 | |
150 | 155 | /** |
151 | 156 | * The event identifier from which events will be supplied to the delegate. |
@@ -154,16 +159,16 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
154 | 159 | * |
155 | 160 | * @since 1.0.0 |
156 | 161 | */ |
157 | -@property (readonly) CDEventIdentifier sinceEventIdentifier; | |
162 | +@property (readonly) CDEventIdentifier sinceEventIdentifier; | |
158 | 163 | |
159 | 164 | /** |
160 | - * The last event that occured and thas has been delivered to the delegate. | |
165 | + * The last event that occured and has been delivered to the delegate. | |
161 | 166 | * |
162 | - * @return The last event that occured and thas has been delivered to the delegate. | |
167 | + * @return The last event that occured and has been delivered to the delegate. | |
163 | 168 | * |
164 | 169 | * @since 1.0.0 |
165 | 170 | */ |
166 | -@property (retain, readonly) CDEvent *lastEvent; | |
171 | +@property (strong, readonly) CDEvent *lastEvent; | |
167 | 172 | |
168 | 173 | /** |
169 | 174 | * The URLs that we watch for events. |
@@ -172,7 +177,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
172 | 177 | * |
173 | 178 | * @since 1.0.0 |
174 | 179 | */ |
175 | -@property (readonly) NSArray *watchedURLs; | |
180 | +@property (copy, readonly) NSArray *watchedURLs; | |
176 | 181 | |
177 | 182 | |
178 | 183 | /** @name Configuring the Event watcher */ |
@@ -184,7 +189,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
184 | 189 | * |
185 | 190 | * @since 1.0.0 |
186 | 191 | */ |
187 | -@property (copy) NSArray *excludedURLs; | |
192 | +@property (copy) NSArray *excludedURLs; | |
188 | 193 | |
189 | 194 | /** |
190 | 195 | * Wheter events from sub-directories of the watched URLs should be ignored or not. |
@@ -194,7 +199,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
194 | 199 | * |
195 | 200 | * @since 1.0.0 |
196 | 201 | */ |
197 | -@property (assign) BOOL ignoreEventsFromSubDirectories; | |
202 | +@property (assign) BOOL ignoreEventsFromSubDirectories; | |
198 | 203 | |
199 | 204 | |
200 | 205 | #pragma mark Event identifier class methods |
@@ -211,8 +216,8 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
211 | 216 | + (CDEventIdentifier)currentEventIdentifier; |
212 | 217 | |
213 | 218 | |
214 | -#pragma mark Init methods | |
215 | -/** @name Creating CDEvents Objects */ | |
219 | +#pragma mark Creating CDEvents Objects With a Delegate | |
220 | +/** @name Creating CDEvents Objects With a Delegate */ | |
216 | 221 | /** |
217 | 222 | * Returns an <code>CDEvents</code> object initialized with the given URLs to watch. |
218 | 223 | * |
@@ -271,8 +276,6 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; | ||
271 | 276 | delegate:(id<CDEventsDelegate>)delegate |
272 | 277 | onRunLoop:(NSRunLoop *)runLoop; |
273 | 278 | |
274 | - | |
275 | - | |
276 | 279 | /** |
277 | 280 | * 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. |
278 | 281 | * |
@@ -311,6 +314,104 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
311 | 314 | excludeURLs:(NSArray *)exludeURLs |
312 | 315 | streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags; |
313 | 316 | |
317 | +#pragma mark Creating CDEvents Objects With a Block | |
318 | +/** @name Creating CDEvents Objects With a Block */ | |
319 | +/** | |
320 | + * Returns an <code>CDEvents</code> object initialized with the given URLs to watch. | |
321 | + * | |
322 | + * @param URLs An array of URLs we want to watch. | |
323 | + * @param block The block which the CDEvents object executes when it recieves an event. | |
324 | + * @return An CDEvents object initialized with the given URLs to watch. | |
325 | + * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>. | |
326 | + * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. | |
327 | + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. | |
328 | + * | |
329 | + * @see initWithURLs:delegate:onRunLoop: | |
330 | + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
331 | + * @see CDEventsEventBlock | |
332 | + * @see kCDEventsDefaultEventStreamFlags | |
333 | + * @see kCDEventsSinceEventNow | |
334 | + * | |
335 | + * @discussion Calls initWithURLs:block:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
336 | + * with <code>sinceEventIdentifier</code> with the event identifier for "event | |
337 | + * since now", <code>notificationLatency</code> set to 3.0 seconds, | |
338 | + * <code>ignoreEventsFromSubDirectories</code> set to <code>NO</code>, | |
339 | + * <code>excludedURLs</code> to <code>nil</code>, the event stream creation | |
340 | + * flags will be set to <code>kCDEventsDefaultEventStreamFlags</code> and | |
341 | + * schedueled on the current run loop. | |
342 | + * | |
343 | + * @since head | |
344 | + */ | |
345 | +- (id)initWithURLs:(NSArray *)URLs block:(CDEventsEventBlock)block; | |
346 | + | |
347 | +/** | |
348 | + * Returns an <code>CDEvents</code> object initialized with the given URLs to watch and schedules the watcher on the given run loop. | |
349 | + * | |
350 | + * @param URLs An array of URLs we want to watch. | |
351 | + * @param block The block which the CDEvents object executes when it recieves an event. | |
352 | + * @param runLoop The run loop which the which the watcher should be schedueled on. | |
353 | + * @return An CDEvents object initialized with the given URLs to watch. | |
354 | + * @throws NSInvalidArgumentException if <em>URLs</em> is empty or points to <code>nil</code>. | |
355 | + * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. | |
356 | + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. | |
357 | + * | |
358 | + * @see initWithURLs:delegate: | |
359 | + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
360 | + * @see CDEventsEventBlock | |
361 | + * @see kCDEventsDefaultEventStreamFlags | |
362 | + * @see kCDEventsSinceEventNow | |
363 | + * | |
364 | + * @discussion Calls initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: | |
365 | + * with <code>sinceEventIdentifier</code> with the event identifier for "event | |
366 | + * since now", <code>notificationLatency</code> set to 3.0 seconds, | |
367 | + * <code>ignoreEventsFromSubDirectories</code> set to <code>NO</code>, | |
368 | + * <code>excludedURLs</code> to <code>nil</code> and the event stream creation | |
369 | + * flags will be set to <code>kCDEventsDefaultEventStreamFlags</code>. | |
370 | + * | |
371 | + * @since head | |
372 | + */ | |
373 | +- (id)initWithURLs:(NSArray *)URLs | |
374 | + block:(CDEventsEventBlock)block | |
375 | + onRunLoop:(NSRunLoop *)runLoop; | |
376 | + | |
377 | +/** | |
378 | + * 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. | |
379 | + * | |
380 | + * @param URLs An array of URLs (<code>NSURL</code>) we want to watch. | |
381 | + * @param block The block which the CDEvents object executes when it recieves an event. | |
382 | + * @param runLoop The run loop which the which the watcher should be schedueled on. | |
383 | + * @param sinceEventIdentifier Events that have happened after the given event identifier will be supplied. | |
384 | + * @param notificationLatency The (approximate) time intervall between notifications sent to the delegate. | |
385 | + * @param ignoreEventsFromSubDirs Wheter events from sub-directories of the watched URLs should be ignored or not. | |
386 | + * @param exludeURLs An array of URLs that we should ignore events from. Pass <code>nil</code> if none should be excluded. | |
387 | + * @param streamCreationFlags The event stream creation flags. | |
388 | + * @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. | |
389 | + * @throws NSInvalidArgumentException if the parameter URLs is empty or points to <code>nil</code>. | |
390 | + * @throws NSInvalidArgumentException if <em>delegate</em>is <code>nil</code>. | |
391 | + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. | |
392 | + * | |
393 | + * @see initWithURLs:delegate: | |
394 | + * @see initWithURLs:delegate:onRunLoop: | |
395 | + * @see ignoreEventsFromSubDirectories | |
396 | + * @see excludedURLs | |
397 | + * @see CDEventsEventBlock | |
398 | + * @see FSEventStreamCreateFlags | |
399 | + * | |
400 | + * @discussion To ask for events "since now" pass the return value of | |
401 | + * currentEventIdentifier as the parameter <code>sinceEventIdentifier</code>. | |
402 | + * CDEventStreamCreationFailureException should be extremely rare. | |
403 | + * | |
404 | + * @since head | |
405 | + */ | |
406 | +- (id)initWithURLs:(NSArray *)URLs | |
407 | + block:(CDEventsEventBlock)block | |
408 | + onRunLoop:(NSRunLoop *)runLoop | |
409 | +sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier | |
410 | +notificationLantency:(CFTimeInterval)notificationLatency | |
411 | +ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | |
412 | + excludeURLs:(NSArray *)exludeURLs | |
413 | +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags; | |
414 | + | |
314 | 415 | #pragma mark Flush methods |
315 | 416 | /** @name Flushing Events */ |
316 | 417 | /** |
@@ -1,15 +1,48 @@ | ||
1 | -// | |
2 | -// CDEvents.m | |
3 | -// CDEvents | |
4 | -// | |
5 | -// Created by Aron Cedercrantz on 03/04/10. | |
6 | -// Copyright 2010 __MyCompanyName__. All rights reserved. | |
7 | -// | |
1 | +/** | |
2 | + * CDEvents | |
3 | + * | |
4 | + * Copyright (c) 2010-2012 Aron Cedercrantz | |
5 | + * http://github.com/rastersize/CDEvents/ | |
6 | + * | |
7 | + * Permission is hereby granted, free of charge, to any person | |
8 | + * obtaining a copy of this software and associated documentation | |
9 | + * files (the "Software"), to deal in the Software without | |
10 | + * restriction, including without limitation the rights to use, | |
11 | + * copy, modify, merge, publish, distribute, sublicense, and/or sell | |
12 | + * copies of the Software, and to permit persons to whom the | |
13 | + * Software is furnished to do so, subject to the following | |
14 | + * conditions: | |
15 | + * | |
16 | + * The above copyright notice and this permission notice shall be | |
17 | + * included in all copies or substantial portions of the Software. | |
18 | + * | |
19 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
20 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
21 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
22 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
23 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
24 | + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
25 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
26 | + * OTHER DEALINGS IN THE SOFTWARE. | |
27 | + */ | |
8 | 28 | |
9 | 29 | #import "CDEvents.h" |
10 | 30 | |
11 | 31 | #import "CDEventsDelegate.h" |
12 | 32 | |
33 | +#ifndef __has_feature | |
34 | + #define __has_feature(x) 0 | |
35 | +#endif | |
36 | + | |
37 | +#if !__has_feature(objc_arc) | |
38 | + #error CDEvents must be built with ARC. | |
39 | +#endif | |
40 | + | |
41 | +#if !__has_feature(blocks) | |
42 | + #error CDEvents must be built with support for blocks. | |
43 | +#endif | |
44 | + | |
45 | + | |
13 | 46 | #pragma mark CDEvents custom exceptions |
14 | 47 | NSString *const CDEventsEventStreamCreationFailureException = @"CDEventsEventStreamCreationFailureException"; |
15 | 48 |
@@ -25,9 +58,17 @@ const CDEventIdentifier kCDEventsSinceEventNow = kFSEventStreamEventIdSinceNow; | ||
25 | 58 | #pragma mark - |
26 | 59 | #pragma mark Private API |
27 | 60 | // Private API |
28 | -@interface CDEvents () | |
61 | +@interface CDEvents () { | |
62 | +@private | |
63 | + CDEventsEventBlock _eventBlock; | |
64 | + | |
65 | + FSEventStreamRef _eventStream; | |
66 | + NSUInteger _eventStreamCreationFlags; | |
67 | +} | |
29 | 68 | |
30 | -@property (retain, readwrite) CDEvent *lastEvent; | |
69 | +// Redefine the properties that should be writeable. | |
70 | +@property (strong, readwrite) CDEvent *lastEvent; | |
71 | +@property (copy, readwrite) NSArray *watchedURLs; | |
31 | 72 | |
32 | 73 | // The FSEvents callback function |
33 | 74 | static void CDEventsCallback( |
@@ -73,12 +114,6 @@ static void CDEventsCallback( | ||
73 | 114 | [self disposeEventStream]; |
74 | 115 | |
75 | 116 | _delegate = nil; |
76 | - | |
77 | - [_lastEvent release]; | |
78 | - [_watchedURLs release]; | |
79 | - [_excludedURLs release]; | |
80 | - | |
81 | - [super dealloc]; | |
82 | 117 | } |
83 | 118 | |
84 | 119 | - (void)finalize |
@@ -113,22 +148,73 @@ static void CDEventsCallback( | ||
113 | 148 | |
114 | 149 | - (id)initWithURLs:(NSArray *)URLs |
115 | 150 | delegate:(id<CDEventsDelegate>)delegate |
116 | - onRunLoop:(NSRunLoop *)runLoop | |
151 | + onRunLoop:(NSRunLoop *)runLoop | |
117 | 152 | sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier |
118 | 153 | notificationLantency:(CFTimeInterval)notificationLatency |
119 | 154 | ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs |
120 | - excludeURLs:(NSArray *)exludeURLs | |
121 | - streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags | |
155 | + excludeURLs:(NSArray *)exludeURLs | |
156 | +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags | |
122 | 157 | { |
123 | - if (delegate == nil || URLs == nil || [URLs count] == 0) { | |
158 | + if (delegate == nil) { | |
159 | + [NSException raise:NSInvalidArgumentException | |
160 | + format:@"Invalid arguments passed to CDEvents init-method."]; | |
161 | + } | |
162 | + | |
163 | + _delegate = delegate; | |
164 | + | |
165 | + return [self initWithURLs:URLs | |
166 | + block:^(CDEvents *watcher, CDEvent *event){ | |
167 | + if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) { | |
168 | + [[watcher delegate] URLWatcher:watcher eventOccurred:event]; | |
169 | + } | |
170 | + } | |
171 | + onRunLoop:runLoop | |
172 | + sinceEventIdentifier:sinceEventIdentifier | |
173 | + notificationLantency:notificationLatency | |
174 | + ignoreEventsFromSubDirs:ignoreEventsFromSubDirs | |
175 | + excludeURLs:exludeURLs | |
176 | + streamCreationFlags:streamCreationFlags]; | |
177 | +} | |
178 | + | |
179 | + | |
180 | +#pragma mark Creating CDEvents Objects With a Block | |
181 | +- (id)initWithURLs:(NSArray *)URLs block:(CDEventsEventBlock)block | |
182 | +{ | |
183 | + return [self initWithURLs:URLs block:block onRunLoop:[NSRunLoop currentRunLoop]]; | |
184 | +} | |
185 | + | |
186 | +- (id)initWithURLs:(NSArray *)URLs | |
187 | + block:(CDEventsEventBlock)block | |
188 | + onRunLoop:(NSRunLoop *)runLoop | |
189 | +{ | |
190 | + return [self initWithURLs:URLs | |
191 | + block:block | |
192 | + onRunLoop:runLoop | |
193 | + sinceEventIdentifier:kCDEventsSinceEventNow | |
194 | + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY | |
195 | + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS | |
196 | + excludeURLs:nil | |
197 | + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; | |
198 | +} | |
199 | + | |
200 | +- (id)initWithURLs:(NSArray *)URLs | |
201 | + block:(CDEventsEventBlock)block | |
202 | + onRunLoop:(NSRunLoop *)runLoop | |
203 | +sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier | |
204 | +notificationLantency:(CFTimeInterval)notificationLatency | |
205 | +ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | |
206 | + excludeURLs:(NSArray *)exludeURLs | |
207 | +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags | |
208 | +{ | |
209 | + if (block == NULL || URLs == nil || [URLs count] == 0) { | |
124 | 210 | [NSException raise:NSInvalidArgumentException |
125 | 211 | format:@"Invalid arguments passed to CDEvents init-method."]; |
126 | 212 | } |
127 | 213 | |
128 | 214 | if ((self = [super init])) { |
129 | 215 | _watchedURLs = [URLs copy]; |
130 | - [self setExcludedURLs:exludeURLs]; | |
131 | - [self setDelegate:delegate]; | |
216 | + _excludedURLs = [exludeURLs copy]; | |
217 | + _eventBlock = block; | |
132 | 218 | |
133 | 219 | _sinceEventIdentifier = sinceEventIdentifier; |
134 | 220 | _eventStreamCreationFlags = streamCreationFlags; |
@@ -157,7 +243,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
157 | 243 | - (id)copyWithZone:(NSZone *)zone |
158 | 244 | { |
159 | 245 | CDEvents *copy = [[CDEvents alloc] initWithURLs:[self watchedURLs] |
160 | - delegate:[self delegate] | |
246 | + block:[self eventBlock] | |
161 | 247 | onRunLoop:[NSRunLoop currentRunLoop] |
162 | 248 | sinceEventIdentifier:[self sinceEventIdentifier] |
163 | 249 | notificationLantency:[self notificationLatency] |
@@ -168,6 +254,12 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
168 | 254 | return copy; |
169 | 255 | } |
170 | 256 | |
257 | +#pragma mark Block | |
258 | +- (CDEventsEventBlock)eventBlock | |
259 | +{ | |
260 | + return _eventBlock; | |
261 | +} | |
262 | + | |
171 | 263 | |
172 | 264 | #pragma mark Flush methods |
173 | 265 | - (void)flushSynchronously |
@@ -193,10 +285,10 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
193 | 285 | - (NSString *)streamDescription |
194 | 286 | { |
195 | 287 | CFStringRef streamDescriptionCF = FSEventStreamCopyDescription(_eventStream); |
196 | - NSString *returnString = [[NSString alloc] initWithString:(NSString *)streamDescriptionCF]; | |
288 | + NSString *returnString = [[NSString alloc] initWithString:(__bridge NSString *)streamDescriptionCF]; | |
197 | 289 | CFRelease(streamDescriptionCF); |
198 | 290 | |
199 | - return [returnString autorelease]; | |
291 | + return returnString; | |
200 | 292 | } |
201 | 293 | |
202 | 294 |
@@ -205,7 +297,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
205 | 297 | { |
206 | 298 | FSEventStreamContext callbackCtx; |
207 | 299 | callbackCtx.version = 0; |
208 | - callbackCtx.info = (void *)self; | |
300 | + callbackCtx.info = (__bridge void *)self; | |
209 | 301 | callbackCtx.retain = NULL; |
210 | 302 | callbackCtx.release = NULL; |
211 | 303 | callbackCtx.copyDescription = NULL; |
@@ -218,7 +310,7 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs | ||
218 | 310 | _eventStream = FSEventStreamCreate(kCFAllocatorDefault, |
219 | 311 | &CDEventsCallback, |
220 | 312 | &callbackCtx, |
221 | - (CFArrayRef)watchedPaths, | |
313 | + (__bridge CFArrayRef)watchedPaths, | |
222 | 314 | (FSEventStreamEventId)[self sinceEventIdentifier], |
223 | 315 | [self notificationLatency], |
224 | 316 | _eventStreamCreationFlags); |
@@ -240,39 +332,40 @@ static void CDEventsCallback( | ||
240 | 332 | ConstFSEventStreamRef streamRef, |
241 | 333 | void *callbackCtxInfo, |
242 | 334 | size_t numEvents, |
243 | - void *eventPaths, | |
335 | + void *eventPaths, // CFArrayRef | |
244 | 336 | const FSEventStreamEventFlags eventFlags[], |
245 | 337 | const FSEventStreamEventId eventIds[]) |
246 | 338 | { |
247 | - CDEvents *watcher = (CDEvents *)callbackCtxInfo; | |
248 | - | |
339 | + CDEvents *watcher = (__bridge CDEvents *)callbackCtxInfo; | |
340 | + NSArray *eventPathsArray = (__bridge NSArray *)eventPaths; | |
249 | 341 | NSArray *watchedURLs = [watcher watchedURLs]; |
250 | 342 | NSArray *excludedURLs = [watcher excludedURLs]; |
251 | - NSArray *eventPathsArray = (NSArray *)eventPaths; | |
252 | - BOOL shouldIgnore = NO; | |
253 | 343 | CDEvent *lastEvent = nil; |
254 | - | |
344 | + | |
255 | 345 | for (NSUInteger i = 0; i < numEvents; ++i) { |
256 | - shouldIgnore = NO; | |
346 | + BOOL shouldIgnore = NO; | |
347 | + FSEventStreamEventFlags flags = eventFlags[i]; | |
348 | + FSEventStreamEventId identifier = eventIds[i]; | |
257 | 349 | |
258 | - NSString *eventPath = [[eventPathsArray objectAtIndex:i] | |
259 | - stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; | |
260 | - NSURL *eventURL = [NSURL URLWithString:eventPath]; | |
261 | 350 | // We do this hackery to ensure that the eventPath string doesn't |
262 | 351 | // contain any trailing slash. |
263 | - eventPath = [eventURL path]; | |
352 | + NSURL *eventURL = [NSURL fileURLWithPath:[[eventPathsArray objectAtIndex:i] stringByStandardizingPath]]; | |
353 | + NSString *eventPath = [eventURL path]; | |
264 | 354 | |
355 | + // Ignore all events except for the URLs we are explicitly watching. | |
265 | 356 | if ([watcher ignoreEventsFromSubDirectories]) { |
266 | 357 | shouldIgnore = YES; |
267 | - for (NSURL *URL in watchedURLs) { | |
268 | - if ([[URL path] isEqualToString:eventPath]) { | |
358 | + for (NSURL *url in watchedURLs) { | |
359 | + if ([[url path] isEqualToString:eventPath]) { | |
269 | 360 | shouldIgnore = NO; |
270 | 361 | break; |
271 | 362 | } |
272 | 363 | } |
364 | + // Ignore all explicitly excludeded URLs (not required to check if we | |
365 | + // ignore all events from sub-directories). | |
273 | 366 | } else if (excludedURLs != nil) { |
274 | - for (NSURL *URL in excludedURLs) { | |
275 | - if ([eventPath hasPrefix:[URL path]]) { | |
367 | + for (NSURL *url in excludedURLs) { | |
368 | + if ([eventPath hasPrefix:[url path]]) { | |
276 | 369 | shouldIgnore = YES; |
277 | 370 | break; |
278 | 371 | } |
@@ -280,30 +373,16 @@ static void CDEventsCallback( | ||
280 | 373 | } |
281 | 374 | |
282 | 375 | if (!shouldIgnore) { |
283 | - CDEvent *event = [[CDEvent alloc] initWithIdentifier:eventIds[i] | |
284 | - date:[NSDate date] | |
285 | - URL:eventURL | |
286 | - flags:eventFlags[i]]; | |
287 | - // Dispose of old lastEvent and retain the currently last | |
288 | - [lastEvent release]; | |
289 | - lastEvent = [event retain]; | |
290 | - | |
291 | - if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) { | |
292 | - [[watcher delegate] URLWatcher:watcher eventOccurred:event]; | |
293 | - } | |
294 | - | |
295 | - // Last event? | |
296 | - if (i == (numEvents - 1)) { | |
297 | - [watcher setLastEvent:event]; | |
298 | - } | |
376 | + CDEvent *event = [[CDEvent alloc] initWithIdentifier:identifier date:[NSDate date] URL:eventURL flags:flags]; | |
377 | + lastEvent = event; | |
299 | 378 | |
300 | - [event release]; | |
379 | + CDEventsEventBlock eventBlock = [watcher eventBlock]; | |
380 | + eventBlock(watcher, event); | |
301 | 381 | } |
302 | 382 | } |
303 | 383 | |
304 | 384 | if (lastEvent) { |
305 | 385 | [watcher setLastEvent:lastEvent]; |
306 | - [lastEvent release]; | |
307 | 386 | } |
308 | 387 | } |
309 | 388 |
@@ -0,0 +1,13 @@ | ||
1 | +Pod::Spec.new do |s| | |
2 | + s.name = "CDEvents" | |
3 | + s.version = "1.2.0" | |
4 | + s.summary = "An Objective-C wrapper for Mac OS X’s FSEvents C API." | |
5 | + s.homepage = "http://rastersize.github.com/CDEvents" | |
6 | + s.license = { :type => 'MIT', :file => 'LICENSE' } | |
7 | + s.author = { "Aron Cedercrantz" => "aron@cedercrantz.se" } | |
8 | + s.source = { :git => "https://github.com/rastersize/CDEvents.git", :tag => "1.2.0" } | |
9 | + s.platform = :osx, '10.6' | |
10 | + s.source_files = '*.{h,m}' | |
11 | + s.framework = 'CoreServices' | |
12 | + s.requires_arc = true | |
13 | +end | |
\ No newline at end of file |
@@ -242,7 +242,8 @@ | ||
242 | 242 | 0867D690FE84028FC02AAC07 /* Project object */ = { |
243 | 243 | isa = PBXProject; |
244 | 244 | attributes = { |
245 | - LastUpgradeCheck = 0420; | |
245 | + LastUpgradeCheck = 0460; | |
246 | + ORGANIZATIONNAME = "Aron Cedercrantz"; | |
246 | 247 | }; |
247 | 248 | buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */; |
248 | 249 | compatibilityVersion = "Xcode 3.2"; |
@@ -328,17 +329,19 @@ | ||
328 | 329 | isa = XCBuildConfiguration; |
329 | 330 | buildSettings = { |
330 | 331 | ALWAYS_SEARCH_USER_PATHS = NO; |
332 | + CLANG_ENABLE_OBJC_ARC = YES; | |
333 | + COMBINE_HIDPI_IMAGES = YES; | |
331 | 334 | COPY_PHASE_STRIP = NO; |
332 | 335 | DYLIB_COMPATIBILITY_VERSION = 1; |
333 | 336 | DYLIB_CURRENT_VERSION = 1; |
334 | 337 | FRAMEWORK_VERSION = A; |
335 | 338 | GCC_DYNAMIC_NO_PIC = NO; |
336 | - GCC_ENABLE_OBJC_GC = supported; | |
337 | - GCC_MODEL_TUNING = G5; | |
339 | + GCC_ENABLE_OBJC_GC = unsupported; | |
340 | + GCC_MODEL_TUNING = ""; | |
338 | 341 | GCC_OPTIMIZATION_LEVEL = 0; |
339 | 342 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
340 | 343 | GCC_PREFIX_HEADER = CDEvents_Prefix.pch; |
341 | - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; | |
344 | + GCC_PREPROCESSOR_DEFINITIONS = ""; | |
342 | 345 | INFOPLIST_FILE = Info.plist; |
343 | 346 | INSTALL_PATH = "@loader_path/../Frameworks"; |
344 | 347 | PRODUCT_NAME = CDEvents; |
@@ -350,15 +353,17 @@ | ||
350 | 353 | isa = XCBuildConfiguration; |
351 | 354 | buildSettings = { |
352 | 355 | ALWAYS_SEARCH_USER_PATHS = NO; |
356 | + CLANG_ENABLE_OBJC_ARC = YES; | |
357 | + COMBINE_HIDPI_IMAGES = YES; | |
353 | 358 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
354 | 359 | DYLIB_COMPATIBILITY_VERSION = 1; |
355 | 360 | DYLIB_CURRENT_VERSION = 1; |
356 | 361 | FRAMEWORK_VERSION = A; |
357 | - GCC_ENABLE_OBJC_GC = supported; | |
358 | - GCC_MODEL_TUNING = G5; | |
362 | + GCC_ENABLE_OBJC_GC = unsupported; | |
363 | + GCC_MODEL_TUNING = ""; | |
359 | 364 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
360 | 365 | GCC_PREFIX_HEADER = CDEvents_Prefix.pch; |
361 | - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; | |
366 | + GCC_PREPROCESSOR_DEFINITIONS = ""; | |
362 | 367 | INFOPLIST_FILE = Info.plist; |
363 | 368 | INSTALL_PATH = "@loader_path/../Frameworks"; |
364 | 369 | PRODUCT_NAME = CDEvents; |
@@ -369,16 +374,19 @@ | ||
369 | 374 | 1DEB91B208733DA50010E9CD /* Debug */ = { |
370 | 375 | isa = XCBuildConfiguration; |
371 | 376 | buildSettings = { |
372 | - ARCHS = ( | |
373 | - x86_64, | |
374 | - i386, | |
375 | - ); | |
377 | + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; | |
378 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | |
379 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |
380 | + CLANG_WARN_INT_CONVERSION = YES; | |
381 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |
376 | 382 | GCC_C_LANGUAGE_STANDARD = gnu99; |
383 | + GCC_ENABLE_SSE3_EXTENSIONS = YES; | |
377 | 384 | GCC_OPTIMIZATION_LEVEL = 0; |
378 | 385 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; |
379 | 386 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
387 | + GCC_WARN_UNINITIALIZED_AUTOS = YES; | |
380 | 388 | GCC_WARN_UNUSED_VARIABLE = YES; |
381 | - MACOSX_DEPLOYMENT_TARGET = 10.5; | |
389 | + MACOSX_DEPLOYMENT_TARGET = 10.6; | |
382 | 390 | ONLY_ACTIVE_ARCH = YES; |
383 | 391 | RUN_CLANG_STATIC_ANALYZER = YES; |
384 | 392 | SDKROOT = macosx; |
@@ -388,15 +396,18 @@ | ||
388 | 396 | 1DEB91B308733DA50010E9CD /* Release */ = { |
389 | 397 | isa = XCBuildConfiguration; |
390 | 398 | buildSettings = { |
391 | - ARCHS = ( | |
392 | - x86_64, | |
393 | - i386, | |
394 | - ); | |
399 | + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; | |
400 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | |
401 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | |
402 | + CLANG_WARN_INT_CONVERSION = YES; | |
403 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | |
395 | 404 | GCC_C_LANGUAGE_STANDARD = gnu99; |
405 | + GCC_ENABLE_SSE3_EXTENSIONS = YES; | |
396 | 406 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; |
397 | 407 | GCC_WARN_ABOUT_RETURN_TYPE = YES; |
408 | + GCC_WARN_UNINITIALIZED_AUTOS = YES; | |
398 | 409 | GCC_WARN_UNUSED_VARIABLE = YES; |
399 | - MACOSX_DEPLOYMENT_TARGET = 10.5; | |
410 | + MACOSX_DEPLOYMENT_TARGET = 10.6; | |
400 | 411 | RUN_CLANG_STATIC_ANALYZER = YES; |
401 | 412 | SDKROOT = macosx; |
402 | 413 | }; |
@@ -406,14 +417,15 @@ | ||
406 | 417 | isa = XCBuildConfiguration; |
407 | 418 | buildSettings = { |
408 | 419 | ALWAYS_SEARCH_USER_PATHS = NO; |
420 | + COMBINE_HIDPI_IMAGES = YES; | |
409 | 421 | COPY_PHASE_STRIP = NO; |
410 | 422 | GCC_DYNAMIC_NO_PIC = NO; |
411 | 423 | GCC_ENABLE_OBJC_GC = unsupported; |
412 | - GCC_MODEL_TUNING = G5; | |
424 | + GCC_MODEL_TUNING = ""; | |
413 | 425 | GCC_OPTIMIZATION_LEVEL = 0; |
414 | 426 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
415 | 427 | GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; |
416 | - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; | |
428 | + GCC_PREPROCESSOR_DEFINITIONS = ""; | |
417 | 429 | INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; |
418 | 430 | INSTALL_PATH = "$(HOME)/Applications"; |
419 | 431 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; |
@@ -424,6 +436,7 @@ | ||
424 | 436 | AppKit, |
425 | 437 | ); |
426 | 438 | PRODUCT_NAME = CDEventsTestApp; |
439 | + ZERO_LINK = NO; | |
427 | 440 | }; |
428 | 441 | name = Debug; |
429 | 442 | }; |
@@ -431,13 +444,14 @@ | ||
431 | 444 | isa = XCBuildConfiguration; |
432 | 445 | buildSettings = { |
433 | 446 | ALWAYS_SEARCH_USER_PATHS = NO; |
447 | + COMBINE_HIDPI_IMAGES = YES; | |
434 | 448 | COPY_PHASE_STRIP = YES; |
435 | 449 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
436 | 450 | GCC_ENABLE_OBJC_GC = unsupported; |
437 | - GCC_MODEL_TUNING = G5; | |
451 | + GCC_MODEL_TUNING = ""; | |
438 | 452 | GCC_PRECOMPILE_PREFIX_HEADER = YES; |
439 | 453 | GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; |
440 | - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; | |
454 | + GCC_PREPROCESSOR_DEFINITIONS = ""; | |
441 | 455 | INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; |
442 | 456 | INSTALL_PATH = "$(HOME)/Applications"; |
443 | 457 | LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; |
@@ -1,7 +1,7 @@ | ||
1 | 1 | /** |
2 | - * SCEvents | |
2 | + * CDEvents | |
3 | 3 | * |
4 | - * Copyright (c) 2010 Aron Cedercrantz | |
4 | + * Copyright (c) 2010-2012 Aron Cedercrantz | |
5 | 5 | * http://github.com/rastersize/CDEvents/ |
6 | 6 | * |
7 | 7 | * Permission is hereby granted, free of charge, to any person |
@@ -17,11 +17,11 @@ | ||
17 | 17 | <key>CFBundlePackageType</key> |
18 | 18 | <string>FMWK</string> |
19 | 19 | <key>CFBundleShortVersionString</key> |
20 | - <string>1.1.2</string> | |
20 | + <string>1.2.0</string> | |
21 | 21 | <key>CFBundleSignature</key> |
22 | 22 | <string>????</string> |
23 | 23 | <key>CFBundleVersion</key> |
24 | - <string>1.1.2</string> | |
24 | + <string>1.2.0</string> | |
25 | 25 | <key>NSPrincipalClass</key> |
26 | 26 | <string></string> |
27 | 27 | </dict> |
@@ -0,0 +1,7 @@ | ||
1 | +Copyright (c) 2010, 2011 Aron Cedercrantz | |
2 | + | |
3 | +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
4 | + | |
5 | +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | |
6 | + | |
7 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@@ -1,26 +1,92 @@ | ||
1 | -# CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # | |
1 | +# CDEvents | |
2 | +***Note:*** The `develop` branch **requires Mac OS X 10.6 or newer** as the framework relies on [ARC](http://clang.llvm.org/docs/AutomaticReferenceCounting.html "Automatic Reference Counting Technical Specification") and [blocks](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html "Blocks Programming Topics"). | |
2 | 3 | |
3 | -## What is this? ## | |
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/). | |
4 | +Website: http://rastersize.github.com/CDEvents | |
5 | 5 | |
6 | -## Requirements ## | |
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. | |
6 | +## What is this? | |
7 | +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) with support for blocks. Furthermore, all the classes are immutable and it should be thread-safe. | |
8 | 8 | |
9 | -## What differentiates CDEvents from SCEvents then? ## | |
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 | 9 | |
12 | -Another difference between `CDEvents` and `SCEvents` is that `CDEvents` is available for both manual memory management and environments using garbage collection. | |
10 | +## Requirements | |
11 | +Requires Mac OS X 10.6 (Snow Leopard) and an Intel 64-bit CPU. The requirements stems from that automatic reference counting (ARC) is supported from 10.6 and up as long as the modern (i.e. 64-bit) Objective-C runtime is used since ARC requires the non-fragile ABI. Although the built product works on 10.6 and up it must be built on a machine running 10.7 (Lion) using Xcode 4.2 and the 10.7 SDK as the 10.6 SDK does not include ARC. The built product support both manual memory management and automatic reference counting. | |
13 | 12 | |
14 | -So I've written some of the code from scratch and "borrowed" some from `SCEvents`. | |
13 | +If you need to support older versions of OS X or garbage collection please see the branch `support/1.1`. All _1.1.x_ version will support garbage collection and OS X 10.5. | |
15 | 14 | |
16 | -## API documentation ## | |
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. | |
18 | 15 | |
19 | -## Authors ## | |
16 | +## Usage | |
17 | +You can use either the block based version (recommended) or the delegate based. Using both systems at the same time is not supported. | |
18 | + | |
19 | +### Block based (recommended) | |
20 | +1. Add CDEvents to your project, | |
21 | + * either by compiling the project and dragging the `CDEvents.framework` into your project or | |
22 | + * by dragging the entire CDEvents project into your project as a sub-project. | |
23 | +2. Import the `CDEvents.h` header where you need it. | |
24 | +3. Set up your `CDEvents` instance and give it a block to execute when a event occurs. | |
25 | + | |
26 | +Easy example code: | |
27 | + | |
28 | + self.events = [[CDEvents alloc]] initWithURLs:<NSArray of URLs to watch> | |
29 | + block:^(CDEvents *watcher, CDEvent *event) { | |
30 | + <Your code here> | |
31 | + }]; | |
32 | + | |
33 | +Or use all the all-options initiator: | |
34 | + | |
35 | + self.events = [[CDEvents alloc] initWithURLs:<NSArray of URLs to watch> | |
36 | + block:^(CDEvents *watcher, CDEvent *event) { | |
37 | + <Your code here> | |
38 | + } | |
39 | + onRunLoop:[NSRunLoop currentRunLoop] | |
40 | + sinceEventIdentifier:kCDEventsSinceEventNow | |
41 | + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY | |
42 | + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS | |
43 | + excludeURLs:<NSArray of URLs to exlude> | |
44 | + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; | |
45 | + | |
46 | +See the test app (`TestApp`) for an example on how to use the framework. | |
47 | + | |
48 | +### Delegate based | |
49 | +***This is the same behavior as pre ARC and blocks.*** | |
50 | + | |
51 | +1. Add CDEvents to your project, | |
52 | + * either by compiling the project and dragging the `CDEvents.framework` into your project or | |
53 | + * by dragging the entire CDEvents project into your project as a sub-project. | |
54 | +2. Import the `CDEvents.h` header where you need it. | |
55 | +3. Import the `CDEventsDelegate.h` header where you need it (i.e. in the file which declares your delegate). | |
56 | +4. Implement the delegate (`-URLWatcher:eventOccurred:`) and create your `CDEvents` instance. | |
57 | +5. Zero out the delegate when you no longer need it. | |
58 | + | |
59 | +Example code: | |
60 | + | |
61 | + self.events = [[CDEvents alloc] initWithURLs:<NSArray of URLs to watch> | |
62 | + delegate:<Your delegate> | |
63 | + onRunLoop:[NSRunLoop currentRunLoop] | |
64 | + sinceEventIdentifier:kCDEventsSinceEventNow | |
65 | + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY | |
66 | + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS | |
67 | + excludeURLs:<NSArray of URLs to exlude> | |
68 | + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; | |
69 | + | |
70 | +See the test app (`TestApp`) for an example on how to use the framework. | |
71 | + | |
72 | +**Important:** Since Mac OS X 10.6 is set as the deployment target automatic zeroing of weak references is not available. Thus you must set the `delegate` of `CDEvents` to `nil` when you no longer want to receive events. That is, at least in your `-dealloc` method. This is also required when using 10.7 and up! (`delegate` is an `unsafe_unretained` property.) | |
73 | + | |
74 | +For more details please refer to the documentation in the header files and the section "API documentation" below. | |
75 | + | |
76 | + | |
77 | +## API documentation | |
78 | +Read the latest [API documentation](http://rastersize.github.com/CDEvents/docs/api/head) or [browse for each version](http://rastersize.github.com/CDEvents/docs/api) of CDEvents. Alternatively you can generate it yourself, please see below. | |
79 | + | |
80 | +### appledoc | |
81 | +Run the script `api.appledoc.sh` from the root of the project. The script takes one optional argument, the version of the project as a string. If the version string is empty "HEAD" will be used instead. | |
82 | + | |
83 | +### Doxygen | |
84 | +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. | |
20 | 85 | |
21 | -* Aron Cedercrantz | |
86 | +## Contributors | |
87 | +See GitHubs [contributors to rastersize/CDEvents](https://github.com/rastersize/CDEvents/contributors) statistics page. | |
22 | 88 | |
23 | -## License ## | |
89 | +## License | |
24 | 90 | The code is released under the [MIT-license](http://www.opensource.org/licenses/mit-license.php). |
25 | 91 | |
26 | -If you want, even though you really don't have to, I would love hearing what you use CDEvents for! Send me an email (first name @ last name dot se) or a [message via GitHub](http://github.com/inbox/new/rastersize). | |
92 | +If you want, even though you really don't have to, I would love to hear what you use CDEvents for! Send me an email (first name (i.e. aron) @ last name (i.e. cedercrantz) dot se). |
@@ -31,6 +31,9 @@ | ||
31 | 31 | #import <CDEvents/CDEvents.h> |
32 | 32 | |
33 | 33 | |
34 | +#define CD_EVENTS_TEST_APP_USE_BLOCKS_API 1 | |
35 | + | |
36 | + | |
34 | 37 | bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) |
35 | 38 | { |
36 | 39 | static SInt32 versionMajor = 0, versionMinor = 0; |
@@ -69,6 +72,16 @@ bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) | ||
69 | 72 | creationFlags |= kFSEventStreamCreateFlagFileEvents; |
70 | 73 | } |
71 | 74 | |
75 | +#if CD_EVENTS_TEST_APP_USE_BLOCKS_API | |
76 | + _events = [[CDEvents alloc] initWithURLs:watchedURLs | |
77 | + block:^(CDEvents *watcher, CDEvent *event){ NSLog(@"[Block] URLWatcher: %@\nEvent: %@", watcher, event); } | |
78 | + onRunLoop:[NSRunLoop currentRunLoop] | |
79 | + sinceEventIdentifier:kCDEventsSinceEventNow | |
80 | + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY | |
81 | + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS | |
82 | + excludeURLs:excludeURLs | |
83 | + streamCreationFlags:creationFlags]; | |
84 | +#else | |
72 | 85 | _events = [[CDEvents alloc] initWithURLs:watchedURLs |
73 | 86 | delegate:self |
74 | 87 | onRunLoop:[NSRunLoop currentRunLoop] |
@@ -78,6 +91,7 @@ bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) | ||
78 | 91 | excludeURLs:excludeURLs |
79 | 92 | streamCreationFlags:creationFlags]; |
80 | 93 | //[_events setIgnoreEventsFromSubDirectories:YES]; |
94 | +#endif | |
81 | 95 | |
82 | 96 | NSLog(@"-[CDEventsTestAppController run]:\n%@\n------\n%@", |
83 | 97 | _events, |
@@ -92,9 +106,9 @@ bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) | ||
92 | 106 | [super dealloc]; |
93 | 107 | } |
94 | 108 | |
95 | -- (void)URLWatcher:(CDEvents *)URLWatcher eventOccurred:(CDEvent *)event | |
109 | +- (void)URLWatcher:(CDEvents *)urlWatcher eventOccurred:(CDEvent *)event | |
96 | 110 | { |
97 | - NSLog(@"URLWatcher: %@\nEvent: %@", URLWatcher, event); | |
111 | + NSLog(@"[Delegate] URLWatcher: %@\nEvent: %@", urlWatcher, event); | |
98 | 112 | } |
99 | 113 | |
100 | 114 | @end |
@@ -0,0 +1,45 @@ | ||
1 | +#!/bin/sh | |
2 | + | |
3 | +## | |
4 | +# USAGE | |
5 | +# ./api.appledoc.sh [version-string] | |
6 | +# | |
7 | +# Execute it from the root of the CDEvents project. | |
8 | + | |
9 | + | |
10 | +PROJECT_VERSION="HEAD" | |
11 | +if [ "$#" -gt "0" ] | |
12 | +then | |
13 | + PROJECT_VERSION=$1 | |
14 | +fi | |
15 | + | |
16 | +API_DOCS_DIR="./api/appledoc" | |
17 | +#HEADER_FILES=`find . -name '*.h'` | |
18 | +HEADER_FILES=`ls *.h` | |
19 | + | |
20 | + | |
21 | +echo "API documentation generator for CDEvents v1" | |
22 | +echo "Will save generated documentation to \"${API_DOCS_DIR}\"" | |
23 | +echo "Removing old API documentation" | |
24 | +rm -r $API_DOCS_DIR/html 2> /dev/null | |
25 | +rm -r $API_DOCS_DIR/docset 2> /dev/null | |
26 | + | |
27 | +echo "Will generate API documentation based on:" | |
28 | +echo ${HEADER_FILES} | |
29 | + | |
30 | +echo "Generating for version \"${PROJECT_VERSION}\"..." | |
31 | +appledoc \ | |
32 | + --output ${API_DOCS_DIR} \ | |
33 | + --project-name "CDEvents" \ | |
34 | + --project-version ${PROJECT_VERSION} \ | |
35 | + --project-company "Aron Cedercrantz" \ | |
36 | + --company-id "com.cedercrantz" \ | |
37 | + --create-html \ | |
38 | + --keep-intermediate-files \ | |
39 | + --no-install-docset \ | |
40 | + ${HEADER_FILES} | |
41 | +echo "Done!" | |
42 | + | |
43 | +echo "You can open the HTML documentation with:" | |
44 | +echo "\"open ${API_DOCS_DIR}/html/index.html\"" | |
45 | + |