Память: объект не освобождается после отключения контроллера просмотра, с ARC

У меня есть 2 контроллера вида,

FirstViewController → SecondViewController через

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

memory graph

на SecondViewContrller, когда я делаю

[self dismissViewControllerAnimated:YES completion:nil];

enter image description here

Мой вопрос: почему объекты не выпускаются на secondViewController после того, как я уволил этот диспетчер представлений. Как вы можете видеть на графике Он не спустился после увольнения. BTW - лучший способ опубликовать/закрыть ViewController?

[EDIT]

I NSLog сообщение о методе dealloc на каждом VC, Когда я начинаю с FVC- > SVC → [отклонять SVC]. это мои журналы

enter image description here

Ответ 1

Это может быть довольно грубый материал. Раньше у меня были подобные проблемы. Найдите свой код и посмотрите, есть ли у вас сильные или неправильные ссылки на объекты.

Одна из моих главных ошибок (и то, что я видел в Интернете сотни раз) - это свойства делегата. Я написал их как @property (nonatomic, retain) id<protocol>delegate; довольно долго, поскольку понял, что если я это сделаю, делегированный объект не будет выпущен. В этом случае нужно использовать assign.

Надеюсь, что вам помогут...

Ответ 2

Я провел некоторое исследование с этим поведением.

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

Как вы можете видеть после нажатия кнопкиMeButtonAction, вызывается secondViewController, выделенный и после нажатия вызываемого second_controller_express_iss_iss_issout_switchAction, успешно отменяется.

НО: В большинстве случаев он освобождается немедленно, но если вы представляете и отклоняете его очень быстро (дважды в секунду или около того), dellocation не запускается немедленно, а через некоторое время.

Предположим, что это путем разработки процедуры ARC deallocation. Не уверен.

Ответ 3

попробуйте это...

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

SVC = nil;

Ответ 4

Проведя много часов на этом, я, наконец, нашел недостающую часть головоломки: вам не нужно устанавливать какие-либо сильные ссылки на ViewController на nil, вы также должны аннулировать любые таймеры и знать о блокировки хранения. Каждый раз, когда вы используете себя в блоке, вы создаете цикл сохранения! Вместо этого вы должны объявить такую ​​переменную

__unsafe_unretained ViewController *weakSelf = self; 

и использовать его вместо self в блоке.

Ответ 5

Проверьте все IBOutlets в своем приложении. Для них может быть "сильное" свойство. Сделайте их "слабыми". Например, IBOulet должен выглядеть следующим образом:

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

Проверьте все делегаты (если есть) в приложении. Каждый делегат должен быть следующим:

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

Обратите внимание, что для восстановления памяти ARC требуется некоторое количество времени.

Ответ 6

Таймеры были в моем случае. Добавленный таймер недействителен для viewWillDisappear, и затем были выпущены контроллеры представлений.