虽然使用viewDidAppear,但我经常使用此过程,因为我不能确定其他视图控制器不会在调用当前的viewWillDisappear 之前调用viewWillAppear,这在您分配时可能会带来不便某个“共享实例”的代表。
无论如何,我总是使用视图控制器来处理这种重新加载,然后调用特定的视图进行刷新。在某些特定情况下,我在 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 的任何内容来处理事件。