Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
463 views
in Technique[技术] by (71.8m points)

objective c - iTunes File Sharing app: realtime monitoring for incoming datas

I'm working on iOS project that supports iTunes file sharing feature. The goal is realtime tracking incoming/changed data's.

I'm using (kinda modified) DirectoryWatcher class from Apple's sample code and also tried this source code.

The data is NSBundle (*.bundle) and some bundles are in 100-500 MB ranges, depends on its content, some video/audio stuff. The bundles has xml based descriptor file in it.

The problem is any of these codes above fires notification or whatever else when the data just started copying and but not when the copy/change/remove process finished completely.

Tried next:

checking file attributes:

NSDictionary *fileAttrs = [[NSFileManager defaultManager] attributesOfItemAtPath:[contURL path] error:nil];
BOOL fileBusy = [[fileAttrs objectForKey:NSFileBusy] boolValue];

looking for the fileSize changes:

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");
    }
);

any other solutions?

The solution above works great for bin files, but not for .bundle (as .bundle files are directory actually). In order to make it work with .bundle, you should iterate each file inside .bundle

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use GCD's dispatch sources mechanism - using it you can observe particular system events (in your case, this is vnode type events, since you're working with file system). To setup observer for particular directory, i used code like this:

- (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(@"

");
        });

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

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

    return source;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...