iTunes文件共享应用程序:实时监控传入数据

Gal*_* Sh 5 filesystems objective-c ios

我正在开发支持iTunes文件共享功能的iOS项目.目标是实时跟踪传入/更改的数据.

我正在使用Apple的示例代码中的(有点修改过的) DirectoryWatcher类,并尝试了这个源代码.

数据是NSBundle(*.bundle),一些捆绑包在100-500 MB范围内,取决于其内容,一些视频/音频内容.bundle包含基于xml的描述符文件.

问题是上面的任何一个代码触发了火灾通知或其他任何其他数据刚刚开始复制时,而不是当复制/更改/删除过程完全完成时.

尝试下一个:

检查文件属性:

NSDictionary *fileAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[contURL path] error:nil];
BOOL fileBusy = [[fileAttrs objectForKey:NSFileBusy] boolValue];
Run Code Online (Sandbox Code Playgroud)

寻找fileSize变化:

dispatch_async(_checkQueue, ^{
    for (NSURL *contURL in tempBundleURLs) {
        NSInteger lastSize = 0;
        NSDictionary *fileAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[contURL path] error:nil];
        NSInteger fileSize = [[fileAttrs objectForKey:NSFileSize] intValue];

        do {
            lastSize = fileSize;
            [NSThread sleepForTimeInterval:1];

            fileAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[contURL path] error:nil];
            fileSize = [[fileAttrs objectForKey:NSFileSize] intValue];

            NSLog(@"doing job");
        } while (lastSize != fileSize);

        NSLog(@"next job");
    }
);
Run Code Online (Sandbox Code Playgroud)

还有其他方法吗?

上面的解决方案适用于bin文件,但不适用于.bundle(因为.bundle文件实际上是目录).为了使它与.bundle一起使用,你应该迭代.bundle中的每个文件

Ola*_*ane 8

您可以使用GCD的调度源机制 - 使用它可以观察特定的系统事件(在您的情况下,这是vnode类型的事件,因为您正在使用文件系统).要为特定目录设置观察者,我使用如下代码:

- (dispatch_source_t) fileSystemDispatchSourceAtPath:(NSString*) path
{
    int fileDescr = open([path fileSystemRepresentation], O_EVTONLY);// observe file system events for particular path - you can pass here Documents directory path
    //observer queue is my private dispatch_queue_t object
    dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fileDescr, DISPATCH_VNODE_ATTRIB| DISPATCH_VNODE_WRITE|DISPATCH_VNODE_LINK|DISPATCH_VNODE_EXTEND, observerQueue);// create dispatch_source object to observe vnode events
    dispatch_source_set_registration_handler(source, ^{
        NSLog(@"registered for observation");
        //event handler is called each time file system event of selected type (DISPATCH_VNODE_*) has occurred
        dispatch_source_set_event_handler(source, ^{

            dispatch_source_vnode_flags_t flags = dispatch_source_get_data(source);//obtain flags
            NSLog(@"%lu",flags);

            if(flags & DISPATCH_VNODE_WRITE)//flag is set to DISPATCH_VNODE_WRITE every time data is appended to file
            {
                NSLog(@"DISPATCH_VNODE_WRITE");
                NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
                float size = [[dict valueForKey:NSFileSize] floatValue];
                NSLog(@"%f",size);
            }
            if(flags & DISPATCH_VNODE_ATTRIB)//this flag is passed when file is completely written.
            {
                NSLog(@"DISPATCH_VNODE_ATTRIB");
                dispatch_source_cancel(source);
            }
            if(flags & DISPATCH_VNODE_LINK)
            {
                NSLog(@"DISPATCH_VNODE_LINK");
            }
            if(flags & DISPATCH_VNODE_EXTEND)
            {
                NSLog(@"DISPATCH_VNODE_EXTEND");
            }
            NSLog(@"file = %@",path);
            NSLog(@"\n\n");
        });

        dispatch_source_set_cancel_handler(source, ^{
            close(fileDescr);
        });
    });

    //we have to resume dispatch_objects
    dispatch_resume(source);

    return source;
}
Run Code Online (Sandbox Code Playgroud)