1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
// /** *
NotificationObserver *
觀察者類 *
這個類在NotificationCenter的addObserver中會自動創建,不需要你去使用它。 **/ class CC_DLL NotificationObserver : public Ref { private : Ref* _target; // 觀察者主體對象 SEL_CallFuncO _selector; // 消息回調函數 std::string _name; // 消息名稱 Ref* _sender; // 消息傳遞的數據 public : // 創建一個觀察者對象 NotificationObserver(Ref *target, SEL_CallFuncO selector, const std::string& name, Ref *sender); // 當post發佈消息時,執行_selector回調函數,傳入sender消息數據 void performSelector(Ref *sender); }; /** *
NotificationCenter *
消息訂閱/發佈中心類 */ class CC_DLL __NotificationCenter : public Ref { private : // 保存觀察者數組 NotificationObserver __Array *_observers; public : // 獲取單例對象 static __NotificationCenter* getInstance(); static void destroyInstance(); // 訂閱消息。爲某指定的target主體,訂閱消息。 // target : 要訂閱消息的主體(一般爲 this) // selector : 消息回調函數(發佈消息時,會調用該函數) // name : 消息名稱(類型) // sender : 需要傳遞的數據。若不傳數據,則置爲 nullptr void addObserver(Ref* target, SEL_CallFuncO selector, const std::string& name, Ref* sender); // 發佈消息。根據某個消息名稱name,發佈消息。 // name : 消息名稱 // sender : 需要傳遞的數據。默認爲 nullptr void postNotification( const std::string& name, Ref* sender = nullptr); // 退訂消息。移除某指定的target主體中,消息名稱爲name的訂閱。 // target : 主體對象 // name : 消息名稱 void removeObserver(Ref* target, const std::string& name); // 退訂消息。移除某指定的target主體中,所有的消息訂閱。 // target : 主體對象 // @returns : 移除的訂閱數量 int removeAllObservers(Ref* target); }; // |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// bool HelloWorld::init() { if ( !Layer::init() ) return false ; // 訂閱消息 addObserver // target主體對象 : this // 回調函數 : getMsg() // 消息名稱 : "test" // 傳遞數據 : nullptr NotificationCenter::getInstance()->addObserver( this , callfuncO_selector(HelloWorld::getMsg), "test" , nullptr); // 發佈消息 postNotification this ->sendMsg(); return true ; } // 發佈消息 void HelloWorld::sendMsg() { // 發佈名稱爲"test"的消息 NotificationCenter::getInstance()->postNotification( "test" , nullptr); } // 消息回調函數,接收到的消息傳遞數據爲sender void HelloWorld::getMsg(Ref* sender) { CCLOG( "getMsg in HelloWorld" ); } // |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// void __NotificationCenter::addObserver(Ref *target, SEL_CallFuncO selector, const std::string& name, Ref *sender) { // target已經訂閱了name這個消息 if ( this ->observerExisted(target, name, sender)) return ; // 爲target主體訂閱的name消息,創建一個觀察者 NotificationObserver *observer = new NotificationObserver(target, selector, name, sender); if (!observer) return ; // 加入 _observers 數組 observer->autorelease(); _observers->addObject(observer); } // |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// void __NotificationCenter::postNotification( const std::string& name, Ref *sender = nullptr) { __Array* ObserversCopy = __Array::createWithCapacity(_observers->count()); ObserversCopy->addObjectsFromArray(_observers); Ref* obj = nullptr; // 遍歷觀察者數組 CCARRAY_FOREACH(ObserversCopy, obj) { NotificationObserver* observer = static_cast <NotificationObserver*>(obj); if (!observer) continue ; // 是否訂閱了名稱爲name的消息 if (observer->getName() == name && (observer->getSender() == sender || observer->getSender() == nullptr || sender == nullptr)) { // 執行observer對應的target主體所綁定的selector回調函數 observer->performSelector(sender); } } } // |
1
2
3
4
5
6
7
8
|
// // 是否訂閱了名稱爲name的消息 if (observer->getName() == name && (observer->getSender() == sender || observer->getSender() == nullptr || sender == nullptr)) { // 執行observer對應的target主體所綁定的selector回調函數 observer->performSelector(sender); } // |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
// class Base : public Ref { public : void walk(Ref* sender) { CCLOG( "%s is walk" , data); } void run(Ref* sender) { CCLOG( "%s is run" , data); } // 訂閱消息 void addObserver() { // 訂閱 "walk" 和 "run" 消息 // 故意傳遞一個 data 數據 NotificationCenter::getInstance()->addObserver( this , callfuncO_selector(Base::walk), "walk" , (Ref*)data); NotificationCenter::getInstance()->addObserver( this , callfuncO_selector(Base::run), "run" , (Ref*)data); } public : char data[10]; // 類數據,表示類名 }; class A : public Base { public : A() { strcpy (data, "A" ); } // 數據爲類名 "A" }; class B : public Base { public : B() { strcpy (data, "B" ); } // 數據爲類名 "B" }; // |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// bool HelloWorld::init() { if ( !Layer::init() ) return false ; // 創建A類和B類。 A* a = new A(); B* b = new B(); a->addObserver(); // A類 訂閱消息 b->addObserver(); // B類 訂閱消息 // 發佈 "walk" 消息 NotificationCenter::getInstance()->postNotification( "walk" ); // 分割線 CCLOG( "--------------------------------------------------" ); // 發佈 "run" 消息 // 故意傳遞一個數據 a類的data數據 NotificationCenter::getInstance()->postNotification( "run" , (Ref*)a->data); return true ; } // |