Files
swift-mirror/stdlib/public/SDK/Foundation/Notification.swift
Philippe Hausler f96159b582 [Foundation] Scale back struct Notification's userInfo to be in-line with NSNotification
This simplifies the bridging story for Notifications to their objc counterparts since the id -> Any and AnyHashable changes have now been applied (which makes the previous boxing strategy no longer needed). Previous consumers of Notification that were using String keys should still work, however any explicit dictionary types should migrate from Swift 2.2 -> Swift 3 from userInfo as [NSObject:AnyObject] to [AnyHashable:Any]. The condition of distributed notifications (in non sandboxed apps) requiring plist types still applies and will fail at runtime if incorrect types are passed into the objective-c layer, and in the case of sandboxed apps userInfo still is forbidden (this change is a non functional change in the respect to those behaviors).

Resolves the following issues:
<rdar://problem/27426757>
<rdar://problem/27561621>
<rdar://problem/27259984>
2016-08-03 16:27:06 -07:00

138 lines
4.5 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@_exported import Foundation // Clang module
/**
`Notification` encapsulates information broadcast to observers via a `NotificationCenter`.
*/
public struct Notification : ReferenceConvertible, Equatable, Hashable {
public typealias ReferenceType = NSNotification
/// A tag identifying the notification.
public var name: Name
/// An object that the poster wishes to send to observers.
///
/// Typically this is the object that posted the notification.
public var object: Any?
/// Storage for values or objects related to this notification.
public var userInfo: [AnyHashable : Any]?
/// Initialize a new `Notification`.
///
/// The default value for `userInfo` is nil.
public init(name: Name, object: Any? = nil, userInfo: [AnyHashable : Any]? = nil) {
self.name = name
self.object = object
self.userInfo = userInfo
}
public var hashValue: Int {
return name.rawValue.hash
}
public var description: String {
return "name = \(name.rawValue), object = \(object), userInfo = \(userInfo)"
}
public var debugDescription: String {
return description
}
// FIXME: Handle directly via API Notes
public typealias Name = NSNotification.Name
/// Compare two notifications for equality.
public static func ==(lhs: Notification, rhs: Notification) -> Bool {
if lhs.name.rawValue != rhs.name.rawValue {
return false
}
if let lhsObj = lhs.object {
if let rhsObj = rhs.object {
if lhsObj as AnyObject !== rhsObj as AnyObject {
return false
}
} else {
return false
}
} else if rhs.object != nil {
return false
}
if let lhsUserInfo = lhs.userInfo {
if let rhsUserInfo = rhs.userInfo {
// user info must be compared in the object form since the userInfo in swift is not comparable
return lhs._bridgeToObjectiveC() == rhs._bridgeToObjectiveC()
} else {
return false
}
} else if rhs.userInfo != nil {
return false
}
return true
}
}
extension Notification: CustomReflectable {
public var customMirror: Mirror {
var children: [(label: String?, value: Any)] = []
children.append((label: "name", value: self.name.rawValue))
if let o = self.object {
children.append((label: "object", value: o))
}
if let u = self.userInfo {
children.append((label: "userInfo", value: u))
}
let m = Mirror(self, children:children, displayStyle: Mirror.DisplayStyle.class)
return m
}
}
extension Notification : _ObjectiveCBridgeable {
public static func _getObjectiveCType() -> Any.Type {
return NSNotification.self
}
@_semantics("convertToObjectiveC")
public func _bridgeToObjectiveC() -> NSNotification {
return NSNotification(name: name, object: object, userInfo: userInfo)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNotification, result: inout Notification?) {
if !_conditionallyBridgeFromObjectiveC(x, result: &result) {
fatalError("Unable to bridge type")
}
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNotification, result: inout Notification?) -> Bool {
result = Notification(name: x.name, object: x.object, userInfo: x.userInfo)
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNotification?) -> Notification {
var result: Notification? = nil
_forceBridgeFromObjectiveC(source!, result: &result)
return result!
}
}
extension NSNotification : _HasCustomAnyHashableRepresentation {
// Must be @nonobjc to avoid infinite recursion during bridging.
@nonobjc
public func _toCustomAnyHashable() -> AnyHashable? {
return AnyHashable(self as Notification)
}
}