From 69a2adcaaffc073e4c8d9d51583dc042e3146351 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 17 Aug 2011 20:35:37 +0200 Subject: [PATCH 01/32] Updated project for ARC. --- CDEvent.h | 8 ++++---- CDEvent.m | 18 +++++------------- CDEvents.h | 20 ++++++++++---------- CDEvents.m | 20 ++++++++------------ CDEvents.xcodeproj/project.pbxproj | 20 ++++++++------------ 5 files changed, 35 insertions(+), 51 deletions(-) diff --git a/CDEvent.h b/CDEvent.h index af48e71..21625bc 100644 --- a/CDEvent.h +++ b/CDEvent.h @@ -71,8 +71,8 @@ typedef FSEventStreamEventFlags CDEventFlags; @interface CDEvent : NSObject { @private CDEventIdentifier _identifier; - NSDate *_date; - NSURL *_URL; + NSDate *__weak _date; + NSURL *__weak _URL; CDEventFlags _flags; } @@ -96,7 +96,7 @@ typedef FSEventStreamEventFlags CDEventFlags; * * @since 1.0.0 */ -@property (readonly) NSDate *date; +@property (weak, readonly) NSDate *date; /** * The URL of the item which changed. @@ -105,7 +105,7 @@ typedef FSEventStreamEventFlags CDEventFlags; * * @since 1.0.0 */ -@property (readonly) NSURL *URL; +@property (weak, readonly) NSURL *URL; /** @name Getting Event Flags */ diff --git a/CDEvent.m b/CDEvent.m index 0ef758b..c091b37 100644 --- a/CDEvent.m +++ b/CDEvent.m @@ -44,22 +44,14 @@ + (CDEvent *)eventWithIdentifier:(NSUInteger)identifier URL:(NSURL *)URL flags:(CDEventFlags)flags { - return [[[CDEvent alloc] initWithIdentifier:identifier + return [[CDEvent alloc] initWithIdentifier:identifier date:date URL:URL - flags:flags] - autorelease]; + flags:flags]; } #pragma mark Init/dealloc methods -- (void)dealloc -{ - [_date release]; - [_URL release]; - - [super dealloc]; -} - (id)initWithIdentifier:(NSUInteger)identifier date:(NSDate *)date @@ -69,8 +61,8 @@ - (id)initWithIdentifier:(NSUInteger)identifier if ((self = [super init])) { _identifier = identifier; _flags = flags; - _date = [date retain]; - _URL = [URL retain]; + _date = date; + _URL = URL; } return self; @@ -101,7 +93,7 @@ - (id)initWithCoder:(NSCoder *)aDecoder - (id)copyWithZone:(NSZone *)zone { // We can do this since we are immutable. - return [self retain]; + return self; } diff --git a/CDEvents.h b/CDEvents.h index 4e67f20..9f5a8c5 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -107,20 +107,20 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; */ @interface CDEvents : NSObject { @private - __weak id _delegate; + //__weak id _delegate; FSEventStreamRef _eventStream; - CFTimeInterval _notificationLatency; + //CFTimeInterval _notificationLatency; - CDEventIdentifier _sinceEventIdentifier; + //CDEventIdentifier _sinceEventIdentifier; NSUInteger _eventStreamCreationFlags; - BOOL _ignoreEventsFromSubDirectories; + //BOOL _ignoreEventsFromSubDirectories; - CDEvent *_lastEvent; + //CDEvent *_lastEvent; - NSArray *_watchedURLs; - NSArray *_excludedURLs; + //NSArray *_watchedURLs; + //NSArray *_excludedURLs; } #pragma mark Properties @@ -135,7 +135,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (assign) __weak id delegate; +@property (weak) id delegate; /** @name Getting Event Watcher Properties */ /** @@ -163,7 +163,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (retain, readonly) CDEvent *lastEvent; +@property (strong, readonly) CDEvent *lastEvent; /** * The URLs that we watch for events. @@ -172,7 +172,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (readonly) NSArray *watchedURLs; +@property (strong, readonly) NSArray *watchedURLs; /** @name Configuring the Event watcher */ diff --git a/CDEvents.m b/CDEvents.m index 11e6393..b2d1d44 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -27,7 +27,8 @@ // Private API @interface CDEvents () -@property (retain, readwrite) CDEvent *lastEvent; +@property (strong, readwrite) CDEvent *lastEvent; +@property (strong, readwrite) NSArray *watchedURLs; // The FSEvents callback function static void CDEventsCallback( @@ -74,11 +75,7 @@ - (void)dealloc _delegate = nil; - [_lastEvent release]; - [_watchedURLs release]; - [_excludedURLs release]; - [super dealloc]; } - (void)finalize @@ -193,10 +190,10 @@ - (NSString *)description - (NSString *)streamDescription { CFStringRef streamDescriptionCF = FSEventStreamCopyDescription(_eventStream); - NSString *returnString = [[NSString alloc] initWithString:(NSString *)streamDescriptionCF]; + NSString *returnString = [[NSString alloc] initWithString:(__bridge NSString *)streamDescriptionCF]; CFRelease(streamDescriptionCF); - return [returnString autorelease]; + return returnString; } @@ -205,7 +202,7 @@ - (void)createEventStream { FSEventStreamContext callbackCtx; callbackCtx.version = 0; - callbackCtx.info = (void *)self; + callbackCtx.info = (__bridge void *)self; callbackCtx.retain = NULL; callbackCtx.release = NULL; callbackCtx.copyDescription = NULL; @@ -218,7 +215,7 @@ - (void)createEventStream _eventStream = FSEventStreamCreate(kCFAllocatorDefault, &CDEventsCallback, &callbackCtx, - (CFArrayRef)watchedPaths, + (__bridge CFArrayRef)watchedPaths, (FSEventStreamEventId)[self sinceEventIdentifier], [self notificationLatency], _eventStreamCreationFlags); @@ -244,11 +241,11 @@ static void CDEventsCallback( const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { - CDEvents *watcher = (CDEvents *)callbackCtxInfo; + CDEvents *watcher = (__bridge CDEvents *)callbackCtxInfo; NSArray *watchedURLs = [watcher watchedURLs]; NSArray *excludedURLs = [watcher excludedURLs]; - NSArray *eventPathsArray = (NSArray *)eventPaths; + NSArray *eventPathsArray = (__bridge NSArray *)eventPaths; BOOL shouldIgnore = NO; for (NSUInteger i = 0; i < numEvents; ++i) { @@ -293,7 +290,6 @@ static void CDEventsCallback( [watcher setLastEvent:event]; } - [event release]; } } diff --git a/CDEvents.xcodeproj/project.pbxproj b/CDEvents.xcodeproj/project.pbxproj index 1f10b8b..bb8ceff 100644 --- a/CDEvents.xcodeproj/project.pbxproj +++ b/CDEvents.xcodeproj/project.pbxproj @@ -321,13 +321,14 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_ENABLE_OBJC_GC = supported; + GCC_ENABLE_OBJC_GC = unsupported; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; @@ -344,11 +345,12 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; - GCC_ENABLE_OBJC_GC = supported; + GCC_ENABLE_OBJC_GC = unsupported; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = CDEvents_Prefix.pch; @@ -363,16 +365,13 @@ 1DEB91B208733DA50010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - x86_64, - i386, - ); + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.5; + MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = YES; @@ -383,15 +382,12 @@ 1DEB91B308733DA50010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ARCHS = ( - x86_64, - i386, - ); + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.5; + MACOSX_DEPLOYMENT_TARGET = 10.7; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = YES; SDKROOT = macosx; From 4bf77e1cabcf87d7b0e73fde2623f7626d847049 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Thu, 18 Aug 2011 13:41:24 +0200 Subject: [PATCH 02/32] Changed the readme to reflect the status of the ARC feature branch. --- README.mdown | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.mdown b/README.mdown index 1914b28..e29c890 100644 --- a/README.mdown +++ b/README.mdown @@ -1,10 +1,13 @@ # CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # +***Note:*** Experimental ARC branch ## What is this? ## 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/). ## Requirements ## -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. +Requires Mac OS X 10.7 (Lion) and an Intel 64-bit CPU, the requirements stem from that automatic reference counting (ARC) was introduced with full support in OS X 10.7 when using the modern (i.e. 64-bit) Objective-C runtime. Supports both manual memory management and automatic reference counting. + +If you need to support older versions of OS X please see the non-ARC branch, currently `develop` and `master`. Though which branch is the non-ARC will probably change in the future. ## What differentiates CDEvents from SCEvents then? ## 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. From 984bcba0cf4236b1f446a87c59b350e775336f94 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Thu, 18 Aug 2011 14:02:09 +0200 Subject: [PATCH 03/32] Added nores on how to use the project to the readme. --- README.mdown | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.mdown b/README.mdown index e29c890..b4f9399 100644 --- a/README.mdown +++ b/README.mdown @@ -9,6 +9,30 @@ Requires Mac OS X 10.7 (Lion) and an Intel 64-bit CPU, the requirements stem fro If you need to support older versions of OS X please see the non-ARC branch, currently `develop` and `master`. Though which branch is the non-ARC will probably change in the future. +## Usage ## + +1. Add CDEvents to your project, + * either by compiling the project and dragging the `CDEvents.framework` into your project or + * by dragging the entire CDEvents project into your project as a sub-project. +2. Import the `CDEvents.h` header where you need it. +3. Import the `CDEventsDelegate.h` header where you need it (i.e. in the file which declares your delegate). +4. See the test app (`TestApp`) for details on how to use the framework. Essentially it boils down to, + 1. Implement the delegate method `-URLWatcher:eventOccurred:`. + 2. Set up your `CDEvents` instance. + +` ` + + self.events = [[CDEvents alloc] initWithURLs: + delegate: + onRunLoop:[NSRunLoop currentRunLoop] + sinceEventIdentifier:kCDEventsSinceEventNow + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS + excludeURLs: + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; + +For more details please refer to the documentation in the header files and the section "API documentation" below. + ## What differentiates CDEvents from SCEvents then? ## 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. From b22a03123c61601b1321b3142f7d0c470ff43bed Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Thu, 18 Aug 2011 14:08:10 +0200 Subject: [PATCH 04/32] Changed the internal behaviour of the watchedURLs property. Moved ivar declaration in CDEvents to the private class extension. --- CDEvents.h | 24 ++++-------------------- CDEvents.m | 9 +++++++-- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/CDEvents.h b/CDEvents.h index 9f5a8c5..1fc988a 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -105,23 +105,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@interface CDEvents : NSObject { -@private - //__weak id _delegate; - - FSEventStreamRef _eventStream; - //CFTimeInterval _notificationLatency; - - //CDEventIdentifier _sinceEventIdentifier; - NSUInteger _eventStreamCreationFlags; - - //BOOL _ignoreEventsFromSubDirectories; - - //CDEvent *_lastEvent; - - //NSArray *_watchedURLs; - //NSArray *_excludedURLs; -} +@interface CDEvents : NSObject {} #pragma mark Properties /** @name Managing the Delegate */ @@ -157,9 +141,9 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; @property (readonly) CDEventIdentifier sinceEventIdentifier; /** - * The last event that occured and thas has been delivered to the delegate. + * The last event that occured and has been delivered to the delegate. * - * @return The last event that occured and thas has been delivered to the delegate. + * @return The last event that occured and has been delivered to the delegate. * * @since 1.0.0 */ @@ -172,7 +156,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (strong, readonly) NSArray *watchedURLs; +@property (copy, readonly) NSArray *watchedURLs; /** @name Configuring the Event watcher */ diff --git a/CDEvents.m b/CDEvents.m index b2d1d44..b4d3920 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -25,10 +25,15 @@ #pragma mark - #pragma mark Private API // Private API -@interface CDEvents () +@interface CDEvents () { +@private + FSEventStreamRef _eventStream; + NSUInteger _eventStreamCreationFlags; +} +// Redefine the properties that should be writeable. @property (strong, readwrite) CDEvent *lastEvent; -@property (strong, readwrite) NSArray *watchedURLs; +@property (copy, readwrite) NSArray *watchedURLs; // The FSEvents callback function static void CDEventsCallback( From 1aa80ce247dedb129b096f842fdb147d55c17808 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Thu, 18 Aug 2011 14:10:45 +0200 Subject: [PATCH 05/32] Removed now unsued ivar declarations. --- CDEvent.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/CDEvent.h b/CDEvent.h index 21625bc..48f8088 100644 --- a/CDEvent.h +++ b/CDEvent.h @@ -68,13 +68,7 @@ typedef FSEventStreamEventFlags CDEventFlags; * * @since 1.0.0 */ -@interface CDEvent : NSObject { -@private - CDEventIdentifier _identifier; - NSDate *__weak _date; - NSURL *__weak _URL; - CDEventFlags _flags; -} +@interface CDEvent : NSObject {} #pragma mark Properties /** @name Getting Event Properties */ From d65e893f377814d72e23721bbd395db87b184ba5 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 21 Aug 2011 14:29:03 +0200 Subject: [PATCH 06/32] Fixed an incorrect copyright notice. Still under MIT though! --- CDEvents.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CDEvents.m b/CDEvents.m index b4d3920..4630f6f 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -3,7 +3,7 @@ // CDEvents // // Created by Aron Cedercrantz on 03/04/10. -// Copyright 2010 __MyCompanyName__. All rights reserved. +// Copyright 2010 Aron Cedercrantz. All rights reserved. // #import "CDEvents.h" From 3d2a8dd1a5f01de1b1c3d7c177b1d4148acf946c Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Tue, 30 Aug 2011 20:28:20 +0200 Subject: [PATCH 07/32] Changed the ARC branch to deploy down to 10.6 instead of only 10.7 and up. This change requires the user of the framework to set the CDEvents delegate to nil when it is no longer needed (i.e. in -dealloc). --- CDEvent.h | 4 ++-- CDEvents.h | 14 +++++++------- CDEvents.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CDEvent.h b/CDEvent.h index f677a35..3b1efd5 100644 --- a/CDEvent.h +++ b/CDEvent.h @@ -89,7 +89,7 @@ typedef FSEventStreamEventFlags CDEventFlags; * * @since 1.0.0 */ -@property (weak, readonly) NSDate *date; +@property (unsafe_unretained, readonly) NSDate *date; /** * The URL of the item which changed. @@ -98,7 +98,7 @@ typedef FSEventStreamEventFlags CDEventFlags; * * @since 1.0.0 */ -@property (weak, readonly) NSURL *URL; +@property (unsafe_unretained, readonly) NSURL *URL; /** @name Getting Event Flags */ diff --git a/CDEvents.h b/CDEvents.h index 1fc988a..0d1a7f0 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -119,7 +119,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (weak) id delegate; +@property (unsafe_unretained) id delegate; /** @name Getting Event Watcher Properties */ /** @@ -129,7 +129,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (readonly) CFTimeInterval notificationLatency; +@property (readonly) CFTimeInterval notificationLatency; /** * The event identifier from which events will be supplied to the delegate. @@ -138,7 +138,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (readonly) CDEventIdentifier sinceEventIdentifier; +@property (readonly) CDEventIdentifier sinceEventIdentifier; /** * The last event that occured and has been delivered to the delegate. @@ -147,7 +147,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (strong, readonly) CDEvent *lastEvent; +@property (strong, readonly) CDEvent *lastEvent; /** * The URLs that we watch for events. @@ -156,7 +156,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (copy, readonly) NSArray *watchedURLs; +@property (copy, readonly) NSArray *watchedURLs; /** @name Configuring the Event watcher */ @@ -168,7 +168,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (copy) NSArray *excludedURLs; +@property (copy) NSArray *excludedURLs; /** * Wheter events from sub-directories of the watched URLs should be ignored or not. @@ -178,7 +178,7 @@ extern const CDEventIdentifier kCDEventsSinceEventNow; * * @since 1.0.0 */ -@property (assign) BOOL ignoreEventsFromSubDirectories; +@property (assign) BOOL ignoreEventsFromSubDirectories; #pragma mark Event identifier class methods diff --git a/CDEvents.xcodeproj/project.pbxproj b/CDEvents.xcodeproj/project.pbxproj index f2e8acd..7373914 100644 --- a/CDEvents.xcodeproj/project.pbxproj +++ b/CDEvents.xcodeproj/project.pbxproj @@ -378,10 +378,10 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx; + SDKROOT = macosx10.7; }; name = Debug; }; @@ -393,10 +393,10 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.7; + MACOSX_DEPLOYMENT_TARGET = 10.6; PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx; + SDKROOT = macosx10.7; }; name = Release; }; From f4da94003e8b82a72136ac06cd3bdf893cf89d2d Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Tue, 30 Aug 2011 20:29:43 +0200 Subject: [PATCH 08/32] Updated the readme to reflect the new deployment target. --- README.mdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.mdown b/README.mdown index b4f9399..b48e143 100644 --- a/README.mdown +++ b/README.mdown @@ -5,7 +5,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). 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/). ## Requirements ## -Requires Mac OS X 10.7 (Lion) and an Intel 64-bit CPU, the requirements stem from that automatic reference counting (ARC) was introduced with full support in OS X 10.7 when using the modern (i.e. 64-bit) Objective-C runtime. Supports both manual memory management and automatic reference counting. +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. (ARC requires the non-fragile ABI.) Although the built product should work 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. Supports both manual memory management and automatic reference counting. If you need to support older versions of OS X please see the non-ARC branch, currently `develop` and `master`. Though which branch is the non-ARC will probably change in the future. @@ -30,6 +30,8 @@ If you need to support older versions of OS X please see the non-ARC branch, cur ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS excludeURLs: streamCreationFlags:kCDEventsDefaultEventStreamFlags]; + +**Important:** Since we have 10.6 set as the deployment target automatic zeroing of weak references is not available and as such 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! For more details please refer to the documentation in the header files and the section "API documentation" below. From f5c2709aede6c62542b259013215c7c65a8e8265 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Fri, 21 Oct 2011 18:36:24 +0200 Subject: [PATCH 09/32] Added CDEventsEventBlock type. --- CDEvents.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CDEvents.h b/CDEvents.h index 0d1a7f0..fc0e31c 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -94,6 +94,17 @@ extern const CDEventsEventStreamCreationFlags kCDEventsDefaultEventStreamFlags; extern const CDEventIdentifier kCDEventsSinceEventNow; +#pragma mark - +#pragma mark CDEvents Block Type +@class CDEvents; +/** + * Type of the block which gets called when an event occurs. + * + * @since head + */ +typedef void (^CDEventsEventBlock)(CDEvents *watcher, CDEvent *event); + + #pragma mark - #pragma mark CDEvents interface /** From 91fadddc78799eec5b2b174aa76779f1047e6678 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Fri, 21 Oct 2011 18:38:48 +0200 Subject: [PATCH 10/32] Added logic to use blocks instead. - Added init* methods for blocks. - Changed so that the old init* methods for delegates now call the new block based ones. - Changed so that the callback executes the block. --- CDEvents.h | 114 +++++++++++++++++++++++++++- CDEvents.m | 80 ++++++++++++++++--- TestApp/CDEventsTestAppController.m | 2 +- 3 files changed, 179 insertions(+), 17 deletions(-) diff --git a/CDEvents.h b/CDEvents.h index fc0e31c..34feda1 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -132,6 +132,16 @@ typedef void (^CDEventsEventBlock)(CDEvents *watcher, CDEvent *event); */ @property (unsafe_unretained) id delegate; +/** @name Getting Event Block */ +/** + * The event block. + * + * @return The CDEventsEventBlock block which is executed when an event occurs. + * + * @since head + */ +@property (readonly) CDEventsEventBlock eventBlock; + /** @name Getting Event Watcher Properties */ /** * The (approximate) time intervall between notifications sent to the delegate. @@ -206,8 +216,8 @@ typedef void (^CDEventsEventBlock)(CDEvents *watcher, CDEvent *event); + (CDEventIdentifier)currentEventIdentifier; -#pragma mark Init methods -/** @name Creating CDEvents Objects */ +#pragma mark Creating CDEvents Objects With a Delegate +/** @name Creating CDEvents Objects With a Delegate */ /** * Returns an CDEvents object initialized with the given URLs to watch. * @@ -266,8 +276,6 @@ typedef void (^CDEventsEventBlock)(CDEvents *watcher, CDEvent *event); delegate:(id)delegate onRunLoop:(NSRunLoop *)runLoop; - - /** * Returns an CDEvents 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. * @@ -306,6 +314,104 @@ ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs excludeURLs:(NSArray *)exludeURLs streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags; +#pragma mark Creating CDEvents Objects With a Block +/** @name Creating CDEvents Objects With a Block */ +/** + * Returns an CDEvents object initialized with the given URLs to watch. + * + * @param URLs An array of URLs we want to watch. + * @param block The block which the CDEvents object executes when it recieves an event. + * @return An CDEvents object initialized with the given URLs to watch. + * @throws NSInvalidArgumentException if URLs is empty or points to nil. + * @throws NSInvalidArgumentException if delegateis nil. + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. + * + * @see initWithURLs:delegate:onRunLoop: + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: + * @see CDEventsEventBlock + * @see kCDEventsDefaultEventStreamFlags + * @see kCDEventsSinceEventNow + * + * @discussion Calls initWithURLs:block:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: + * with sinceEventIdentifier with the event identifier for "event + * since now", notificationLatency set to 3.0 seconds, + * ignoreEventsFromSubDirectories set to NO, + * excludedURLs to nil, the event stream creation + * flags will be set to kCDEventsDefaultEventStreamFlags and + * schedueled on the current run loop. + * + * @since head + */ +- (id)initWithURLs:(NSArray *)URLs block:(CDEventsEventBlock)block; + +/** + * Returns an CDEvents object initialized with the given URLs to watch and schedules the watcher on the given run loop. + * + * @param URLs An array of URLs we want to watch. + * @param block The block which the CDEvents object executes when it recieves an event. + * @param runLoop The run loop which the which the watcher should be schedueled on. + * @return An CDEvents object initialized with the given URLs to watch. + * @throws NSInvalidArgumentException if URLs is empty or points to nil. + * @throws NSInvalidArgumentException if delegateis nil. + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. + * + * @see initWithURLs:delegate: + * @see initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: + * @see CDEventsEventBlock + * @see kCDEventsDefaultEventStreamFlags + * @see kCDEventsSinceEventNow + * + * @discussion Calls initWithURLs:delegate:onRunLoop:sinceEventIdentifier:notificationLantency:ignoreEventsFromSubDirs:excludeURLs:streamCreationFlags: + * with sinceEventIdentifier with the event identifier for "event + * since now", notificationLatency set to 3.0 seconds, + * ignoreEventsFromSubDirectories set to NO, + * excludedURLs to nil and the event stream creation + * flags will be set to kCDEventsDefaultEventStreamFlags. + * + * @since head + */ +- (id)initWithURLs:(NSArray *)URLs + block:(CDEventsEventBlock)block + onRunLoop:(NSRunLoop *)runLoop; + +/** + * Returns an CDEvents 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. + * + * @param URLs An array of URLs (NSURL) we want to watch. + * @param block The block which the CDEvents object executes when it recieves an event. + * @param runLoop The run loop which the which the watcher should be schedueled on. + * @param sinceEventIdentifier Events that have happened after the given event identifier will be supplied. + * @param notificationLatency The (approximate) time intervall between notifications sent to the delegate. + * @param ignoreEventsFromSubDirs Wheter events from sub-directories of the watched URLs should be ignored or not. + * @param exludeURLs An array of URLs that we should ignore events from. Pass nil if none should be excluded. + * @param streamCreationFlags The event stream creation flags. + * @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. + * @throws NSInvalidArgumentException if the parameter URLs is empty or points to nil. + * @throws NSInvalidArgumentException if delegateis nil. + * @throws CDEventsEventStreamCreationFailureException if we failed to create a event stream. + * + * @see initWithURLs:delegate: + * @see initWithURLs:delegate:onRunLoop: + * @see ignoreEventsFromSubDirectories + * @see excludedURLs + * @see CDEventsEventBlock + * @see FSEventStreamCreateFlags + * + * @discussion To ask for events "since now" pass the return value of + * currentEventIdentifier as the parameter sinceEventIdentifier. + * CDEventStreamCreationFailureException should be extremely rare. + * + * @since head + */ +- (id)initWithURLs:(NSArray *)URLs + block:(CDEventsEventBlock)block + onRunLoop:(NSRunLoop *)runLoop +sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier +notificationLantency:(CFTimeInterval)notificationLatency +ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs + excludeURLs:(NSArray *)exludeURLs +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags; + #pragma mark Flush methods /** @name Flushing Events */ /** diff --git a/CDEvents.m b/CDEvents.m index 4630f6f..d6bcdf2 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -27,6 +27,8 @@ // Private API @interface CDEvents () { @private + CDEventsEventBlock _eventBlock; + FSEventStreamRef _eventStream; NSUInteger _eventStreamCreationFlags; } @@ -79,8 +81,6 @@ - (void)dealloc [self disposeEventStream]; _delegate = nil; - - } - (void)finalize @@ -115,22 +115,73 @@ - (id)initWithURLs:(NSArray *)URLs - (id)initWithURLs:(NSArray *)URLs delegate:(id)delegate - onRunLoop:(NSRunLoop *)runLoop + onRunLoop:(NSRunLoop *)runLoop sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier notificationLantency:(CFTimeInterval)notificationLatency ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs - excludeURLs:(NSArray *)exludeURLs - streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags + excludeURLs:(NSArray *)exludeURLs +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags { - if (delegate == nil || URLs == nil || [URLs count] == 0) { + if (delegate == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Invalid arguments passed to CDEvents init-method."]; + } + + _delegate = delegate; + + return [self initWithURLs:URLs + block:^(CDEvents *watcher, CDEvent *event){ + if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) { + [[watcher delegate] URLWatcher:watcher eventOccurred:event]; + } + } + onRunLoop:runLoop + sinceEventIdentifier:sinceEventIdentifier + notificationLantency:notificationLatency + ignoreEventsFromSubDirs:ignoreEventsFromSubDirs + excludeURLs:exludeURLs + streamCreationFlags:streamCreationFlags]; +} + + +#pragma mark Creating CDEvents Objects With a Block +- (id)initWithURLs:(NSArray *)URLs block:(CDEventsEventBlock)block +{ + return [self initWithURLs:URLs block:block onRunLoop:[NSRunLoop currentRunLoop]]; +} + +- (id)initWithURLs:(NSArray *)URLs + block:(CDEventsEventBlock)block + onRunLoop:(NSRunLoop *)runLoop +{ + return [self initWithURLs:URLs + block:block + onRunLoop:runLoop + sinceEventIdentifier:kCDEventsSinceEventNow + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS + excludeURLs:nil + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; +} + +- (id)initWithURLs:(NSArray *)URLs + block:(CDEventsEventBlock)block + onRunLoop:(NSRunLoop *)runLoop +sinceEventIdentifier:(CDEventIdentifier)sinceEventIdentifier +notificationLantency:(CFTimeInterval)notificationLatency +ignoreEventsFromSubDirs:(BOOL)ignoreEventsFromSubDirs + excludeURLs:(NSArray *)exludeURLs +streamCreationFlags:(CDEventsEventStreamCreationFlags)streamCreationFlags +{ + if (block == NULL || URLs == nil || [URLs count] == 0) { [NSException raise:NSInvalidArgumentException format:@"Invalid arguments passed to CDEvents init-method."]; } if ((self = [super init])) { _watchedURLs = [URLs copy]; - [self setExcludedURLs:exludeURLs]; - [self setDelegate:delegate]; + _excludedURLs = [exludeURLs copy]; + _eventBlock = block; _sinceEventIdentifier = sinceEventIdentifier; _eventStreamCreationFlags = streamCreationFlags; @@ -159,7 +210,7 @@ - (id)initWithURLs:(NSArray *)URLs - (id)copyWithZone:(NSZone *)zone { CDEvents *copy = [[CDEvents alloc] initWithURLs:[self watchedURLs] - delegate:[self delegate] + block:[self eventBlock] onRunLoop:[NSRunLoop currentRunLoop] sinceEventIdentifier:[self sinceEventIdentifier] notificationLantency:[self notificationLatency] @@ -170,6 +221,12 @@ - (id)copyWithZone:(NSZone *)zone return copy; } +#pragma mark Block +- (CDEventsEventBlock)eventBlock +{ + return _eventBlock; +} + #pragma mark Flush methods - (void)flushSynchronously @@ -286,9 +343,8 @@ static void CDEventsCallback( URL:eventURL flags:eventFlags[i]]; - if ([(id)[watcher delegate] conformsToProtocol:@protocol(CDEventsDelegate)]) { - [[watcher delegate] URLWatcher:watcher eventOccurred:event]; - } + CDEventsEventBlock eventBlock = [watcher eventBlock]; + eventBlock(watcher, event); // Last event? if (i == (numEvents - 1)) { diff --git a/TestApp/CDEventsTestAppController.m b/TestApp/CDEventsTestAppController.m index fcc934b..d8fe20d 100644 --- a/TestApp/CDEventsTestAppController.m +++ b/TestApp/CDEventsTestAppController.m @@ -94,7 +94,7 @@ - (void)dealloc - (void)URLWatcher:(CDEvents *)URLWatcher eventOccurred:(CDEvent *)event { - NSLog(@"URLWatcher: %@\nEvent: %@", URLWatcher, event); + NSLog(@"[Delegate] URLWatcher: %@\nEvent: %@", URLWatcher, event); } @end From 98abd8e999f61d3029a86948cf996e9728e9dcce Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 24 Oct 2011 19:08:30 +0200 Subject: [PATCH 11/32] Fix lastEvent not getting set. - The lastEvent could some times not get set if the last event sent to the callback was ignored or excluded. - Did some cleanup in the callback. --- CDEvents.m | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/CDEvents.m b/CDEvents.m index d6bcdf2..964da70 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -299,38 +299,41 @@ static void CDEventsCallback( ConstFSEventStreamRef streamRef, void *callbackCtxInfo, size_t numEvents, - void *eventPaths, + void *eventPaths, // CFArrayRef const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { - CDEvents *watcher = (__bridge CDEvents *)callbackCtxInfo; - + CDEvents *watcher = (__bridge CDEvents *)callbackCtxInfo; + NSArray *eventPathsArray = (__bridge NSArray *)eventPaths; NSArray *watchedURLs = [watcher watchedURLs]; NSArray *excludedURLs = [watcher excludedURLs]; - NSArray *eventPathsArray = (__bridge NSArray *)eventPaths; - BOOL shouldIgnore = NO; - + CDEvent *lastEvent = nil; + for (NSUInteger i = 0; i < numEvents; ++i) { - shouldIgnore = NO; + BOOL shouldIgnore = NO; + FSEventStreamEventFlags flags = eventFlags[i]; + FSEventStreamEventId identifier = eventIds[i]; - NSString *eventPath = [[eventPathsArray objectAtIndex:i] - stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSURL *eventURL = [NSURL URLWithString:eventPath]; // We do this hackery to ensure that the eventPath string doesn't // contain any trailing slash. + NSString *eventPath = [[eventPathsArray objectAtIndex:i] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSURL *eventURL = [NSURL URLWithString:eventPath]; eventPath = [eventURL path]; + // Ignore all events except for the URLs we are explicitly watching. if ([watcher ignoreEventsFromSubDirectories]) { shouldIgnore = YES; - for (NSURL *URL in watchedURLs) { - if ([[URL path] isEqualToString:eventPath]) { + for (NSURL *url in watchedURLs) { + if ([[url path] isEqualToString:eventPath]) { shouldIgnore = NO; break; } } + // Ignore all explicitly excludeded URLs (not required to check if we + // ignore all events from sub-directories). } else if (excludedURLs != nil) { - for (NSURL *URL in excludedURLs) { - if ([eventPath hasPrefix:[URL path]]) { + for (NSURL *url in excludedURLs) { + if ([eventPath hasPrefix:[url path]]) { shouldIgnore = YES; break; } @@ -338,23 +341,17 @@ static void CDEventsCallback( } if (!shouldIgnore) { - CDEvent *event = [[CDEvent alloc] initWithIdentifier:eventIds[i] - date:[NSDate date] - URL:eventURL - flags:eventFlags[i]]; + CDEvent *event = [[CDEvent alloc] initWithIdentifier:identifier date:[NSDate date] URL:eventURL flags:flags]; + lastEvent = event; CDEventsEventBlock eventBlock = [watcher eventBlock]; eventBlock(watcher, event); - - // Last event? - if (i == (numEvents - 1)) { - [watcher setLastEvent:event]; - } - } } - + if (lastEvent) { + [watcher setLastEvent:lastEvent]; + } } @end From d95574b5ab2955c5c238ec2ad3866442c336508a Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 24 Oct 2011 23:05:05 +0200 Subject: [PATCH 12/32] Change project settings. - Cleanup of the project settings (basically the same as ttilley did in https://github.com/ttilley/CDEvents/commit/140434b7d8238862ad341a10aa57479869807dfd). --- .gitattributes | 1 - CDEvents.xcodeproj/project.pbxproj | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.gitattributes b/.gitattributes index 6ecc74a..357f41b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,2 @@ -*.pbxproj binary *.m diff=objc *.mm diff=objc diff --git a/CDEvents.xcodeproj/project.pbxproj b/CDEvents.xcodeproj/project.pbxproj index 7373914..3e9ef3d 100644 --- a/CDEvents.xcodeproj/project.pbxproj +++ b/CDEvents.xcodeproj/project.pbxproj @@ -336,11 +336,11 @@ GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_ENABLE_OBJC_GC = unsupported; - GCC_MODEL_TUNING = G5; + GCC_MODEL_TUNING = ""; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = CDEvents_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; + GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "@loader_path/../Frameworks"; PRODUCT_NAME = CDEvents; @@ -358,10 +358,10 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_ENABLE_OBJC_GC = unsupported; - GCC_MODEL_TUNING = G5; + GCC_MODEL_TUNING = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = CDEvents_Prefix.pch; - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; + GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = Info.plist; INSTALL_PATH = "@loader_path/../Frameworks"; PRODUCT_NAME = CDEvents; @@ -374,6 +374,7 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; @@ -390,6 +391,7 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -407,11 +409,11 @@ COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_GC = unsupported; - GCC_MODEL_TUNING = G5; + GCC_MODEL_TUNING = ""; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; + GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; @@ -422,6 +424,7 @@ AppKit, ); PRODUCT_NAME = CDEventsTestApp; + ZERO_LINK = NO; }; name = Debug; }; @@ -432,10 +435,10 @@ COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_ENABLE_OBJC_GC = unsupported; - GCC_MODEL_TUNING = G5; + GCC_MODEL_TUNING = ""; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; - GCC_PREPROCESSOR_DEFINITIONS = NS_BUILD_32_LIKE_64; + GCC_PREPROCESSOR_DEFINITIONS = ""; INFOPLIST_FILE = "CDEventsTestApp-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; From 98a743775e3eba656c88ca1b097fafeba7aea5b1 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 24 Oct 2011 23:05:36 +0200 Subject: [PATCH 13/32] Update the test app to be able to use blocks API. --- TestApp/CDEventsTestAppController.m | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/TestApp/CDEventsTestAppController.m b/TestApp/CDEventsTestAppController.m index d8fe20d..2654198 100644 --- a/TestApp/CDEventsTestAppController.m +++ b/TestApp/CDEventsTestAppController.m @@ -31,6 +31,9 @@ #import +#define CD_EVENTS_TEST_APP_USE_BLOCKS_API 1 + + bool systemVersionIsAtLeast(SInt32 major, SInt32 minor) { static SInt32 versionMajor = 0, versionMinor = 0; @@ -69,6 +72,16 @@ - (void)run creationFlags |= kFSEventStreamCreateFlagFileEvents; } +#if CD_EVENTS_TEST_APP_USE_BLOCKS_API + _events = [[CDEvents alloc] initWithURLs:watchedURLs + block:^(CDEvents *watcher, CDEvent *event){ NSLog(@"[Block] URLWatcher: %@\nEvent: %@", watcher, event); } + onRunLoop:[NSRunLoop currentRunLoop] + sinceEventIdentifier:kCDEventsSinceEventNow + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS + excludeURLs:excludeURLs + streamCreationFlags:creationFlags]; +#else _events = [[CDEvents alloc] initWithURLs:watchedURLs delegate:self onRunLoop:[NSRunLoop currentRunLoop] @@ -78,6 +91,7 @@ - (void)run excludeURLs:excludeURLs streamCreationFlags:creationFlags]; //[_events setIgnoreEventsFromSubDirectories:YES]; +#endif NSLog(@"-[CDEventsTestAppController run]:\n%@\n------\n%@", _events, @@ -92,9 +106,9 @@ - (void)dealloc [super dealloc]; } -- (void)URLWatcher:(CDEvents *)URLWatcher eventOccurred:(CDEvent *)event +- (void)URLWatcher:(CDEvents *)urlWatcher eventOccurred:(CDEvent *)event { - NSLog(@"[Delegate] URLWatcher: %@\nEvent: %@", URLWatcher, event); + NSLog(@"[Delegate] URLWatcher: %@\nEvent: %@", urlWatcher, event); } @end From 44ade61ed2aede69aefea7a4206543c732ebc00f Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 24 Oct 2011 23:05:56 +0200 Subject: [PATCH 14/32] Update the read me to reflect the new changes. --- README.mdown | 81 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/README.mdown b/README.mdown index b48e143..7e02d35 100644 --- a/README.mdown +++ b/README.mdown @@ -1,55 +1,86 @@ # CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # -***Note:*** Experimental ARC branch +***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"). + ## What is this? ## -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/). +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. + ## Requirements ## -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. (ARC requires the non-fragile ABI.) Although the built product should work 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. Supports both manual memory management and automatic reference counting. +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. + +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. -If you need to support older versions of OS X please see the non-ARC branch, currently `develop` and `master`. Though which branch is the non-ARC will probably change in the future. ## Usage ## +You can use either the block based version (recommended) or the delegate based. Using both systems at the same time is not supported. + +### Block based (recommended) ### +1. Add CDEvents to your project, + * either by compiling the project and dragging the `CDEvents.framework` into your project or + * by dragging the entire CDEvents project into your project as a sub-project. +2. Import the `CDEvents.h` header where you need it. +3. Set up your `CDEvents` instance and give it a block to execute when a event occurs. + +Easy example code: + + self.events = [[CDEvents alloc]] initWithURLs: + block:^(CDEvents *watcher, CDEvent *event) { + + }]; + +Or use all the glory-all-options initiator: + + self.events = [[CDEvents alloc] initWithURLs: + block:^(CDEvents *watcher, CDEvent *event) { + + } + onRunLoop:[NSRunLoop currentRunLoop] + sinceEventIdentifier:kCDEventsSinceEventNow + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS + excludeURLs: + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; + +See the test app (`TestApp`) for an example on how to use the framework. + +### Delegate based ### +***This is the same behavior as pre ARC and blocks.*** 1. Add CDEvents to your project, * either by compiling the project and dragging the `CDEvents.framework` into your project or * by dragging the entire CDEvents project into your project as a sub-project. 2. Import the `CDEvents.h` header where you need it. 3. Import the `CDEventsDelegate.h` header where you need it (i.e. in the file which declares your delegate). -4. See the test app (`TestApp`) for details on how to use the framework. Essentially it boils down to, - 1. Implement the delegate method `-URLWatcher:eventOccurred:`. - 2. Set up your `CDEvents` instance. +4. Implement the delegate (`-URLWatcher:eventOccurred:`) and create your `CDEvents` instance. +5. Zero out the delegate when you no longer need it. -` ` +Example code: self.events = [[CDEvents alloc] initWithURLs: - delegate: - onRunLoop:[NSRunLoop currentRunLoop] - sinceEventIdentifier:kCDEventsSinceEventNow - notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY - ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS - excludeURLs: - streamCreationFlags:kCDEventsDefaultEventStreamFlags]; - -**Important:** Since we have 10.6 set as the deployment target automatic zeroing of weak references is not available and as such 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: + onRunLoop:[NSRunLoop currentRunLoop] + sinceEventIdentifier:kCDEventsSinceEventNow + notificationLantency:CD_EVENTS_DEFAULT_NOTIFICATION_LATENCY + ignoreEventsFromSubDirs:CD_EVENTS_DEFAULT_IGNORE_EVENT_FROM_SUB_DIRS + excludeURLs: + streamCreationFlags:kCDEventsDefaultEventStreamFlags]; -For more details please refer to the documentation in the header files and the section "API documentation" below. +See the test app (`TestApp`) for an example on how to use the framework. -## What differentiates CDEvents from SCEvents then? ## -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. +**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.) -Another difference between `CDEvents` and `SCEvents` is that `CDEvents` is available for both manual memory management and environments using garbage collection. +For more details please refer to the documentation in the header files and the section "API documentation" below. -So I've written some of the code from scratch and "borrowed" some from `SCEvents`. ## API documentation ## 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. -## Authors ## +## Author ## -* Aron Cedercrantz +* [Aron Cedercrantz](http://github.com/rastersize) ## License ## The code is released under the [MIT-license](http://www.opensource.org/licenses/mit-license.php). -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). +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) or a [message via GitHub](http://github.com/inbox/new/rastersize). From beb5d7114c092a5b99f964a1f684c1740abf0977 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 2 Nov 2011 14:40:30 +0100 Subject: [PATCH 15/32] Add script to generate documentation using appledoc. --- CDEvents.xcodeproj/project.pbxproj | 1 + api.appledoc.sh | 45 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100755 api.appledoc.sh diff --git a/CDEvents.xcodeproj/project.pbxproj b/CDEvents.xcodeproj/project.pbxproj index 3e9ef3d..1dc0a23 100644 --- a/CDEvents.xcodeproj/project.pbxproj +++ b/CDEvents.xcodeproj/project.pbxproj @@ -243,6 +243,7 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 0420; + ORGANIZATIONNAME = "Aron Cedercrantz"; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */; compatibilityVersion = "Xcode 3.2"; diff --git a/api.appledoc.sh b/api.appledoc.sh new file mode 100755 index 0000000..8d751bf --- /dev/null +++ b/api.appledoc.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +## +# USAGE +# ./api.appledoc.sh [version-string] +# +# Execute it from the root of the CDEvents project. + + +PROJECT_VERSION="HEAD" +if [ "$#" -gt "0" ] +then + PROJECT_VERSION=$1 +fi + +API_DOCS_DIR="./api/appledoc" +#HEADER_FILES=`find . -name '*.h'` +HEADER_FILES=`ls *.h` + + +echo "API documentation generator for CDEvents v1" +echo "Will save generated documentation to \"${API_DOCS_DIR}\"" +echo "Removing old API documentation" +rm -r $API_DOCS_DIR/html 2> /dev/null +rm -r $API_DOCS_DIR/docset 2> /dev/null + +echo "Will generate API documentation based on:" +echo ${HEADER_FILES} + +echo "Generating for version \"${PROJECT_VERSION}\"..." +appledoc \ + --output ${API_DOCS_DIR} \ + --project-name "CDEvents" \ + --project-version ${PROJECT_VERSION} \ + --project-company "Aron Cedercrantz" \ + --company-id "com.cedercrantz" \ + --create-html \ + --keep-intermediate-files \ + --no-install-docset \ + ${HEADER_FILES} +echo "Done!" + +echo "You can open the HTML documentation with:" +echo "\"open ${API_DOCS_DIR}/html/index.html\"" + From 694b652dcf979b4f8d820b23ae721b9fdb98f9a6 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 2 Nov 2011 14:41:00 +0100 Subject: [PATCH 16/32] Add license file. --- LICENSE | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..abd9afa --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2010, 2011 Aron Cedercrantz + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. From 677958e4832d7ce2bec3496244d6707c7835d353 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 2 Nov 2011 14:53:25 +0100 Subject: [PATCH 17/32] Update readme to reflect online documentation. --- README.mdown | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.mdown b/README.mdown index 7e02d35..e9466f4 100644 --- a/README.mdown +++ b/README.mdown @@ -74,6 +74,12 @@ For more details please refer to the documentation in the header files and the s ## API documentation ## +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. + +### appledoc ### +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. + +### Doxygen ### 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. ## Author ## From 3a4ae54bde78f8cb938c355b59965c2595bd1b0f Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 2 Nov 2011 16:53:34 +0100 Subject: [PATCH 18/32] Ignore "docs" directory. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de6dd78..1ae5be2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ build *~.xib api +docs From 84bcca96c395e979a03c5e27541fbba90f8fc7f6 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 2 Nov 2011 16:56:38 +0100 Subject: [PATCH 19/32] Update readme with link to new website. --- README.mdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.mdown b/README.mdown index e9466f4..1bd591e 100644 --- a/README.mdown +++ b/README.mdown @@ -1,6 +1,7 @@ # CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # ***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"). +Website: http://rastersize.github.com/CDEvents ## What is this? ## 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. From 860cd4e34a991d3b5ba606917cdbb9fa74ba7200 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 11 Dec 2011 20:50:55 +0100 Subject: [PATCH 20/32] Change the authors section in the readme. --- README.mdown | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.mdown b/README.mdown index 1bd591e..5423fdb 100644 --- a/README.mdown +++ b/README.mdown @@ -83,9 +83,8 @@ Run the script `api.appledoc.sh` from the root of the project. The script takes ### Doxygen ### 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. -## Author ## - -* [Aron Cedercrantz](http://github.com/rastersize) +## Contributors ## +See GitHubs [https://github.com/rastersize/CDEvents/contributors](contributors to rastersize/CDEvents) statistics page. ## License ## The code is released under the [MIT-license](http://www.opensource.org/licenses/mit-license.php). From 681cd3a51f39869ca72c452a3271d2777a4ff69d Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 11 Dec 2011 20:53:57 +0100 Subject: [PATCH 21/32] Fix contributors URL. --- README.mdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.mdown b/README.mdown index 5423fdb..5454602 100644 --- a/README.mdown +++ b/README.mdown @@ -84,7 +84,7 @@ Run the script `api.appledoc.sh` from the root of the project. The script takes 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. ## Contributors ## -See GitHubs [https://github.com/rastersize/CDEvents/contributors](contributors to rastersize/CDEvents) statistics page. +See GitHubs [contributors to rastersize/CDEvents](https://github.com/rastersize/CDEvents/contributors) statistics page. ## License ## The code is released under the [MIT-license](http://www.opensource.org/licenses/mit-license.php). From 1a476d19b3f986528f5ee17335cc6173b62ab00a Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Mon, 9 Jan 2012 12:38:08 +0100 Subject: [PATCH 22/32] Update README.mdown --- README.mdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.mdown b/README.mdown index 5454602..1bf8d32 100644 --- a/README.mdown +++ b/README.mdown @@ -30,7 +30,7 @@ Easy example code: }]; -Or use all the glory-all-options initiator: +Or use all the all-options initiator: self.events = [[CDEvents alloc] initWithURLs: block:^(CDEvents *watcher, CDEvent *event) { From aa9b6972d7ab952eb62354fc40797de6fad2f653 Mon Sep 17 00:00:00 2001 From: Sidney Just Date: Sun, 11 Mar 2012 11:58:23 +0100 Subject: [PATCH 23/32] Made CDEvents class create CDEvent objects with file URLs instead of normal URLs (allows easier comparison with NSURL objects returned by eg. NSFileManager) --- CDEvents.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CDEvents.m b/CDEvents.m index 964da70..094e5c4 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -317,7 +317,7 @@ static void CDEventsCallback( // We do this hackery to ensure that the eventPath string doesn't // contain any trailing slash. NSString *eventPath = [[eventPathsArray objectAtIndex:i] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSURL *eventURL = [NSURL URLWithString:eventPath]; + NSURL *eventURL = [NSURL fileURLWithPath:eventPath]; eventPath = [eventURL path]; // Ignore all events except for the URLs we are explicitly watching. From bcd28f5da9a4fc703f27524fcaab2ef5b03f8dac Mon Sep 17 00:00:00 2001 From: tonyxiao Date: Sun, 21 Oct 2012 19:17:03 -0700 Subject: [PATCH 24/32] Correctly handle path that contains spaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently spaces in path are escaped twice.  NSString *p = [@"/my folder" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] => @"/my%20folder" NSURL *u = [NSURL fileURLWithString:p] => file://localhost/my%2520folder NSString *p2 = [u path] => @"/my%20folder" @"/my%20folder" != @"/my folder" Using `stringByStandardizingPath` will still guarantee that eventPath doesn't contain trailing slash. --- CDEvents.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CDEvents.m b/CDEvents.m index 094e5c4..1697a5b 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -316,9 +316,8 @@ static void CDEventsCallback( // We do this hackery to ensure that the eventPath string doesn't // contain any trailing slash. - NSString *eventPath = [[eventPathsArray objectAtIndex:i] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSURL *eventURL = [NSURL fileURLWithPath:eventPath]; - eventPath = [eventURL path]; + NSURL *eventURL = [NSURL fileURLWithPath:[[eventPathsArray objectAtIndex:i] stringByStandardizingPath]]; + NSString *eventPath = [eventURL path]; // Ignore all events except for the URLs we are explicitly watching. if ([watcher ignoreEventsFromSubDirectories]) { From a10aa140de50a079a2e03cc5b685df6d0a491b06 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:16:54 +0100 Subject: [PATCH 25/32] Remove link to GitHub messages. - That was removed some time ago. Signed-off-by: Aron Cedercrantz --- README.mdown | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.mdown b/README.mdown index 1bf8d32..fa790d3 100644 --- a/README.mdown +++ b/README.mdown @@ -1,22 +1,22 @@ -# CDEvents ![Project status](http://stillmaintained.com/rastersize/CDEvents.png) # +# CDEvents ***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"). Website: http://rastersize.github.com/CDEvents -## What is this? ## +## What is this? 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. -## Requirements ## +## Requirements 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. 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. -## Usage ## +## Usage You can use either the block based version (recommended) or the delegate based. Using both systems at the same time is not supported. -### Block based (recommended) ### +### Block based (recommended) 1. Add CDEvents to your project, * either by compiling the project and dragging the `CDEvents.framework` into your project or * by dragging the entire CDEvents project into your project as a sub-project. @@ -45,7 +45,7 @@ Or use all the all-options initiator: See the test app (`TestApp`) for an example on how to use the framework. -### Delegate based ### +### Delegate based ***This is the same behavior as pre ARC and blocks.*** 1. Add CDEvents to your project, @@ -74,19 +74,19 @@ See the test app (`TestApp`) for an example on how to use the framework. For more details please refer to the documentation in the header files and the section "API documentation" below. -## API documentation ## +## API documentation 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. -### appledoc ### +### appledoc 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. -### Doxygen ### +### Doxygen 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. -## Contributors ## +## Contributors See GitHubs [contributors to rastersize/CDEvents](https://github.com/rastersize/CDEvents/contributors) statistics page. -## License ## +## License The code is released under the [MIT-license](http://www.opensource.org/licenses/mit-license.php). -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) or a [message via GitHub](http://github.com/inbox/new/rastersize). +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). From 99c3333427f39a15d52db84841fff808cb044ed6 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:17:28 +0100 Subject: [PATCH 26/32] Add podspec by @dwlnetnl (#13). Signed-off-by: Aron Cedercrantz --- CDEvents.podspec | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CDEvents.podspec diff --git a/CDEvents.podspec b/CDEvents.podspec new file mode 100644 index 0000000..e9738fa --- /dev/null +++ b/CDEvents.podspec @@ -0,0 +1,13 @@ +Pod::Spec.new do |s| + s.name = "CDEvents" + s.version = "1.1.2" + s.summary = "An Objective-C wrapper for Mac OS X’s FSEvents C API." + s.homepage = "http://rastersize.github.com/CDEvents" + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.author = { "Aron Cedercrantz" => "aron@cedercrantz.se" } + s.source = { :git => "https://github.com/rastersize/CDEvents.git", :tag => "1.1.2" } + s.platform = :osx, '10.5' + s.source_files = '*.{h,m}' + s.framework = 'CoreServices' + s.requires_arc = true +end \ No newline at end of file From 0a464c498ffc20ee0fabd1a44452247ce81b9a60 Mon Sep 17 00:00:00 2001 From: Anner van Hardenbroek Date: Wed, 21 Nov 2012 20:28:45 +0100 Subject: [PATCH 27/32] Fix ARC setting in podspec. --- CDEvents.podspec | 1 - 1 file changed, 1 deletion(-) diff --git a/CDEvents.podspec b/CDEvents.podspec index e9738fa..08a6671 100644 --- a/CDEvents.podspec +++ b/CDEvents.podspec @@ -9,5 +9,4 @@ Pod::Spec.new do |s| s.platform = :osx, '10.5' s.source_files = '*.{h,m}' s.framework = 'CoreServices' - s.requires_arc = true end \ No newline at end of file From 9d94cf031b856dd4e1025216cf77df865600a324 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:31:59 +0100 Subject: [PATCH 28/32] Update Xcode project. - Change SDK to latest Mac OS X (decided by your Xcode version) instead of fixed at 10.7. - Enables a few more warnings. - Removes some stuff which is no longer used. Signed-off-by: Aron Cedercrantz --- CDEvents.xcodeproj/project.pbxproj | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/CDEvents.xcodeproj/project.pbxproj b/CDEvents.xcodeproj/project.pbxproj index 1dc0a23..e9acfd4 100644 --- a/CDEvents.xcodeproj/project.pbxproj +++ b/CDEvents.xcodeproj/project.pbxproj @@ -242,7 +242,7 @@ 0867D690FE84028FC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0420; + LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Aron Cedercrantz"; }; buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "CDEvents" */; @@ -330,12 +330,12 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_OBJC_ARC = YES; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_ENABLE_OBJC_GC = unsupported; GCC_MODEL_TUNING = ""; GCC_OPTIMIZATION_LEVEL = 0; @@ -354,6 +354,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_OBJC_ARC = YES; + COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -374,16 +375,21 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx10.7; + SDKROOT = macosx; }; name = Debug; }; @@ -391,15 +397,19 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_SSE3_EXTENSIONS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; - PREBINDING = NO; RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = macosx10.7; + SDKROOT = macosx; }; name = Release; }; @@ -407,6 +417,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_GC = unsupported; @@ -433,6 +444,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_ENABLE_OBJC_GC = unsupported; From a3afd7be128269f2badc4e45e6bab1e01b9073b4 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:33:24 +0100 Subject: [PATCH 29/32] Add compile time check of ARC and blocks. Signed-off-by: Aron Cedercrantz --- CDEvents.m | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CDEvents.m b/CDEvents.m index 1697a5b..279d9e7 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -10,6 +10,19 @@ #import "CDEventsDelegate.h" +#ifndef __has_feature + #define __has_feature(x) 0 +#endif + +#if !__has_feature(objc_arc) + #error CDEvents must be built with ARC. +#endif + +#if !__has_feature(blocks) + #error CDEvents must be built with support for blocks. +#endif + + #pragma mark CDEvents custom exceptions NSString *const CDEventsEventStreamCreationFailureException = @"CDEventsEventStreamCreationFailureException"; From 46f63c8ccd34fe51f6093189e40a996a11078d7c Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:42:39 +0100 Subject: [PATCH 30/32] Update podspec to 1.2.0. - This version requires ARC and blocks. It does not support garbage collection, for that please see 1.1.x. Signed-off-by: Aron Cedercrantz --- CDEvents.podspec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CDEvents.podspec b/CDEvents.podspec index 08a6671..f7f85d0 100644 --- a/CDEvents.podspec +++ b/CDEvents.podspec @@ -1,12 +1,13 @@ Pod::Spec.new do |s| s.name = "CDEvents" - s.version = "1.1.2" + s.version = "1.2.0" s.summary = "An Objective-C wrapper for Mac OS X’s FSEvents C API." s.homepage = "http://rastersize.github.com/CDEvents" s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { "Aron Cedercrantz" => "aron@cedercrantz.se" } - s.source = { :git => "https://github.com/rastersize/CDEvents.git", :tag => "1.1.2" } - s.platform = :osx, '10.5' + s.source = { :git => "https://github.com/rastersize/CDEvents.git", :tag => "1.2.0" } + s.platform = :osx, '10.6' s.source_files = '*.{h,m}' s.framework = 'CoreServices' + s.requires_arc = true end \ No newline at end of file From eeba752b5b56ba042c14318c32c9e53d6794b200 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:45:20 +0100 Subject: [PATCH 31/32] Change framework version to 1.2.0. Signed-off-by: Aron Cedercrantz --- Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Info.plist b/Info.plist index c2fd20c..fc9889f 100644 --- a/Info.plist +++ b/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.2 + 1.2.0 CFBundleSignature ???? CFBundleVersion - 1.1.2 + 1.2.0 NSPrincipalClass From 5beb7cda791537bc956d7a09ec89371bb73e198b Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Wed, 21 Nov 2012 20:47:44 +0100 Subject: [PATCH 32/32] Bump copyright years. - Also add missing license header to CDEvents.m. Signed-off-by: Aron Cedercrantz --- CDEvent.h | 2 +- CDEvent.m | 2 +- CDEvents.h | 2 +- CDEvents.m | 34 +++++++++++++++++++++++++++------- CDEventsDelegate.h | 4 ++-- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/CDEvent.h b/CDEvent.h index 3b1efd5..55b2934 100644 --- a/CDEvent.h +++ b/CDEvent.h @@ -1,7 +1,7 @@ /** * CDEvents * - * Copyright (c) 2010 Aron Cedercrantz + * Copyright (c) 2010-2012 Aron Cedercrantz * http://github.com/rastersize/CDEvents/ * * Permission is hereby granted, free of charge, to any person diff --git a/CDEvent.m b/CDEvent.m index ee98d02..d790443 100644 --- a/CDEvent.m +++ b/CDEvent.m @@ -1,7 +1,7 @@ /** * CDEvents * - * Copyright (c) 2010 Aron Cedercrantz + * Copyright (c) 2010-2012 Aron Cedercrantz * http://github.com/rastersize/CDEvents/ * * Permission is hereby granted, free of charge, to any person diff --git a/CDEvents.h b/CDEvents.h index 34feda1..8162af4 100644 --- a/CDEvents.h +++ b/CDEvents.h @@ -1,7 +1,7 @@ /** * CDEvents * - * Copyright (c) 2010 Aron Cedercrantz + * Copyright (c) 2010-2012 Aron Cedercrantz * http://github.com/rastersize/CDEvents/ * * Permission is hereby granted, free of charge, to any person diff --git a/CDEvents.m b/CDEvents.m index 279d9e7..6c4ae39 100644 --- a/CDEvents.m +++ b/CDEvents.m @@ -1,10 +1,30 @@ -// -// CDEvents.m -// CDEvents -// -// Created by Aron Cedercrantz on 03/04/10. -// Copyright 2010 Aron Cedercrantz. All rights reserved. -// +/** + * CDEvents + * + * Copyright (c) 2010-2012 Aron Cedercrantz + * http://github.com/rastersize/CDEvents/ + * + * 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: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 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. + */ #import "CDEvents.h" diff --git a/CDEventsDelegate.h b/CDEventsDelegate.h index ab1cc40..1e44aef 100644 --- a/CDEventsDelegate.h +++ b/CDEventsDelegate.h @@ -1,7 +1,7 @@ /** - * SCEvents + * CDEvents * - * Copyright (c) 2010 Aron Cedercrantz + * Copyright (c) 2010-2012 Aron Cedercrantz * http://github.com/rastersize/CDEvents/ * * Permission is hereby granted, free of charge, to any person