TabBarController 的 NSNotification
NSNotification for TabBarControllers
我有一个 BaseController (BVC),我已经开始在 viewWillAppear 中收听通知并在 viewWillDisappear 方法中停止收听它们。
BVC
- CustomView (Notification received updates this VC)
现在我已经从 BVC 继承了 4 个不同的控制器class。
BVC
|-- FirstVC (FVC)
|-- SecondVC (SVC)
|-- ThirdVC (TVC)
现在,我有一个 TarBarController,它通过 NavigationViewController (NVC)
将这 3 个 VC 作为其项目
TabBarController
|- NVC->FVC
|- NVC->SVC
|- NVC->TVC
我的问题是,我从一个 AVPlayer 实例的 Singleton 对象发送了一个 playWillBegin 通知。从顶部活动的 VC 收到通知,但如果我不快速切换选项卡,则其他控制器不会收到通知。
我也在 SO 中读到,其他 VC 未实例化,这就是未收到通知的原因。但是我不能在 VC 中使用 init 方法,因为它要求我使用 initWithaCoder
我的项目全是代码,不使用故事板等。所以我的 TabBarController 是 swift class,那里有项目,TabBarController 实例在 AppDelegate
编辑 1:相关的 SO QA 链接
Link1
Link2
编辑 2:澄清为什么我无法在 VC 的 init() 方法中添加任何内容
BaseViewController - 片段
init() {
super.init() //Please refer image for error message
}
required init?(coder aDecoder: NSCoder) {
}
TabBarController
class TabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
tabBar.tintColor = UIColor.whiteColor()
self.delegate = self
let FNVC = UINavigationController(rootViewController: FVC())
//Other initialization code
let SNVC = UINavigationController(rootViewController: SVC())
//Other initialization code
let TNVC = UINavigationController(rootViewController: TVC())
//Other initialization code
viewControllers = [FNVC, SNVC, TNVC]
}
}
非活动选项卡未收到通知的第一个原因是不可见控制器已取消订阅。例如,当您从选项卡 #2 (SecondVC
) 切换到选项卡 #1 (FirstVC
) 时,-[viewWillDisappear:]
会为 SecondVC
调用并停止监听因此该控制器将不再收到通知。
我建议在 -[viewDidLoad:]
开始收听并在 -[dealloc]
停止(或 deinit
在 Swift):
Obj-C:
- (void) viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(someFunction:) name:@"notification_name" object:nil];
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Swift:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(BaseController.someFunction), name:Notification.Name("foobar"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
第二个原因是视图可能还没有加载,所以[-viewDidLoad:]
没有被调用,相应的视图控制器也没有被订阅。要解决此问题,您可以在创建选项卡的视图控制器时强制加载 VC 的视图,例如:
Obj-C:
FirstVC *vc1 = [FirstVC new];
[vc1 view]; // loading view, subscribing
Swift:
let vc1 = FirstVC()
let _ = vc1.view
更新
假设你可以使用初始化器(正如@danh 在下面的评论中所解释的那样),最好在 init
方法而不是 viewDidLoad
中订阅。在这种情况下,无需强制加载视图,您可以省略 [vc view]
调用:
Obj-C:
- (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])){
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notified:) name:@"foobar" object:nil];
}
return self;
}
Swift:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
NotificationCenter.default.addObserver(self, selector: #selector(BaseViewController.someFunc), name:Notification.Name("foobar"), object: nil)
}
我有一个 BaseController (BVC),我已经开始在 viewWillAppear 中收听通知并在 viewWillDisappear 方法中停止收听它们。
BVC
- CustomView (Notification received updates this VC)
现在我已经从 BVC 继承了 4 个不同的控制器class。
BVC
|-- FirstVC (FVC)
|-- SecondVC (SVC)
|-- ThirdVC (TVC)
现在,我有一个 TarBarController,它通过 NavigationViewController (NVC)
将这 3 个 VC 作为其项目TabBarController
|- NVC->FVC
|- NVC->SVC
|- NVC->TVC
我的问题是,我从一个 AVPlayer 实例的 Singleton 对象发送了一个 playWillBegin 通知。从顶部活动的 VC 收到通知,但如果我不快速切换选项卡,则其他控制器不会收到通知。
我也在 SO 中读到,其他 VC 未实例化,这就是未收到通知的原因。但是我不能在 VC 中使用 init 方法,因为它要求我使用 initWithaCoder
我的项目全是代码,不使用故事板等。所以我的 TabBarController 是 swift class,那里有项目,TabBarController 实例在 AppDelegate
编辑 1:相关的 SO QA 链接 Link1 Link2
编辑 2:澄清为什么我无法在 VC 的 init() 方法中添加任何内容 BaseViewController - 片段
init() {
super.init() //Please refer image for error message
}
required init?(coder aDecoder: NSCoder) {
}
TabBarController
class TabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
tabBar.tintColor = UIColor.whiteColor()
self.delegate = self
let FNVC = UINavigationController(rootViewController: FVC())
//Other initialization code
let SNVC = UINavigationController(rootViewController: SVC())
//Other initialization code
let TNVC = UINavigationController(rootViewController: TVC())
//Other initialization code
viewControllers = [FNVC, SNVC, TNVC]
}
}
非活动选项卡未收到通知的第一个原因是不可见控制器已取消订阅。例如,当您从选项卡 #2 (SecondVC
) 切换到选项卡 #1 (FirstVC
) 时,-[viewWillDisappear:]
会为 SecondVC
调用并停止监听因此该控制器将不再收到通知。
我建议在 -[viewDidLoad:]
开始收听并在 -[dealloc]
停止(或 deinit
在 Swift):
Obj-C:
- (void) viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(someFunction:) name:@"notification_name" object:nil];
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Swift:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(BaseController.someFunction), name:Notification.Name("foobar"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
第二个原因是视图可能还没有加载,所以[-viewDidLoad:]
没有被调用,相应的视图控制器也没有被订阅。要解决此问题,您可以在创建选项卡的视图控制器时强制加载 VC 的视图,例如:
Obj-C:
FirstVC *vc1 = [FirstVC new];
[vc1 view]; // loading view, subscribing
Swift:
let vc1 = FirstVC()
let _ = vc1.view
更新
假设你可以使用初始化器(正如@danh 在下面的评论中所解释的那样),最好在 init
方法而不是 viewDidLoad
中订阅。在这种情况下,无需强制加载视图,您可以省略 [vc view]
调用:
Obj-C:
- (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])){
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notified:) name:@"foobar" object:nil];
}
return self;
}
Swift:
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
NotificationCenter.default.addObserver(self, selector: #selector(BaseViewController.someFunc), name:Notification.Name("foobar"), object: nil)
}