在我目前的设计中,我有一个表示文件夹结构的tableview。当用户点击单元格时,会创建AFHTTPRequestOperation
以下载文件。当单元格当前显示当前下载状态时,下载文件:无/下载/下载。
下载状态设置在NSManagedObject
上,对应于每个单元格。在我的下载完成块中,我将下载状态设置为“已下载”标志。这样做的问题是,如果用户导航远离当前的tableview数据并导航到另一个,竞争块将设置错误的NSManagedObject
- 它会根据NSIndex
进行查找。
简而言之,我想知道如何将对象与AFHTTPRequestOperation
一起传递,以便在完成时可以对其执行操作。它可以像int或string一样简单,我可以根据此值执行NSPredicate
请求。
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[self.operations addObject:operation];
[self.inProgressDownloads addObject:indexPath];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *extension = [[self.selectedFile.name componentsSeparatedByString:@"."] lastObject];
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat: @"%@.%@", self.selectedFile.item_id, extension]];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
self.selectedFile.status = DOWNLOADING;
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"File downloaded to: %@", path);
self.selectedFile.status = DOWNLOADED;
self.selectedFile.is_stored = @YES;
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
self.selectedFile.status = DOWNLOAD_ERROR;
}];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
dispatch_async(dispatch_get_main_queue(), ^{
float percent = (float)totalBytesRead / (float)totalBytesExpectedToRead;
NSLog(@"totalBytesExpectedToRead %d", (int)(percent * 100));
});
}];
[operation start];
答案 0 :(得分:3)
简而言之,我想知道如何将对象与AFHTTPRequestOperation一起传递,以便在完成时可以对其执行操作。它可以像int或string一样简单,我可以根据此值执行NSPredicate请求。
这就是封闭/阻挡的力量发挥作用的地方。您不需要将任何特殊内容传递给块。您可以引用块中词汇可见的任何对象,并在块运行时可用。
来自Apple docs(具体而言,第2点):
Blocks通常代表小的,自包含的代码片段。因此,它们特别有用,可以封装可以同时执行的工作单元,或者集合中的项目,或者当另一个操作完成时作为回调。
块是传统回调函数的有用替代方法,主要有两个原因:
它们允许您在稍后在方法实现的上下文中执行的调用点编写代码。
因此,块通常是框架方法的参数。- 醇>
他们允许访问本地变量 您可以直接访问本地变量,而不是使用需要执行操作所需的所有上下文信息的数据结构的回调。
如果我理解你想要做什么,这应该有效:
TYPE_HERE* localSelectedFile = self.selectedFile;
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"File downloaded to: %@", path);
localSelectedFile.status = DOWNLOADED;
localSelectedFile.is_stored = @YES;
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
...
我执行self.selectedFile
时将operation
的值存储到局部变量中的位置;然后我将该局部变量用于块体。这是合法的(这是我所指的闭包的强大功能:它们自己保存有关其执行上下文的信息)并且会为您提供对您正在处理的对象的引用。
您可能会发现this对整体视图感兴趣。