Я использую эту процедуру довольно часто, хотя с помощью viewDidAppear
, так как я не могу быть уверен, что какой-либо другой контроллер представления не будет вызывать viewWillAppear
до нынешней СВОЕЙ viewWillDisappear
будет называться, и это может быть неудобство, когда вы назначаете делегат некоторые " общий экземпляр ".
В любом случае, я всегда использую контроллеры представлений для обработки этих перезагрузок, а затем вызываю определенные виды, которые нужно обновить. Было несколько конкретных случаев, когда я отказался от подписки в методе removeFromSuperView
, но вы можете понять, что это не лучший подход, так как представление может быть снова добавлено в какое-то представление в качестве подзапроса, и подписка не выполняется автоматически. Но опять же я использую это в тех случаях, когда сам вид сам сохраняется из-за подписки, для которой наиболее распространенной ситуацией является использование таймера или ссылки на изображение (этого можно избежать, используя 2 класса, но это другое дело).
Если эта подписка/отказ от подписки используется на уровне диспетчеров вида, как при проверке видимости видимости, я скорее предлагаю вам оставить ее там и вручную подписать/отменить подписку, принадлежащую контроллеру представления. Если по какой-либо другой причине ваш код будет более управляемым.
Если, с другой стороны, это должно быть на уровне определенного типа вида (создание библиотеки или даже просто повторное использование), тогда я попытался бы обработать это в некоторых случаях: init
и dealloc
. Опять же, если ресурсы жесткие, я бы переместил логику в контроллер вида.
В любом случае, если вы найдете твердое решение, строго придерживающееся этой логики, я был бы рад услышать об этом.
Редактировать на комментарий, чтобы добавить само сохранить решение:
Когда дело доходит до вопроса, когда класс сохраняется по подписке, такие как таймер или уведомления центра, что вы делаете, это создать 2 класса ,Один представляет ваш интерфейс и имеет все методы, необходимые для получения конкретных данных, и при необходимости содержит делегата, которому абонент может подписаться (имея слабую ссылку), назовем его классом A. Теперь этот класс содержит другой класс, который содержит фактический подписки на внешние источники, такие как центр уведомлений, и самосохраняемый класс B. Таким образом, класс A не сохраняется самостоятельно, поскольку он не имеет прямых подписчиков в центре уведомлений, таймеры ... Это означает, что класс A будет освобожден должным образом, в то время как класс B будет сохраняются и вызывают потенциальную утечку памяти. Класс B тогда нуждается в явном вызове, который будет отменен, поэтому он будет выпущен, и это должно быть сделано в методе класса A dealloc
.
Я думаю, простое объяснение может быть немного сложнее, так что смотреть на этот код:
#import "ClassA.h"
@class ClassA;
@class ClassB;
@protocol ClassBDelegate <NSObject>
- (void)classBPing:(ClassB *)sender;
@end
@interface ClassB : NSObject
@property NSTimer *timer;
@property (weak) id<ClassBDelegate> delegate;
- (void)beginNotificationHandling;
- (void)endNotificationHandling;
@end
@implementation ClassB
- (void)beginNotificationHandling {
if(self.timer == nil) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
}
}
- (void)endNotificationHandling {
[self.timer invalidate];
self.timer = nil;
}
- (void)onTimer {
[self.delegate classBPing:self];
}
@end
@interface ClassA()<ClassBDelegate>
@property ClassB *classBInstance;
@end
@implementation ClassA
- (instancetype)init {
if((self = [super init])) {
self.classBInstance = [[ClassB alloc] init];
self.classBInstance.delegate = self;
[self.classBInstance beginNotificationHandling];
}
return self;
}
- (void)dealloc {
// once this class is deallocated the classB instance must be invalidated so it is deallocated as well
[self.classBInstance endNotificationHandling];
}
- (void)classBPing:(ClassB *)sender {
NSLog(@"Ping");
}
@end
отметить, что это только исходный файл, нет необходимости иметь classB
в файле заголовка, как вы должны не используйте его за пределами classA
. Теперь, используя эту процедуру, вы можете добавлять любые методы, делегаты или что-то еще от classA
для обработки событий.
Init и dealloc становятся проблематичными, когда подписка сохраняет подписчика (например, NSNotificationCenter делает это) –
Да, поскольку я упоминал, что проблема возникает, когда у вас есть ситуация с сохранением себя, как вы только что упомянули. Позвольте мне отредактировать ответ, чтобы добавить это уже упомянутое «другое». –
Попробуйте изучить эту процедуру (отредактировано) ... –