简体   繁体   English

iOS中的中断队列或文件写入操作

[英]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. 我在iPhone上处理大图像,因此将它们保存到磁盘可能要花费几秒钟的时间,有时还需要在尚未完成保存时删除图像。 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. writeToFile:atomically:将要writeToFile:atomically:将所有数据写入文件。 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. 您最好抓住NSFileHandle并快速写入数据的子部分,在每次原子写入之后,您可以检查用户是否已请求取消保存。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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