阻止执行iOS并分配变量

时间:2013-03-21 05:47:01

标签: ios objective-c-blocks

我正在使用drupal-ios-sdk(基于AFNetworking),我的应用程序有一个用故事板创建的标签栏控制器。当加载其中一个视图控制器时,我在initWithCoder中使用drupal-ios-sdk创建一个请求,并在success block中分配一个实例变量。后来在viewDidLoad我尝试打印这个变量,我很感兴趣为什么我必须在成功块中保留实例变量,即使我用autorelease定义变量。

这不是ARC!

未在成功块中使用retain

我的VC.h

@interface AboutViewController : UIViewController {
    @private
    NSDictionary *response;
    NSString *aboutPageHTML;

}
@end

我的VC.m

-(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声明变量似乎没有什么区别。怎么样?

1 个答案:

答案 0 :(得分:1)

这段代码有很多问题。 aboutPageHTML是您想要强引用(即应保留)的实例变量。在aboutPageHTML = [[[NSString alloc]init] autorelease];中,您没有强烈提及它。这是不正确的。

稍后,在你的成功块中(它与块无关;它只是后来运行的任何代码),你做aboutPageHTML = [response valueForKey:@"body"]; [aboutPageHTML retain];确实保留了存储在该实例变量中的对象。所以你在两个地方与同一个实例变量的内存管理不一致。

此外,当您为强引用变量指定另一个值时,应确保释放之前未执行的值。这适用于aboutPageHTMLresponse

最后,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;
}