NSNotification完成原理(结构设计、告诉怎么存储的、name&observer&SEL之间的联系等)

NSNotification是iOS中用于完成音讯告诉的类,它采用了观察者形式来完成跨层传递音讯。NSNotification的完成原理涉及到NSNotification、NSNotificationCenter、Observation和NCTable这几个主要类和结构体。

  1. NSNotification
    NSNotification是用于向其他目标发送告诉的类,它包含了一些必要的信息,包括告诉的称号、发送告诉的目标和可选的用户信息。NSNotification目标是不可变的,一旦创立就不能修改。[1]

  2. NSNotificationCenter
    NSNotificationCenter是NSNotification的办理类,它是一个单例目标。它负责办理一切的NSNotification目标,并将它们发送给对应的观察者。NSNotificationCenter内部保护了一个NCTable结构体,用于存储观察者和告诉之间的联系。[1]

  3. Observation和NCTable
    Observation是一个结构体,用于封装观察者和观察者的办法。它包含了观察者目标、办法选择器、下一个Observation节点的指针等信息。NCTable是一个结构体,用于存储Observation目标。它包含了一个大局的目标表NCTable,其中包含了wildcard、nameless和named等字段,分别用于存储没有告诉称号和目标的告诉、没有告诉称号但有目标的告诉,以及有告诉称号和目标的告诉。[1]

  4. name、observer和SEL之间的联系
    在NSNotification的完成中,name和Observation是映射联系。name和observer都包含在Observation结构体中,经过NCTable中的hash表来建立它们之间的联系。详细来说,nameless表中的hash表的key是object参数,value是Observation结构体;named表中的hash表的key是name参数,value是另一个hash表,这个hash表的key是object参数,value是Observation结构体。经过这种办法,NSNotification完成了name、observer和SEL之间的联系。[1]


Learn more:

  1. iOS进阶之NSNotification的完成原理 – 简书
  2. iOS开发 – NSNotification原理理解 | 幸运四叶草
  3. iOS NSNotification完成原理 – 简书

告诉的发送是同步的,仍是异步

告诉的发送是同步的。

在iOS中,告诉的发送是同步的操作。当调用postNotification:办法发送告诉时,该办法会立行将告诉发送给一切注册的观察者,并等候观察者完成对告诉的处理后才会继续履行发送告诉的代码。

这意味着在发送告诉的过程中,发送告诉的线程会被堵塞,直到一切观察者都接纳到并处理完告诉。这种同步的发送办法能够确保告诉的可靠传递和处理次序的一致性。

需求留意的是,告诉的接纳和处理是异步的。当观察者接纳到告诉时,它会在自己的线程中异步处理告诉,以防止堵塞主线程或其他线程的履行。

总结起来,告诉的发送是同步的,发送告诉的线程会被堵塞直到一切观察者接纳并处理完告诉。而告诉的接纳和处理是异步的,观察者会在自己的线程中异步处理告诉。

NSNotificationCenter承受音讯和发送音讯是在一个线程里吗?怎么异步发送音讯

NSNotificationCenter的音讯接纳和发送是在同一个线程中进行的。

当调用postNotification:办法发送告诉时,告诉会立即发送给一切注册的观察者,而且发送告诉的线程会被堵塞,直到一切观察者都接纳并处理完告诉。这意味着告诉的发送和观察者的处理是在同一个线程中进行的。

假如你期望异步发送音讯,能够运用postNotificationName:object:userInfo:办法,并结合GCD(Grand Central Dispatch)来完成异步操作。详细步骤如下:

  1. 创立一个自定义的行列,用于履行异步操作。能够运用dispatch_queue_create函数创立一个串行行列或并发行列。

  2. 在自定义行列中运用dispatch_async函数来履行发送告诉的操作。将postNotificationName:object:userInfo:办法放在dispatch_async的block中,以确保在异步行列中履行。

示例代码如下:

// 创立一个自定义行列
let customQueue = DispatchQueue(label: "com.example.notificationQueue")
// 在自定义行列中异步发送告诉
customQueue.async {
    NotificationCenter.default.post(name: NSNotification.Name("CustomNotification"), object: nil, userInfo: nil)
}

经过将发送告诉的操作放在自定义行列中的异步使命中,能够完成异步发送音讯的作用。这样发送告诉的操作将不会堵塞当时线程,而是在后台线程中履行。

需求留意的是,接纳告诉的观察者的处理依然是在告诉所在的线程中进行的。假如你期望观察者的处理也是在异步线程中进行,能够在观察者的处理代码中运用GCD来完成异步操作。

NSNotificationQueue是异步仍是同步发送?在哪个线程呼应

NSNotificationQueue是同步发送告诉的。

NSNotificationQueue是一个用于办理告诉的行列,它能够依照指定的次序发送告诉。当调用NSNotificationQueue的enqueueNotification:postingStyle:办法发送告诉时,告诉会被立即发送,而且发送告诉的线程会被堵塞,直到一切观察者都接纳并处理完告诉。

告诉的接纳和处理是在告诉所在的线程中进行的。假如告诉是在主线程中发送的,那么观察者也会在主线程中接纳和处理告诉。假如告诉是在其他线程中发送的,那么观察者也会在相应的线程中接纳和处理告诉。

需求留意的是,NSNotificationQueue并不是常用的告诉发送办法,一般更常用的是直接运用NSNotificationCenter的postNotification:办法来发送告诉。而NSNotificationCenter的告诉发送是同步的,会堵塞当时线程直到一切观察者接纳并处理完告诉。

总结起来,NSNotificationQueue是同步发送告诉的,发送告诉的线程会被堵塞直到一切观察者接纳并处理完告诉。告诉的接纳和处理是在告诉所在的线程中进行的。

NSNotificationQueue和runloop的联系

NSNotificationQueue和RunLoop之间有一定的联系。

NSNotificationQueue是用于办理告诉的行列,它能够依照指定的次序发送告诉。而RunLoop是iOS中用于处理事件和定时器的机制。

NSNotificationQueue能够将告诉增加到RunLoop中,以便在特定的运转循环形式下发送告诉。经过调用NSNotificationQueue的enqueueNotification:postingStyle:办法,并指定postingStyle为NSPostWhenIdle或NSPostASAP,能够将告诉增加到RunLoop中,并在运转循环闲暇或尽快时发送告诉。

当RunLoop处于运转状况时,它会不断地查看是否有待处理的事件或告诉。假如有待处理的告诉在RunLoop中,RunLoop会将告诉发送给相应的观察者,并在观察者的线程中处理告诉。

需求留意的是,NSNotificationQueue并不依赖于RunLoop来发送告诉。即便没有RunLoop,NSNotificationQueue依然能够发送告诉,仅仅告诉的发送不会遭到RunLoop的调度和控制。

总结起来,NSNotificationQueue能够将告诉增加到RunLoop中,并在特定的运转循环形式下发送告诉。RunLoop会在运转循环中查看并处理待处理的告诉,并将告诉发送给相应的观察者。但NSNotificationQueue并不依赖于RunLoop来发送告诉,它能够独登时发送告诉。

怎么确保告诉接纳的线程在主线程

要确保告诉接纳的线程在主线程中,能够运用以下办法:

  1. 在注册观察者时,指定观察者办法履行的行列为主行列。能够运用NotificationCenteraddObserver(forName:object:queue:using:)办法来注册观察者,并将queue参数设置为OperationQueue.main,这样观察者办法就会在主线程中履行。
NotificationCenter.default.addObserver(forName: NSNotification.Name("NotificationName"), object: nil, queue: OperationQueue.main) { notification in
    // 在主线程中处理告诉
    // ...
}
  1. 在发送告诉时,确保在主线程中发送。能够运用DispatchQueue.main.async来将发送告诉的操作放在主行列中履行。
DispatchQueue.main.async {
    NotificationCenter.default.post(name: NSNotification.Name("NotificationName"), object: nil)
}

经过以上两种办法,能够确保告诉的接纳和处理都在主线程中进行。这样能够防止在观察者办法中进行UI更新或其他需求在主线程履行的操作时出现线程不一致的问题。

需求留意的是,假如告诉是在其他线程中发送的,观察者办法依然会在主线程中履行。这是由于在注册观察者时指定了观察者办法履行的行列为主行列。

页面毁掉时不移除告诉会溃散吗

iOS页面毁掉时不移除告诉可能会导致一些问题,但不一定会导致溃散。

当一个页面被毁掉时,假如该页面依然注册了告诉观察者但没有及时移除,那么当告诉被发送时,观察者办法依然会被调用。这可能导致以下问题:

  1. 野指针拜访:假如在页面毁掉后,告诉触发了已被毁掉的页面的观察者办法,而该办法中拜访了已被释放的目标,就会导致野指针拜访,可能引发溃散。

  2. 内存走漏:假如页面毁掉后,告诉触发了已被毁掉的页面的观察者办法,而该办法中持有了其他目标的强引用,就会导致内存走漏,由于这些目标无法被释放。

为了防止这些问题,一般建议在页面毁掉时移除告诉的观察者。能够在页面的deinit办法中调用NotificationCenterremoveObserver(_:name:object:)办法,将观察者从告诉中心中移除。

deinit {
    NotificationCenter.default.removeObserver(self)
}

这样,在页面毁掉时,告诉触发时就不会再调用已被毁掉的页面的观察者办法,然后防止了潜在的问题。

尽管不移除告诉可能会导致问题,但不一定会导致溃散。详细是否会导致溃散取决于观察者办法中的详细完成和触发告诉的时机。为了确保代码的健壮性和可靠性,建议在页面毁掉时一直移除告诉的观察者。

屡次增加同一个告诉会是什么成果?屡次移除告诉呢

When the same notification is added multiple times in iOS, the result depends on how the notification is registered and handled. Here are the possible outcomes:

  1. Multiple notifications are received: If the same notification is added multiple times without removing it, the observer method associated with the notification will be called multiple times when the notification is posted. This can result in the observer method being executed multiple times, leading to duplicated actions or behavior.

  2. No additional effect: In some cases, adding the same notification multiple times may not have any additional effect. The notification system in iOS is designed to handle multiple registrations for the same notification without causing any issues. In this case, the observer method will still be called only once when the notification is posted.

It’s important to note that adding the same notification multiple times can lead to unexpected behavior and should generally be avoided. It’s recommended to register the notification observer only once and remove it when it’s no longer needed.

When it comes to removing notifications, the same principles apply:

  1. Removing the notification once: If the notification observer is removed once using the removeObserver(_:name:object:) method, the observer will no longer receive any notifications for that specific name and object combination.

  2. Removing the notification multiple times: Removing the same notification multiple times does not have any additional effect. Once the observer is removed, it will no longer receive notifications for that specific name and object combination, regardless of how many times the removal is called.

To ensure proper handling of notifications, it’s recommended to remove the observer when it’s no longer needed, such as when the associated object or view controller is deallocated.


Learn more:

  1. Double Notifications on iPhone – Apple Community
  2. Receiving duplicate push notificat… | Apple Developer Forums
  3. ios – Adding the same observer multiple times without removing it – Stack Overflow