Pointer lost in FSEventStream callback (ObjC and ARC)

I managed to get the basics of FSEventStream so that I can view the folder for new file events. Unfortunately, the callback link that I pass to FSEventStreamCreate () is lost / damaged / not saved, so I cannot access the data object that I need too. Here key code blocks:

FileWatcher.m: (Configure FSEvent Stream)

FSEventStreamContext context; //context.info = (__bridge_retained void *)(uploadQueue); // this didn't help context.info = CFBridgingRetain(uploadQueue); context.version = 0; context.retain = NULL; context.release = NULL; context.copyDescription = NULL; /* Create the stream, passing in a callback */ stream = FSEventStreamCreate(NULL, &FileWatcherCallback, &context, pathsToWatch, kFSEventStreamEventIdSinceNow, /* Or a previous event ID */ latency, kFSEventStreamCreateFlagFileEvents /* Also add kFSEventStreamCreateFlagIgnoreSelf if lots of recursive callbacks */ ); 

Filewatcher.m: FileWatcherCallback

 void FileWatcherCallback( ConstFSEventStreamRef streamRef, FSEventStreamContext *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { int i; char **paths = eventPaths; // Retrieve pointer to the download Queue! NSMutableDictionary *queue = (NSMutableDictionary *)CFBridgingRelease(clientCallBackInfo->info); // Try adding to the queue [queue setValue:@"ToDownload" forKey:@"donkeytest" ]; ... } 

When this callback function is running, I can get the file paths in order, but the clientCallBackInfo-> info pointer to NSMutableDictionary now points to a different memory address than when setting up the stream. When I then try to add to the dictionary, I get an exception (setValue string).

Do I need to handle pointers in any other way? Any help is appreciated. (I am on Xcode 4.5.1 with standard build settings, including ARC.)

+4
source share
2 answers

The second argument to the callback function is void *info (which is context.info ), not a pointer to the FSEventStreamContext context structure.

So this code should work to get the correct pointer:

 void FileWatcherCallback( ConstFSEventStreamRef streamRef, void *info, // <-- this is context.info size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { // ... // Retrieve pointer to the download queue: NSMutableDictionary *queue = CFBridgingRelease(info); // ... } 

Note: It seems to me that there is another problem using CFBridgingRetain() / CFBridgingRelease() . The save counter of the uploadQueue object will decrease every time the callback function is called. This leads to a failure very quickly.

Probably better to use

 context.info = (__bridge void *)(uploadQueue); 

to create an event flow and

 NSMutableDictionary *queue = (__bridge NSMutableDictionary *)info; 

in the callback function. You only need to make sure that you keep a strong link to uploadQueue while using the event stream.

+2
source

I have never used this API, but looking at examples on the Internet, it seems normal to pass self to this pointer. Then, if uploadQueue is an instance variable, you can make it accessible through a property (and have the added benefit of accessing everything in your class instance).

0
source

All Articles