Mat*_*att 4 nsdata grand-central-dispatch ios automatic-ref-counting
我正在尝试创建一个具有唯一名称的文件并在后台向其中写入数据。
mktemp说Whenever it is possible, mkstemp() should be used instead, since it does not have the race condition.
mkstemp在打开的文件描述符中使用结果,因此dispatch_write似乎很明显。
现在NSData必须包裹在dispatch_data_tusing中dispatch_data_create。必须注意释放需要释放的内存,保留必须保留的内存。在 ARC 下,这一点不太明显。
+ (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]);
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是:
mktemp使用而不担心安全/竞争条件吗?NSDatawriteToFile:options:error:dispatch_data_createOK 以避免不必要的复制(保留指向缓冲区的指针NSData)?mkstemps一起使用吗dispatch_write?NSData保持dispatch_data_t有效吗?有这个必要吗?ARC在这里做什么?dispatch_io_close?这并不是真正的目的dispatch_write(dispatch_data一般而言)。正如您所发现的,dispatch_data重点是功能和性能,而不是易用性。你有一个如此简单的问题。
另请注意,您正在讨论的竞争条件与正在您的临时目录中快速创建文件的主动攻击者有关。攻击过程是这样的:
/tmp您和 Eve 都可以读写的临时文件。/tmp并发现某些文件名不存在这是对 Unix 系统的真正攻击。很明显,这并不是针对 iOS 系统的真正攻击。这并不意味着您不应该使用mkstemp. 你应该。但重要的是要了解您要防范的是什么。这不是“哎呀;我与自己相撞”的竞争条件,除非您每秒生成数百个文件(不要这样做)。
好的,那你要怎么做呢?Matt Gallagher 在 Cocoa with Love 中有一个很好的例子: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];
Run Code Online (Sandbox Code Playgroud)
现在,最后,您会看到 Matt 创建了一个文件名和一个NSFileHandle. 两者都可以很好地使用。您可以使用NSData方法写入文件名,也可以使用NSFileHandlewrite 方法。此时使用文件名不存在竞争条件,因为该文件已经存在并且归您所有。
要在后台编写此内容,只需将其粘贴到一个dispatch_async块中即可。
| 归档时间: |
|
| 查看次数: |
1056 次 |
| 最近记录: |