我正在使用drupal-ios-sdk(基于AFNetworking),我的应用程序有一个用故事板创建的标签栏控制器。当加载其中一个视图控制器时,我在initWithCoder
中使用drupal-ios-sdk创建一个请求,并在success block
中分配一个实例变量。后来在viewDidLoad
我尝试打印这个变量,我很感兴趣为什么我必须在成功块中保留实例变量,即使我用autorelease定义变量。
这不是ARC!
@interface AboutViewController : UIViewController {
@private
NSDictionary *response;
NSString *aboutPageHTML;
}
@end
-(id) initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
NSDictionary *viewData = [NSMutableDictionary new];
[viewData setValue:@"aboutse" forKey:@"view_name"];
aboutPageHTML = [[[NSString alloc]init] autorelease];
void(^successBlock)(AFHTTPRequestOperation*, id) =
^(AFHTTPRequestOperation *operation, id responseObject) {
response = [responseObject copy];
aboutPageHTML = [response valueForKey:@"body"];
NSLog(@"%s - %@", __PRETTY_FUNCTION__, aboutPageHTML);
[aboutPageHTML retain]; // critical!
};
[DIOSView viewGet:viewData success:successBlock
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%s, %@", __PRETTY_FUNCTION__, error);
}];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%s - %@", __PRETTY_FUNCTION__, aboutPageHTML);
NSLog(@"%s - %f %f", __PRETTY_FUNCTION__, self.view.bounds.size.width, self.view.bounds.size.height);
}
使用__block
声明变量似乎没有什么区别。怎么样?
答案 0 :(得分:1)
这段代码有很多问题。 aboutPageHTML
是您想要强引用(即应保留)的实例变量。在aboutPageHTML = [[[NSString alloc]init] autorelease];
中,您没有强烈提及它。这是不正确的。
稍后,在你的成功块中(它与块无关;它只是后来运行的任何代码),你做aboutPageHTML = [response valueForKey:@"body"]; [aboutPageHTML retain];
确实保留了存储在该实例变量中的对象。所以你在两个地方与同一个实例变量的内存管理不一致。
此外,当您为强引用变量指定另一个值时,应确保释放之前未执行的值。这适用于aboutPageHTML
和response
。
最后,viewData
指向的对象被泄露,因为你有一个强引用它(你使用new
)但不释放它。
此外,您应该使用setObject:forKey:
和objectForKey:
作为词典。当你想要一个可以改变的字典时,你需要声明一个可变字典。 (这可能是您(错误地)决定使用setValue:forKey:
)
总而言之,这更像是:
-(id) initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
NSMutableDictionary *viewData = [NSMutableDictionary new];
[viewData setObject:@"aboutse" forKey:@"view_name"];
aboutPageHTML = [[NSString alloc] init];
void(^successBlock)(AFHTTPRequestOperation*, id) =
^(AFHTTPRequestOperation *operation, id responseObject) {
[response release];
response = [responseObject copy];
[aboutPageHTML release];
aboutPageHTML = [[response objectForKey:@"body"] retain];
};
[DIOSView viewGet:viewData success:successBlock
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%s, %@", __PRETTY_FUNCTION__, error);
}];
[viewData release];
}
return self;
}