2017-01-04 7 views
0

私はviewWillAppear &の通知をlistenするために開始したBaseController(BVC)を、viewWillDisappearメソッドでリッスンを停止しました。TabBarControllersのNSNotification

BVC 
- CustomView (Notification received updates this VC) 

私はBVCから4つのコントローラをサブクラス化しました。

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

は今、私はNavigationViewController(NVC)を介してこれらの3つのVCのようにそのアイテムを持っている1 TarBarController

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

私の問題があり、私はシングルトンからplayWillBegin通知渡って送信しましたをしましたオブジェクトはAVPlayerインスタンスです。一番上でアクティブなVCからの通知が受信されますが、タブをすばやく切り替えると他のコントローラでは通知が受信されません。

私もSOで読みました。他のVCはインスタンス化されておらず、それは通知が受信されない理由です。しかし、私はVCでinitメソッドを使用することはできません。なぜなら、initWithaCoderを使用するように頼んでいるからです。

私のプロジェクトはすべてコードであり、ストーリーボードなどは使用しません。したがって、私のTabBarControllerは即時クラスで、AppDelegateのTabBarControllerインスタンス

EDIT 1:私はINITに何も追加することができないよ、なぜ明確にするために(VC の)方法BaseViewController - スニペット

012:関連SO QAが Link1 Link2

EDIT 2リンク

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

非アクティブタブで受信されていない通知するための第1の理由は、目に見えないコントローラが解除されていることです。たとえば、タブ#2(SecondVC)からタブ#1(FirstVC)に切り替えると、-[viewWillDisappear:]SecondVCが呼び出され、リスニングが停止され、コントローラは通知を受信しなくなります。

Iは-[viewDidLoad:]にリスニングを開始及び-[dealloc](又はスイフトで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) 
} 

第2の理由は、ビューmまだロードされていないので、[-viewDidLoad:]は呼び出されず、対応するView Controllerはサブスクライブされません。これを解決するには、タブのコントローラを表示するときにVCのビューを強制的に表示することがあります。:

のObj-C:

FirstVC *vc1 = [FirstVC new]; 
[vc1 view]; // loading view, subscribing 

スウィフト:

let vc1 = FirstVC() 
let _ = vc1.view 

UPDATE

に@danhで説明したように、あなたが(初期化子を使用することができますと仮定すると、以下のコメント)、 viewDidLoadの代わりにinitメソッドを使用してください。

の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) 
} 
+0

グレート答えが、あなたのこの場合、ビューの読み込みを強制的に、あなたが[vc view]呼び出しを省略することができます必要はありません最初の理論は正しく、2番目の理論は混乱しています。 OPは、vcsがまだ割り当てられていないという確かに間違いです。 – danh

+1

もっと簡単に言えば、答えは次のようなものです。vcsに、表示されたときだけでなく、ライフサイクル全体の通知を観察させます。 – danh

+0

@danhあなたは正しいです - VCを割り当てる必要がありますが、ビューがロードされているわけではありません。後者は、タブのコントローラが初めて表示されるときに一般的に発生します。 – degapps

関連する問題