4

我已經成功獲取FSEventStream的基礎知識,使我能夠觀察新文件事件的文件夾。不幸的是,我傳入FSEventStreamCreate()的回調引用正在丟失/損壞/未保留,因此我無法訪問我需要的數據對象。這是關鍵的代碼塊:指針在FSEventStream回調中丟失(ObjC和ARC)

FileWatcher.m:(設立FSEvent流)

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" ]; 
    ... 
} 

當這個回調函數被觸發,我可以很好地獲取文件路徑,但指向NSMutableDictionary的clientCallBackInfo-> info指針現在指向與設置流時不同的內存地址。 當我然後嘗試並添加到字典,我得到一個異常拋出(setValue線)。

我是否需要以某種方式處理指針?任何幫助將非常感激。 (我在Xcode 4.5.1上使用默認的構建設置,包括ARC)。

+0

什麼是'uploadQueue'? – trojanfoe

+0

@Steen:你應該接受Martin R的答案,或者解釋爲什麼這不能解決你的問題 –

回答

2

回調函數的第二個參數是void *info(它是context.info),而不是指向FSEventStreamContext context結構的指針。

所以這個代碼應工作,以獲得正確的指針:

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); 
    // ... 
} 

備註:在我看來,這可能是您的CFBridgingRetain()/CFBridgingRelease()使用另一個問題。 uploadQueue對象的保留計數將每次減少調用回調函數。這很快就會導致崩潰。

這可能是更好的使用

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

爲創建事件流,並

NSMutableDictionary *queue = (__bridge NSMutableDictionary *)info; 

在回調函數。只要使用事件流,您只需確保您保持對uploadQueue的強烈參考。

0

我從來沒有用過這個API,但是在網上看例子,在這個指針中通過self似乎是正常的。那麼如果uploadQueue是一個實例變量,你可以通過一個屬性使它可訪問(並且具有訪問類實例中所有內容的附加優勢)。