TabBarControllers的NSNotification

时间:2017-01-04 14:20:12

标签: ios objective-c swift nsnotificationcenter

我有一个BaseController(BVC),我已经开始在viewWillAppear&停止在viewWillDisappear方法中听取它们。

BVC
- CustomView (Notification received updates this VC) 

现在我已经从BVC继承了4个不同的控制器。

BVC
|-- FirstVC (FVC)
|-- SecondVC (SVC)
|-- ThirdVC (TVC)

现在,我有一个通过NavigationViewController(NVC)将这3个VC作为项目的TarBarController

TabBarController
|- NVC->FVC
|- NVC->SVC
|- NVC->TVC

我的问题是,我发送了一个来自Singleton对象的playWillBegin通知,这是一个AVPlayer实例。从VC收到通知,该通知在顶部处于活动状态,但如果我不快速切换选项卡,则不会在其他控制器中收到通知。

我也读过SO,其他VC没有实例化,这就是没有收到通知的原因。但我不能在VC中使用init方法,因为它要求我使用initWithaCoder

我的项目是所有代码,不使用故事板等。所以我的TabBarController是一个快速类,有项目和AppDelegate中的TabBarController实例

编辑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]

     } 
}

enter image description here

1 个答案:

答案 0 :(得分:1)

非活动标签未收到通知的第一个原因是取消订阅了不可见的控制器。当您从标签#2(SecondVC)切换到标签#1(FirstVC)时,会为-[viewWillDisappear:]调用SecondVC停止收听,因此控制器不再接收通知。

我建议开始在-[viewDidLoad:]收听并停在-[dealloc](或Swift中的deinit):

<强>的OBJ-C:

- (void) viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(someFunction:) name:@"notification_name" object:nil];
}

- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

<强>夫特:

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

<强>夫特:

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;
}

<强>夫特:

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)
}