NSNotificationCenter के साथ ऑब्जेक्ट कैसे पास करें


129

मैं अपने एप्लिकेशन प्रतिनिधि से किसी ऑब्जेक्ट को दूसरी कक्षा में एक सूचना रिसीवर को भेजने की कोशिश कर रहा हूं।

मैं पूर्णांक पास करना चाहता हूं messageTotal। अभी मेरे पास है:

रिसीवर में:

- (void) receiveTestNotification:(NSNotification *) notification
{
    if ([[notification name] isEqualToString:@"TestNotification"])
        NSLog (@"Successfully received the test notification!");
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissSheet) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveTestNotification:) name:@"eRXReceived" object:nil];

अधिसूचना करने वाले वर्ग में:

[UIApplication sharedApplication].applicationIconBadgeNumber = messageTotal;
[[NSNotificationCenter defaultCenter] postNotificationName:@"eRXReceived" object:self];

लेकिन मैं ऑब्जेक्ट messageTotalको दूसरी कक्षा में पास करना चाहता हूं ।


तेजी से 2.0 और तेजी से 3.0 के लिए stackoverflow.com/questions/36910965/…
साहिल

जवाबों:


235

आपको "userInfo" वैरिएंट का उपयोग करना होगा और एक NS नॉडर ऑब्जेक्ट पास करना होगा जिसमें मैसेजोटल पूर्णांक हो:

NSDictionary* userInfo = @{@"total": @(messageTotal)};

NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"eRXReceived" object:self userInfo:userInfo];

प्राप्त करने के अंत में आप userInfo शब्दकोश को इस प्रकार एक्सेस कर सकते हैं:

-(void) receiveTestNotification:(NSNotification*)notification
{
    if ([notification.name isEqualToString:@"TestNotification"])
    {
        NSDictionary* userInfo = notification.userInfo;
        NSNumber* total = (NSNumber*)userInfo[@"total"];
        NSLog (@"Successfully received test notification! %i", total.intValue);
    }
}

धन्यवाद, मैं messageTotalUIButton पर बैज सेट कर रहा हूं , क्या आप जानते हैं कि मैं नए बैज काउंट के साथ बटन को कैसे रिफ्रेश कर सकता हूं? में छवि प्रदर्शित करने के लिए कोड viewDidLoadहैUIBarButtonItem *eRXButton = [BarButtonBadge barButtonWithImage:buttonImage badgeString:@"1" atRight:NO toTarget:self action:@selector(eRXButtonPressed)];
जॉन

मुझे यकीन नहीं है कि आपको notification.name की तुलना करने की आवश्यकता क्यों है। जब आप addObserver () करते हैं तो नाम की मैपिंग की जानी चाहिए। एक विशिष्ट अधिसूचना का अवलोकन करते समय ReceTestNotification को केवल कॉल किया जाना चाहिए।
जोहान कार्लसन

1
जोहान, इस सरल मामले में आप सही हैं, लेकिन कई सूचनाओं को एक ही हैंडलर को ट्रिगर करना संभव है
लिटिक

93

प्रदान किए गए समाधान के आधार पर मैंने सोचा कि अपने स्वयं के कस्टम डेटा ऑब्जेक्ट (जो मैंने यहां प्रश्न के अनुसार 'संदेश' के रूप में संदर्भित किया है) को पारित करने के लिए एक उदाहरण दिखाना उपयोगी हो सकता है।

कक्षा ए (प्रेषक):

YourDataObject *message = [[YourDataObject alloc] init];
// set your message properties
NSDictionary *dict = [NSDictionary dictionaryWithObject:message forKey:@"message"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationMessageEvent" object:nil userInfo:dict];

कक्षा बी (रिसीवर):

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

#pragma mark - Notification
-(void) triggerAction:(NSNotification *) notification
{
    NSDictionary *dict = notification.userInfo;
    YourDataObject *message = [dict valueForKey:@"message"];
    if (message != nil) {
        // do stuff here with your message data
    }
}

2
क्यों इस जवाब में अधिक upvotes नहीं है ?! यह पूरी तरह से काम करता है और एक हैक नहीं है!
रूबेन टेनर

4
@Kairos क्योंकि यह इस तरह का उपयोग करने के लिए डिज़ाइन नहीं किया गया है। objectपरम में postNotificationName एक है जो इस सूचना भेजने के अर्थ चाहिए।
xi.lin

2
हाँ ऑब्जेक्ट को परमवीर चक्र का उपयोग करके एक एनएसएडर के रूप में पारित किया जाना चाहिए userInfoऔर ऊपर दिखाए गए उत्तर को अब यह दिखाने के लिए संपादित किया गया है।
डेविड डगलस

1
यह बहुत ही भ्रामक है, क्यों उस जवाब में इतने उत्थान हैं? इसे हटा देना चाहिए। सभी को userInfo का उपयोग करना चाहिए जो इसके लिए बिल्कुल बनाया गया था।
शिन्नीक्स

ठीक है, प्रतिक्रिया के लिए धन्यवाद ... मैंने userInfoऑब्जेक्ट के डेटा को पारित करने के तरीके के रूप में शब्दकोश का उपयोग करने के लिए उत्तर अपडेट किया है ।
डेविड डगलस

27

स्विफ्ट 2 संस्करण

जैसा @ जोहान कार्लसन ने बताया ... मैं गलत कर रहा था। यहां NSNotificationCenter के साथ सूचना भेजने और प्राप्त करने का उचित तरीका है।

सबसे पहले, हम postNotificationName के लिए इनिशलाइज़र को देखते हैं:

init(name name: String,
   object object: AnyObject?,
 userInfo userInfo: [NSObject : AnyObject]?)

स्रोत

हम userInfoपरम का उपयोग करके अपनी जानकारी पास करेंगे । [NSObject : AnyObject]प्रकार पकड़-भर से है ऑब्जेक्टिव-सी । इसलिए, स्विफ्ट भूमि में, हम सभी को एक स्विफ्ट शब्दकोश में पास करने की आवश्यकता है जिसमें चाबियाँ हैं जो कि NSObjectमूल्यों और व्युत्पन्न हैं जो हो सकते हैं AnyObject

उस ज्ञान के साथ हम एक शब्दकोष बनाते हैं जिसे हम objectपैरामीटर में पास करेंगे :

 var userInfo = [String:String]()
 userInfo["UserName"] = "Dan"
 userInfo["Something"] = "Could be any object including a custom Type."

फिर हम शब्दकोश को अपने ऑब्जेक्ट पैरामीटर में पास करते हैं।

प्रेषक

NSNotificationCenter.defaultCenter()
    .postNotificationName("myCustomId", object: nil, userInfo: userInfo)

प्राप्तकर्ता वर्ग

पहले हमें यह सुनिश्चित करने की आवश्यकता है कि हमारी कक्षा अधिसूचना के लिए देख रही है

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("btnClicked:"), name: "myCustomId", object: nil)   
}
    

तब हम अपना शब्दकोश प्राप्त कर सकते हैं:

func btnClicked(notification: NSNotification) {
   let userInfo : [String:String!] = notification.userInfo as! [String:String!]
   let name = userInfo["UserName"]
   print(name)
}

आप वास्तव में PostNotificationName () के इच्छित उपयोग का उल्लंघन कर रहे हैं। लेकिन आप अकेले नहीं हैं। मैंने उपयोगकर्ता ऑब्जेक्ट भेजने के लिए ऑब्जेक्ट पैरामीटर का उपयोग करते हुए कई डेवलपर देखे हैं। दूसरा तर्क, ऑब्जेक्ट, प्रेषक के लिए आरक्षित है। आपको सभी प्रकार की वस्तुओं को भेजने के लिए वास्तव में userInfo को उपयोगकर्ता होना चाहिए। अन्यथा आप यादृच्छिक दुर्घटनाओं आदि का सामना कर सकते हैं
जोहान कार्ल्ससन

25

स्विफ्ट 5

func post() {
    NotificationCenter.default.post(name: Notification.Name("SomeNotificationName"), 
        object: nil, 
        userInfo:["key0": "value", "key1": 1234])
}

func addObservers() {
    NotificationCenter.default.addObserver(self, 
        selector: #selector(someMethod), 
        name: Notification.Name("SomeNotificationName"), 
        object: nil)
}

@objc func someMethod(_ notification: Notification) {
    let info0 = notification.userInfo?["key0"]
    let info1 = notification.userInfo?["key1"]
}

बोनस (जो आपको निश्चित रूप से करना चाहिए!):

इसके Notification.Name("SomeNotificationName")साथ बदलें .someNotificationName:

extension Notification.Name {
    static let someNotificationName = Notification.Name("SomeNotificationName")
}

बदलें "key0"और "key1"साथ Notification.Key.key0और Notification.Key.key1:

extension Notification {
  enum Key: String {
    case key0
    case key1
  }
}

मुझे ऐसा क्यों करना चाहिए? महंगा टाइपो त्रुटियों से बचने के लिए, नाम बदलने का आनंद लें, उपयोग का आनंद लें आदि ...


धन्यवाद। स्पष्ट रूप से Notification.Name का विस्तार संभव है, लेकिन Notification.Key नहीं। 'Key' is not a member type of 'Notification'। यहां देखें: https://ibb.co/hDQYbd2
alpennec

धन्यवाद, ऐसा लगता है कि Keyसंरचना तब से हटा दी गई है। मैं जवाब को अपडेट कर रहा हूं
frouo

1

स्विफ्ट 5.1 कस्टम ऑब्जेक्ट / प्रकार

// MARK: - NotificationName
// Extending notification name to avoid string errors.
extension Notification.Name {
    static let yourNotificationName = Notification.Name("yourNotificationName")
}


// MARK: - CustomObject
class YourCustomObject {
    // Any stuffs you would like to set in your custom object as always.
    init() {}
}

// MARK: - Notification Sender Class
class NotificatioSenderClass {

     // Just grab the content of this function and put it to your function responsible for triggering a notification.
    func postNotification(){
        // Note: - This is the important part pass your object instance as object parameter.
        let yourObjectInstance = YourCustomObject()
        NotificationCenter.default.post(name: .yourNotificationName, object: yourObjectInstance)
    }
}

// MARK: -Notification  Receiver class
class NotificationReceiverClass: UIViewController {
    // MARK: - ViewController Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        // Register your notification listener
        NotificationCenter.default.addObserver(self, selector: #selector(didReceiveNotificationWithCustomObject), name: .yourNotificationName, object: nil)
    }

    // MARK: - Helpers
    @objc private func didReceiveNotificationWithCustomObject(notification: Notification){
        // Important: - Grab your custom object here by casting the notification object.
        guard let yourPassedObject = notification.object as? YourCustomObject else {return}
        // That's it now you can use your custom object
        //
        //

    }
      // MARK: - Deinit
  deinit {
      // Save your memory by releasing notification listener
      NotificationCenter.default.removeObserver(self, name: .yourNotificationName, object: nil)
    }




}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.