Using dispatch_write to write NSData to a unique file in the background in ARC

I am trying to create a file with a unique name and write data to it in the background.

mktemp He speaks Whenever it is possible, mkstemp() should be used instead, since it does not have the race condition.

Usage mkstempleads to an open file descriptor, so dispatch_writeit seems obvious.

Now NSDatashould be enclosed in dispatch_data_tusing dispatch_data_create. Care must be taken of the free memory that must be freed and the storage of the memory that must be retained. In ARC, this is less obvious.

+ (void) createUnique:(NSData*)content name:(NSString*)name
            extension:(NSString*)extension
           completion:(void (^)(NSURL* url, NSError* error))completion {
    dispatch_queue_t queue = dispatch_get_global_queue(
                                       DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_data_t data = dispatch_data_create(content.bytes, content.length,
                                                queue, ^{});
    // dispatch_data_create() copies the buffer if DISPATCH_DATA_DESTRUCTOR_DEFAULT
    // (= NULL) is specified, and attempts to free the buffer if
    // DISPATCH_DATA_DESTRUCTOR_FREE is specified, so an empty destructor is
    // specified.
    dispatch_fd_t descriptor;

    // Ignore details of creating the template C string
    strcpy(nameCString, templateCString);
    descriptor = mkstemps(nameCString, extensionLength);
    free(nameCString);

    if (descriptor != -1) {
        dispatch_write(descriptor, data, queue,
                       ^(dispatch_data_t data, int error) {
                           NSData* strongContent = content;
                           // Will this keep the NSData reference until the
                           // write is finished?

                           if (error) {
                               completion(nil, [NSError
                                                errorWithDomain:NSURLErrorDomain
                                                code:error userInfo:nil]);
                           } else {
                               // Ignore details of getting path from nameCString.
                               completion([NSURL URLWithString:path], nil);
                           }

                           // How does the file get closed?
                       });
    } else {
        completion(nil, [NSError errorWithDomain:NSURLErrorDomain code:errno
                                        userInfo:nil]);
    }
}

So the questions are:

  • Is it even necessary? Should I be mktempused with NSData writeToFile:options:error:and not worry about safety / race conditions?
  • dispatch_data_create , ( NSData)?
  • , mkstemps, dispatch_write?
  • NSData dispatch_data_t ? ? ARC?
  • ? dispatch_io_close?
+4
1

, dispatch_write ( dispatch_data ). , dispatch_data , . .

, , , , . :

  • . Eve () .
  • /tmp, Eve .
  • /tmp ,
  • , Eve , , . ( ).
  • , Eve.
  • . .

Unix-. , iOS. , mkstemp. . , . ", ", ( ).

, ? Cocoa : Cocoa. , :

NSString *tempFileTemplate =
    [NSTemporaryDirectory() stringByAppendingPathComponent:@"myapptempfile.XXXXXX"];
const char *tempFileTemplateCString =
    [tempFileTemplate fileSystemRepresentation];
char *tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
strcpy(tempFileNameCString, tempFileTemplateCString);
int fileDescriptor = mkstemp(tempFileNameCString);

if (fileDescriptor == -1)
{
    // handle file creation failure
}

// This is the file name if you need to access the file by name, otherwise you can remove
// this line.
tempFileName =
    [[NSFileManager defaultManager]
        stringWithFileSystemRepresentation:tempFileNameCString
        length:strlen(tempFileNameCString)];

free(tempFileNameCString);
tempFileHandle =
    [[NSFileHandle alloc]
        initWithFileDescriptor:fileDescriptor
        closeOnDealloc:NO];

, , , , NSFileHandle. . NSData , NSFileHandle write. , , .

, dispatch_async.

+4

All Articles