Swift NotificationCenter传递userInfo至视图控制器时崩溃求助
Hey there! Sorry to hear you're stuck with this crash when posting a notification—let’s break down the most common reasons this happens and how to fix them.
1. Your userInfo contains non-serializable objects
NotificationCenter requires all objects in userInfo to be serializable (i.e., conform to NSCoding or be a Foundation framework type like NSString, NSNumber, NSArray, or NSDictionary). If you’re passing a custom object that doesn’t implement NSCoding, this will almost certainly cause a crash when posting the notification.
Fix:
Either:
- Implement
NSCodingfor your custom object:class CustomUser: NSObject, NSCoding { let id: String let username: String init(id: String, username: String) { self.id = id self.username = username } // MARK: - NSCoding func encode(with coder: NSCoder) { coder.encode(id, forKey: "id") coder.encode(username, forKey: "username") } required init?(coder: NSCoder) { id = coder.decodeObject(forKey: "id") as? String ?? "" username = coder.decodeObject(forKey: "username") as? String ?? "" } } - Or, convert your custom object into a dictionary of basic types before adding it to
userInfo:let userDict = ["id": user.id, "username": user.username] NotificationCenter.default.post(name: .userUpdated, object: nil, userInfo: userDict)
2. The listener view controller has been deallocated (dangling pointer)
If your view controller was dismissed/deallocated but you didn’t remove it as a notification observer, NotificationCenter will try to send the notification to a released object—this causes a classic "bad access" crash.
Fix:
- Use
weak selfin your observer closure to avoid retaining the view controller unnecessarily:// When adding the observer NotificationCenter.default.addObserver(forName: .userUpdated, object: nil, queue: .main) { [weak self] notification in guard let self = self else { return } // Exit if the VC is gone self.handleUserUpdate(notification) } - Always remove observers in your view controller’s
deinit(even though block-based observers auto-remove, it’s a safe habit):deinit { NotificationCenter.default.removeObserver(self) }
3. You’re force-unwrapping userInfo in the receiver
If you post the notification with userInfo: nil but your receiver uses let info = notification.userInfo! (force unwrap), this will crash immediately.
Fix:
Use optional binding to safely access userInfo:
@objc func handleUserUpdate(_ notification: Notification) { guard let userInfo = notification.userInfo else { print("No user info received") return } // Extract values from userInfo safely guard let userId = userInfo["userId"] as? String else { return } // Do something with userId }
4. Mismatched notification names (less likely to crash, but worth checking)
While this won’t cause a crash directly, if your observer is listening for a different notification name than you’re posting, your receiver won’t trigger—and if your logic relies on that notification, it could lead to unexpected behavior (or indirect crashes).
Fix:
Define notification names in a shared extension to avoid typos:
extension Notification.Name { static let userUpdated = Notification.Name("UserUpdatedNotification") } // Post with: NotificationCenter.default.post(name: .userUpdated, object: nil, userInfo: userInfo) // Listen with: NotificationCenter.default.addObserver(forName: .userUpdated, ...)
Start by checking these areas—chances are one of them is causing your crash. Let me know if you need to dive deeper with specific code snippets!
内容的提问来源于stack exchange,提问作者rharding

