我对在像我这样的情况下使用异步块的最佳做法有疑问。
例如,我有两个控制器:(让它成为controller1和controller2)
我在控制器1内推送controller2:
controller2 * c = [[controller2 alloc] init];
[self.navigationController pushViewController:c animated:YES];
[c release];
controller2有一个实例变量:
@interface controller2 : UITableViewController{
UIImageView * imageView;
}
分配并释放它:
- (id)init{
...
imageView = [[UIImageView alloc] init];
...
}
- (void)dealloc{
[imageView release];
[super dealloc];
}
和controller2下载此imageView的图像:
- (void)viewDidLoad{
...
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:
^(NSURLResponse *response, NSData *data, NSError *error) {
UIImage * image = [[UIImage alloc] initWithData:data scale:[[UIScreen mainScreen] scale]];
imageView.image = image;
[image release];
}];
}
显然,用户可以按导航栏顶部的“后退”按钮,我们的controller2对象将通过此imageView发布。
情况:
下载开始;
控制器弹出(用户按下“后退”按钮)
下载结束,imageView.image =图片原因(?)EXC_BAD_ACCESS(因为imageView已发布)
那么,我应该做些什么来让我的代码变得很酷? 我喜欢积木!与NSURLConnection代表相比,这么多的乐趣和更少的代码/类。
块可能保留实例变量吗? (:OOO)
也许我应该在阻止之前保留我的实例变量并在块中释放它? (我觉得这很傻)
那么,使用这些块的最佳做法是什么? 也许我不应该在这种情况下使用块来使我的代码更好?
p.s。:我试图这样做:将NSOperationQueue作为实例变量,并停止dealloc中的所有任务..但这会杀死此块的优势:( 在这种情况下,最好将我的下载器类与委托一起使用;(无论如何代码太多了。
p.p.s .: 我知道我应该在弹出控制器后停止下载;但我不是这样的。 让它成为任何任务(例如,转换视频等,任何“沉重的”后台线程),即使用户离开了这个控制器也应该这样做,但如果它们还活着,它会使用一些实例变量。
谢谢
答案 0 :(得分:1)
您应该使用以下内容声明您的变量:
__block UIImageView*imageView;
答案 1 :(得分:0)
我认为您的阻止方法很好。我认为这是内存管理让你:为什么controller2在它的dealloc方法中取消了imageView。那应该是
[imageView release];
不是dealloc。 controller2是否保留了imageView?
这样做的原因是NSURLConnection块将捕获imageView,因此即使在controller2消失后它也会挂起。在您按下的情况下,控制器消失,imageView获取新图像,然后它也会消失。一切都应该没问题。
我同意你的看法,块很棒。另一件很棒的事情是ARC,两者相处得很好。你能在这个项目中使用ARC吗?
答案 2 :(得分:0)
[NSURLConnection sendAsynchronousRequest:request queue:imageDownloadersQueue completionHandler:^(NSURLResponse *response, NSData *firstImageData, NSError *error) {
NSLog(@"first block beginning [self retainCount] = %d, [imagesDictionary retainCount] = %d",[self retainCount], [imagesDictionary retainCount]);
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
UIImage * first_image = [[[UIImage alloc] initWithData:firstImageData scale:[[UIScreen mainScreen] scale]] autorelease];
[NSURLConnection sendAsynchronousRequest:request queue:imageDownloadersQueue completionHandler:^(NSURLResponse *response, NSData *secondImageData, NSError *error) {
NSLog(@"second block beginning [self retainCount] = %d, [imagesDictionary retainCount] = %d",[self retainCount], [imagesDictionary retainCount]);
UIImage * second_image = [[[UIImage alloc] initWithData:secondImageData scale:[[UIScreen mainScreen] scale]] autorelease];
if(first_image && second_image){
[imagesDictionary setObject:[NSArray arrayWithObjects:first_image, second_image, nil] forKey:match.match_id];
}
}];
}];
第一个块开始[self retainCount] = 2,[imagesDictionary retainCount] = 1
第二个块开始[self retainCount] = 2,[imagesDictionary retainCount] = 1
似乎阻止了“自我”并在最后释放它 所以“自我”(我的实例)不能在块结束之前解除分配
答案就是答案,对吧? 希望如此......谢谢