Память: объект не освобождается после отключения контроллера просмотра, с 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, и затем были выпущены контроллеры представлений.