web-dev-qa-db-ja.com

メモリ:ARCを使用して、ViewControllerが閉じた後にオブジェクトが解放されない

私は2つのビューコントローラーを持っています、

FirstViewController-> SecondViewController経由

[self presentViewController:SVC animated:YES completion:nil];

memory graph

私がするときSecondViewContrllerで

[self dismissViewControllerAnimated:YES completion:nil];

enter image description here

私の質問は、このビューコントローラを閉じた後、なぜオブジェクトがsecondViewControllerで解放されないのかということです。グラフでわかるように、却下しても下がっていません。ところで、ViewControllerをリリース/却下するための最良の方法は何ですか?

[編集]

FVC-> SVC-> [dismiss SVC]から開始すると、すべてのVCのdeallocメソッドに関するメッセージをNSLogします。これは私のログです

enter image description here

13
Bordz

これはかなりラフなものになる可能性があります。以前にも同様の問題がありました。コードを検索して、オブジェクトへの強い参照または間違った参照があるかどうかを確認します。

私の最大の過ちの1つ(そしてインターネットで何百回も見たこと)は、デリゲートプロパティです。 @property (nonatomic, retain) id<protocol>delegate;のように長い間書いていましたが、そうすると、委任されたオブジェクトが解放されないことに気づきました。この場合、assignを使用する必要があります。

それがあなたを助けることを願っています...

8

私はこの振る舞いについて調査しました。

FirstViewController.m

 #import "FirstViewController.h"  
 #import "SecondViewController.h"

@interface FirstViewController ()

@end

@implementation FirstViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    // Custom initialization
}
  return self;
}

-(void)dealloc {
    NSLog(@"First Dealloc");

}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    UIButton *pressMe=[UIButton buttonWithType:UIButtonTypeCustom];
    pressMe.frame = CGRectMake(0, 0, 100, 40);
    pressMe.center = self.view.center;
    [pressMe setTitle:@"PressMe" forState:UIControlStateNormal];
    [pressMe addTarget:self action:@selector(pressMeAction:)             
    forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:pressMe];

// Do any additional setup after loading the view.
 }

 - (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(void) pressMeAction:(id) sender
{
    SecondViewController *svc = [[SecondViewController alloc] init];
    [self presentViewController:svc animated:YES completion:nil];
    NSLog(@"Present Second");
}

@end

SecondViewController.m

を除いてほとんど同じです

-(void) pressDissmissButtonAction:(id) sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
    NSLog(@"Dismiss Second");
}

これが割り当てのダイナミクスです enter image description here

ご覧のとおり、pressMeButtonActionが呼び出された後secondViewControllerが割り当てられ、pressDissmissButtonActionが呼び出された後secondViewControllerが正常に割り当て解除されます。

BUT:ほとんどの場合、すぐに割り当てが解除されますが、非常にすばやく(2秒程度)提示して却下すると、割り当て解除はすぐには実行されませんが、しばらくすると実行されます。

これは、ARC割り当て解除手順の設計実装によるものだと思います。わからない。

2

私の場合、タイマーが問題でした。 viewWillDisappearにタイマー無効化を追加し、ビューコントローラーが解放されました。

0
user3280979

これに何時間も費やした後、私はついにパズルの欠けている部分を見つけました:ViewControllerへの強い参照をnilに設定する必要があるだけでなく、タイマーを無効にする必要がありますブロック保持に注意してくださいサイクル。ブロックで自分自身を使用するときはいつでも、保持サイクルを作成します!代わりに、そのような変数を宣言する必要があります

__unsafe_unretained ViewController *weakSelf = self; 

ブロック内で自分の代わりにそれを使用します。

0
Atomix

アプリケーション内のすべてのIBOutletsを確認してください。それらに「強力な」プロパティが割り当てられている可能性があります。それらを「弱く」します。たとえば、IBOuletは次のようになります。

@property (weak, nonatomic) IBOutlet UILabel *myLabel;

アプリケーション内のすべてのデリゲート(存在する場合)を確認します。すべてのデリゲートは次のようになります。

@property (nonatomic, assign) id <yourProtocol> delegate;

ARCがメモリを回復するのにある程度の時間がかかることに注意してください。

0
KSR

これを試して ...

[self presentViewController:SVC animated:YES completion:nil];

SVC = nil;
0
Shaik Riyaz