0

私は drupal-ios-sdk (AFNetworking に基づく) を使用しており、アプリにはストーリーボードで作成されたタブ バー コントローラーがあります。ビュー コントローラーの 1 つをロードするときにinitWithCoder、drupal-ios-sdk でリクエストを作成し、success block. 後でviewDidLoadこの変数を印刷しようとしましたが、自動解放で変数を定義したとしても、インスタンス変数を成功ブロックに保持する必要がある理由に興味があります。

これはARCではありません!

成功ブロックで保持を使用しない

私の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も違いはないようです。どうして?

4

1 に答える 1

1

このコードには多くの問題があります。aboutPageHTML強い参照が必要なインスタンス変数です(つまり、保持する必要があります)。あなたはそれaboutPageHTML = [[[NSString alloc]init] autorelease];への強い参照を維持していません。これは正しくありません。

そして後で、成功ブロック (ブロックであることは関係ありません。後で実行されるコードにすぎません) でaboutPageHTML = [response valueForKey:@"body"]; [aboutPageHTML retain];、そのインスタンス変数に格納されているオブジェクトを保持します。したがって、2 つの場所で同じインスタンス変数のメモリ管理と矛盾しています。

また、強く参照される変数に別の値を代入するときは、以前の値を必ず解放する必要がありますが、これは行っていません。これは と の両方に当てはまりaboutPageHTMLますresponse

最後に、が指しているオブジェクトviewDataがリークされます。これは、強い参照がある ( を使用するnew) ためですが、解放しないためです。

また、辞書にはsetObject:forKey:andを使用する必要があります。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;
}
于 2013-03-21T09:06:14.010 に答える