简体   繁体   中英

Interrupt queue or file write operation in iOS

I work with large images on the iPhone, so saving them to disk can take several seconds, and sometimes an instruction to delete the image comes when it hasn't finished saving. I would like to interrupt the saving process and delete the file inmediatly, without waiting for it to save first, but I can't find any way to interrupt the queue or the saving operation.

@interface YMSavedImage : NSObject {
    UIImage *image;
    NSString *path;
    dispatch_queue_t imageAccess;
    ...
}
@end

@implementation YMSavedImage

- (id)init
{
    ...
    imageAccess = dispatch_queue_create("imageAccessQueue", NULL);
    ...
}

- (void)save
{
    dispatch_async(imageAccess, ^(void) {
        [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];  // This takes several seconds.
    });
}

- (void)delete
{
    dispatch_sync(imageAccess, ^(void) {
        if ([fileManager fileExistsAtPath:path]) {
            [fileManager removeItemAtPath:path error:NULL];
        }
    });
}

...

@end

writeToFile:atomically: is going to want to write all of the data to file in one shot. You would be better off grabbing an NSFileHandle and quickly writing subsections of the data, after each atomic write you could check to see if the user has requested to cancel saving.

I'd suggest something like:

- (void)save 
{
    dispatch_async(imageAccess, ^{

        // Create an empty file to populate
        [[NSFileManager defaultManager] createFileAtPath:_imageFilePath contents:nil attributes:nil];

        // Grab a handle on the file
        NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:_imageFilePath];

        NSData *imageData = UIImagePNGRepresentation(_image);

        // Store how long the image is
        NSUInteger totalLength = [imageData length];

        // Store how many chunks we should need with the set kDesiredChunkSize
        NSUInteger chunks = totalLength / kDesiredChunkSize;

        NSUInteger i = 0;

        // Walk through the image chunk by chunk and check if we are cancelled after each atomic operation
        for (i = 0; i < chunks; i++) {
            [handle seekToEndOfFile];
            [handle writeData:[imageData subdataWithRange:NSMakeRange(i * kDesiredChunkSize, kDesiredChunkSize)]];

            if (__userCancelledSave) { // The user asked us to cancel,
                [[NSFileManager defaultManager] removeItemAtPath:_imageFilePath error:nil]; // FIXME: Handle this error
                return;
            }
        }

        // Write any remaining data that's less than one chunk in size
        NSUInteger sizeDifference = totalLength - (chunks * kDesiredChunkSize);

        if (sizeDifference > 0) {
            [handle seekToEndOfFile];
            [handle writeData:[imageData subdataWithRange:NSMakeRange(chunks * kDesiredChunkSize, sizeDifference)]];
        }
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM