提出問題
前幾天一個羣友遇到了一個關於NSNotification的問題:現有A,B兩個界面,B界面由A界面push展示出來,A有一輸入框和按鈕,B有一lable,想實現的效果是點擊A的按鈕,將A輸入框的文字傳到B的lable上,問題是第一次無法實現這個,第二次正常。。。
問題分析
這個爲題的根源在於通知的執行步驟,要想完成一個通知,主要有分三步走:
(1)註冊通知: [[NSNotificationCenter defaultCenter]addObserver: selector: name: object: ]; ps:說一下幾個參數意思:Observer:(誰來接受通知消息);selector(方法選擇,執行哪個方法); name:(通知的名稱,也可以說是通知消息的標識,按照這個來區分是否接受通知);object:(接受誰的通知,用這個參設置,nil爲接受所有文件發送的通知)。
(2)發送通知: [[NSNotificationCenter defaultCenter]postNotificationName: object: userInfo:]; Name:(通知標識,與註冊通知是的標識對應);object:(發送方);userInfo:(重點說一下,這是一個字典類型的對象,可以把需要傳遞的值放進這個字典裏)。
(3)執行通知方法:實現註冊通知是選擇的方法,selector後邊的。這裏不在多說。
這三部是按順序來的,上邊的那個問題就是順序的問題,B是Apsuh得到的,比A晚出現,在A中發送通知,B中註冊通知並執行通知方法,顯然是先執行post,然後執行add,
也就是說post(發送通知)的時候,還沒有add(註冊通知),系統找不到接受通知消息的對象,所以導致傳值的失敗,第二次成功是因爲已經註冊通知並沒有移除,所以第二次可以。這種從前往後的正向傳值一般不用通知還是用block和屬性傳值比較好。
問題解決
雖然這種正向傳值我們提倡用block和屬性傳值,但是如果用通知的機制能不能實現呢?答案是肯定的,我們只要保證add(註冊通知)在post(發送通知)之前就可以了。
1.這種方法就是在B重寫init方法,並把 [[NSNotificationCenter defaultCenter]addObserver: selector: name: object: ];方法寫進init中,
2.把發送方法[[NSNotificationCenter defaultCenter]postNotificationName: object: userInfo:]; 寫在點擊按鈕push出B的語句後邊,這樣就可以了。
這裏主要涉及視圖控制器的生命週期,也就是各個方法的執行順序:
一個視圖控制器被創建,並在屏幕上顯示的時候。 代碼的執行順序
1、 alloc 創建對象,分配空間
2、init 初始化對象,初始化數據
3、loadView 加載視圖
4、viewDidLoad 載入完成
5、viewWillAppear 視圖將出現在屏幕
6、viewDidAppear 視圖已在屏幕上渲染完成
當一個視圖被移除屏幕並且銷燬的時候的執行順序,
1、viewWillDisappear 視圖將被從屏幕上移除之
2、viewDidDisappear 視圖已經被從屏幕上移除
3、dealloc 視圖被銷燬