I'm using FSEvents to monitor a directory, and whenever the directory changes I call a block which I originally passed into the FSEventStreamContext of the FSEventStreamRef. How do I release the block when it is time to stop monitoring the directory? Code below for reference.
void fsevents_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
void (^block)() = (__bridge void (^)())(clientCallBackInfo);
block();
}
- (FSEventStreamRef)startObserving:(NSString *)path block:(void(^)())block {
void *ptr = (void *)CFBridgingRetain(block); // NOTE: the block is retained
FSEventStreamContext context = { 0, ptr, NULL, NULL, NULL };
FSEventStreamRef stream = FSEventStreamCreate(NULL, fsevents_callback, &context, (__bridge CFArrayRef)@[path], kFSEventStreamEventIdSinceNow, 10, kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagIgnoreSelf);
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
return stream;
}
- (void)stopObserving:(FSEventStreamRef)stream {
// HELP: the block should be released here. can I get it through FSEvents?
FSEventStreamStop(stream);
FSEventStreamInvalidate(stream);
FSEventStreamRelease(stream);
}
FSEventStreamContext
has member variables for functions to retain and release theinfo
pointer, which in your example is yourvoid *
block pointer.Via Apple's FSEvents reference:
First, retain. Since you need to cast the block to
void *
forFSEventStreamContext
anyway, I think it's fine to continue usingCFBridgingRetain()
in yourstartObserving:
method. No retain callback function is needed.For release, try this callback function:
Then try changing your
FSEventStreamContext
declaration to:That should release your block when
stopObserving:
is called.