2013-03-14 115 views
3

我想在表格视图中为每一行下载图像,所以我编写了一个方法来通过使用块来完成此操作。什么是嵌套块中保留对象的正确方法

我认为indexPath和tableView可能不会被完成块复制,因为它们在If语句中使用。所以我在完成块执行前保留它们。

而且代码:

- (void)downloadImageAtURL:(NSString *)imageURL name:(NSString *)name serial:(BOOL)serial forTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath 
{ 
    NSMutableDictionary *cachedImagesOfURLs = self.cachedImagesOfURLs; 

    UITableView *strongTableView = [tableView retain]; 
    NSIndexPath *strongIndexPath = [indexPath retain]; 

    [self.downloadManager downloadImageAtURL:imageURL 
            identifier:[self identifierForIndexPath:indexPath] 
             serial:serial 
            completion:^(UIImage *image) { 
             if (image) { 
              [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
               [cachedImagesOfURLs setObject:image forKey:imageURL]; 

               id cell = [strongTableView cellForRowAtIndexPath:strongIndexPath]; 
               if ([cell respondsToSelector:@selector(didDownloadImage:withName:)]) { 
                [cell didDownloadImage:image withName:name]; 
               } 
              }]; 
             } 

             [strongTableView release]; 
             [strongIndexPath release]; 
            }]; 
} 

但结果是,当完成块EXCUTE并尝试创建一个块和主线程中运行它,它崩溃。调试器打印“- [XXX cellForRowAtIndexPath:]:无法识别的选择器发送到实例”。我似乎tableView和indexPath被释放。

但我不知道为什么,我试图挽留他们。有人能告诉我如何防止这种事故发生?非常感谢你!

+1

尝试self.tableView – 2013-03-14 04:17:11

+0

不过是要保留这一点,需要你有没有尝试过的方法?变量直接在块?我认为它可能工作 – 2013-03-14 04:22:43

+0

块复制它需要的变量。不需要明确保留。只要避免在块中提及self.downloadManager。 – danh 2013-03-14 04:24:28

回答

1

我觉得这是不够

- (void)downloadImageAtURL:(NSString *)imageURL name:(NSString *)name serial:(BOOL)serial forTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath 
{ 
    NSMutableDictionary *cachedImagesOfURLs = self.cachedImagesOfURLs; 

    [self.downloadManager downloadImageAtURL:imageURL 
            identifier:[self identifierForIndexPath:indexPath] 
             serial:serial 
            completion:^(UIImage *image) { 
             if (image) { 
               [cachedImagesOfURLs setObject:image forKey:imageURL]; 

               id cell = [tableView cellForRowAtIndexPath:indexPath]; 
               if ([cell respondsToSelector:@selector(didDownloadImage:withName:)]) { 
                [cell didDownloadImage:image withName:name]; 
               } 
             } 
            }]; 
} 
+0

可能不需要为mainQueue添加操作,完成块本身可能在主线程上运行。 – danh 2013-03-14 04:32:06

+0

是的,这是正确的。它是绝对复制/粘贴 – 2013-03-14 04:44:29

+0

“完成块本身可能运行在主线程”是什么让你觉得呢? – newacct 2013-03-14 05:25:13

0

甚至更​​少的代码。不知道你指的码位如何工作的,但是从名字,我猜以下就足够了:

- (void)downloadImageAtURL:(NSString *)imageURL name:(NSString *)name serial:(BOOL)serial forTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath { 

    NSMutableDictionary *cachedImagesOfURLs = self.cachedImagesOfURLs; 

    [self.downloadManager downloadImageAtURL:imageURL identifier:[self identifierForIndexPath:indexPath] serial:serial completion:^(UIImage *image) { 
     if (image) { 
      [cachedImagesOfURLs setObject:image forKey:imageURL]; 
      id cell = [strongTableView cellForRowAtIndexPath:strongIndexPath]; 
      if ([cell respondsToSelector:@selector(didDownloadImage:withName:)]) { 
       [cell didDownloadImage:image withName:name]; 
      } 
     } 
    }]; 
} 
相关问题