【问题标题】:NSNotification for TabBarControllersTabBarControllers 的 NSNotification
【发布时间】:2017-01-04 14:20:11
【问题描述】:

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

BVC
- CustomView (Notification received updates this VC) 

现在我已经从 BVC 子类化了 4 个不同的控制器。

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 类,在 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]

     } 
}

【问题讨论】:

    标签: ios objective-c swift nsnotificationcenter


    【解决方案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
    

    更新

    假设您可以使用初始化程序(如下面的 cmets 中 @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)
    }
    

    【讨论】:

    • 很好的答案,但你的第一个理论是正确的,第二个是令人困惑的。 OP 几乎可以肯定是不正确的 vcs 尚未分配。
    • 更简单地说,答案是:让 vcs 观察通知的整个生命周期,而不仅仅是可见时。
    • @danh 你是对的——应该分配 VC,但这并不意味着他们的视图被加载。后者通常会在标签的控制器第一次出现时发生。
    • 然后可以覆盖 OP 使用的 init 方法,并且可以从那里开始观察。无论如何,这对于 dealloc 来说是一个更好的书挡。因为我们希望 viewDidLoad 运行而强制视图加载是很恶心的。如果我们必须把手指伸进去,请直接关注vc1 = [FirstVC new]; 并添加:[[NSNotificationCenter defaultCenter] addObserver: vc1
    • 我只是假设init 方法在幕后存在某种问题,并且 OP 出于某种原因想要避免接触它们(“但我不能在 VC 中使用 init 方法,因为它要求我使用 initWithaCoder")。如果不是这样,那么当然,最好订阅init
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多