Поток, созданный с помощью FSEventStreamCreate, равен нулю

#objective-c #macos #filesystems #macos-carbon #fsevents

#objective-c #macos #файловые системы #macos-carbon #fsevents

Вопрос:

Я хочу создать простой поток событий, чтобы прослушивать события, когда в каталоге происходят какие-либо изменения. Первым шагом является создание потока, но я получаю сообщение об ошибке при создании с использованием функции FSEventStreamCreate. Поиск в Google этой ошибки был бесполезен, я не могу понять, где ошибка.

 (CarbonCore.framework) FSEventStreamCreate: _FSEventStreamCreate: ERROR: (CFStringGetTypeID() != CFGetTypeID(cfStringRef)) (i = 0)
  

Мой код очень похож на тот, который присутствует в документации Apple

В любом случае, это мой код:

 static void gotEvent(ConstFSEventStreamRef stream, 
                 void *clientCallBackInfo, 
                 size_t numEvents, 
                 void *eventPathsVoidPointer, 
                 const FSEventStreamEventFlags eventFlags[], 
                 const FSEventStreamEventId eventIds[]
                 ) {

    NSLog(@"File Changed!");
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    NSString *fileInputPath = @"/tmp/mamma/ciao.txt";
    FSEventStreamRef stream = [self eventStreamForFileAtPath: fileInputPath];
}

- (FSEventStreamRef) eventStreamForFileAtPath: (NSString *) fileInputPath
{
    if (![[NSFileManager defaultManager] fileExistsAtPath:fileInputPath]) {
        @throw [NSException exceptionWithName: @"FileNotFoundException"
                                   reason:@"There is not file at path specified in fileInputPath"
                                 userInfo: nil];
    }
    CFStringRef fileInputDir = (CFStringRef)[fileInputPath stringByDeletingLastPathComponent];
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **) fileInputDir, 1, NULL);
    void *callbackInfo = NULL;
    CFAbsoluteTime latency = 3.0; /* Latency in seconds */

    FSEventStreamRef stream = FSEventStreamCreate(
                                                 NULL, 
                                                 amp;gotEvent, 
                                                 callbackInfo, 
                                                 pathsToWatch, 
                                                 kFSEventStreamEventIdSinceNow, 
                                                 latency, 
                                                 kFSEventStreamEventFlagNone
                                                 );

    return stream;
}
  

Ответ №1:

Попробуйте вместо этого этот код:

 - (FSEventStreamRef) eventStreamForFileAtPath: (NSString *) fileInputPath  {

   if (![[NSFileManager defaultManager] fileExistsAtPath:fileInputPath]) {
       @throw [NSException exceptionWithName:@"FileNotFoundException"
                                      reason:@"There is not file at path specified in fileInputPath"
                                    userInfo:nil];
   }

   NSString *fileInputDir = [fileInputPath stringByDeletingLastPathComponent];

   NSArray *pathsToWatch = [NSArray arrayWithObjects:fileInputDir, nil];

   void *appPointer = (void *)self;

   FSEventStreamContext context = {0, appPointer, NULL, NULL, NULL};

   NSTimeInterval latency = 3.0;

   FSEventStreamRef stream = FSEventStreamCreate(NULL,
                                                  amp;gotEvent,                                 
                                                  amp;context,                                 
                                                  (CFArrayRef) pathsToWatch,                                 
                                                  kFSEventStreamEventIdSinceNow,                                 
                                                  (CFAbsoluteTime) latency,                                 
                                                  kFSEventStreamCreateFlagUseCFTypes                                 
                                                  );

   FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
   FSEventStreamStart(stream);

   return stream;

}
  

Также взгляните на эту ссылку: Мониторинг изменений файлов с помощью API событий файловой системы. Он показывает вам, как отслеживать изменения файлов в вашем приложении Cocoa.

Комментарии:

1. С вашим кодом я, наконец, получаю действительный объект stream . Я не могу точно понять, почему ваш код работает, а мой нет! Единственное отличие, которое я вижу, заключается в том, что вы создаете NSArray вместо того, чтобы создавать непосредственно CFArrayRef . У вас также другой контекст, но, похоже, он не влияет на создание потока

2. Ваш метод будет работать, просто вы забыли поставить ссылочный оператор (amp;) fileInputDir перед CFArrayCreate функцией. Я также не вижу, чтобы вы вызывали FSEventStreamScheduleWithRunLoop() или FSEventStreamStart() . Вы также должны прочитать предоставленную мной ссылку, она покажет вам, как остановить и аннулировать поток после завершения.

3. Проблема заключалась в создании массива. FSEventStreamScheduleWithRunLoop() и FSEventStreamStart() присутствовали в другой части кода. Спасибо за вашу помощь

4. Есть идеи о том, как определить тип события папки, возникающего в папке в методе обратного вызова? Например: переименованный файл, созданный файл и т. Д.?

5. Для тех, кто сейчас сталкивается с этим ответом (как и я), кажется, что соответствующая ссылка сейчас: developer.apple.com/library/content/documentation/Darwin /…