ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 NSNotificationCenter 传递对象

我正在尝试将我的应用程序委托中的对象传递给另一个类中的通知接收器。

我想传递整数 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 传递给另一个类。

对于 swift 2.0 和 swift 3.0 stackoverflow.com/questions/36910965/…

L
LearnCocos2D

您必须使用“userInfo”变体并传递一个包含 messageTotal 整数的 NSDictionary 对象:

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);
    }
}

谢谢,我将 messageTotal 设置为 UIButton 上的徽章,您知道如何使用新的徽章计数刷新按钮吗?在 viewDidLoad 中显示图像的代码是 UIBarButtonItem *eRXButton = [BarButtonBadge barButtonWithImage:buttonImage badgeString:@"1" atRight:NO toTarget:self action:@selector(eRXButtonPressed)];
我不确定您为什么需要比较 notification.name。当您执行 addObserver() 时,应执行名称的映射。仅在观察特定通知时才应调用 receiveTestNotification。
Johan,在这种简单的情况下,您是正确的,但是可能有多个通知触发同一个处理程序
D
David Douglas

在提供的解决方案的基础上,我认为展示一个传递您自己的自定义数据对象的示例可能会有所帮助(我在此处根据问题将其称为“消息”)。

A 类(发件人):

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

B 类(接收器):

- (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
    }
}

为什么这个答案没有更多的赞成票?!它工作完美,不是黑客!
@Kairos,因为它不是为这样使用而设计的。 postNotificationName 中的 object 参数应表示发送此通知的参数。
是的,该对象应该使用 userInfo 参数作为 NSDictionary 传递,并且上面接受的答案现在已被编辑以显示这一点。
这非常具有误导性,为什么这个答案有这么多赞成?这应该被删除。每个人都应该使用正是为此创建的 userInfo。
好的,感谢您的反馈...我已更新答案以使用 userInfo 字典作为传递对象数据的方式。
f
frouo

斯威夫特 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.key0Notification.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
谢谢,从那以后似乎 Key 结构已被删除。我正在更新答案
C
Community

斯威夫特 2 版本

正如@Johan Karlsson 指出的那样......我做错了。这是使用 NSNotificationCenter 发送和接收信息的正确方法。

首先,我们看一下 postNotificationName 的初始化器:

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

source

我们将使用 userInfo 参数传递我们的信息。 [NSObject : AnyObject] 类型是 Objective-C 的保留。因此,在 Swift 领域,我们需要做的就是传入一个 Swift 字典,其中的键来自 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() 的预期用途。但你并不孤单。我见过许多开发人员使用 object 参数来发送用户对象。第二个参数,对象,是为发送者保留的。您应该真正使用 userInfo 来发送各种对象。否则你可能会遇到随机崩溃等。
M
Mussa Charles

Swift 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)
    }




}


是的,它使用 object(在 NotificationCenter.default.post 调用中)传递对象 - 但是,这不是它的用途。 Apple 文档指出,object 是“发布通知的对象。”。请改用 userInfo 来传递自定义数据(如本页许多其他答案所建议的那样)。
嗨,@JRV,感谢您的见解,我当时在我的应用程序上使用了这个实现,到目前为止没有问题。您是否介意澄清使用我上面的实现可能会出现哪些问题或副作用?如果您可以附上支持的测试代码,这将非常有帮助。
正如我所写的,它会起作用,而且我自己实际上也做过同样的事情——直到我更仔细地阅读了 Apple 的文档🙈。而且我不建议使用 Apple 自己的文档,因为它可能会在未来的 NSNotificationCenter 实现中导致意想不到的结果。这是一篇与您的具体问题有关的 SO 帖子:stackoverflow.com/questions/33635445
这是一篇关于 object 参数的实际用途以及如何使用它的帖子:stackoverflow.com/questions/8779220

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅