Skip to content

Commit f96159b

Browse files
committed
[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>
1 parent 43f39b0 commit f96159b

File tree

5 files changed

+22
-297
lines changed

5 files changed

+22
-297
lines changed

stdlib/public/SDK/Foundation/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ add_swift_library(swiftFoundation ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SD
2424
IndexSetThunks.m
2525
Measurement.swift
2626
Notification.swift
27-
NotificationThunks.m
2827
NSStringEncodings.swift
2928
PersonNameComponents.swift
3029
TypePreservingNSNumber.mm
3130
URL.swift
3231
URLComponents.swift
3332
URLRequest.swift
3433
UUID.swift
35-
UserInfo.swift
3634
Hashing.swift
3735
Hashing.m
3836
Thunks.mm

stdlib/public/SDK/Foundation/Notification.swift

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@
1313
@_exported import Foundation // Clang module
1414

1515

16-
@_silgen_name("__NSNotificationCreate")
17-
internal func __NSNotificationCreate(_ name: NSString, _ object: AnyObject?, _ userInfo: AnyObject?) -> NSNotification
18-
19-
@_silgen_name("__NSNotificationUserInfo")
20-
internal func __NSNotificationUserInfo(_ notif: NSNotification) -> AnyObject?
21-
2216
/**
2317
`Notification` encapsulates information broadcast to observers via a `NotificationCenter`.
2418
*/
@@ -34,12 +28,12 @@ public struct Notification : ReferenceConvertible, Equatable, Hashable {
3428
public var object: Any?
3529

3630
/// Storage for values or objects related to this notification.
37-
public var userInfo: [String : Any]?
31+
public var userInfo: [AnyHashable : Any]?
3832

3933
/// Initialize a new `Notification`.
4034
///
4135
/// The default value for `userInfo` is nil.
42-
public init(name: Name, object: Any? = nil, userInfo: [String : Any]? = nil) {
36+
public init(name: Name, object: Any? = nil, userInfo: [AnyHashable : Any]? = nil) {
4337
self.name = name
4438
self.object = object
4539
self.userInfo = userInfo
@@ -61,8 +55,6 @@ public struct Notification : ReferenceConvertible, Equatable, Hashable {
6155
public typealias Name = NSNotification.Name
6256

6357
/// Compare two notifications for equality.
64-
///
65-
/// - note: Notifications that contain non NSObject values in userInfo will never compare as equal. This is because the type information is not preserved in the `userInfo` dictionary.
6658
public static func ==(lhs: Notification, rhs: Notification) -> Bool {
6759
if lhs.name.rawValue != rhs.name.rawValue {
6860
return false
@@ -80,10 +72,8 @@ public struct Notification : ReferenceConvertible, Equatable, Hashable {
8072
}
8173
if let lhsUserInfo = lhs.userInfo {
8274
if let rhsUserInfo = rhs.userInfo {
83-
if lhsUserInfo.count != rhsUserInfo.count {
84-
return false
85-
}
86-
return _NSUserInfoDictionary.compare(lhsUserInfo, rhsUserInfo)
75+
// user info must be compared in the object form since the userInfo in swift is not comparable
76+
return lhs._bridgeToObjectiveC() == rhs._bridgeToObjectiveC()
8777
} else {
8878
return false
8979
}
@@ -116,11 +106,7 @@ extension Notification : _ObjectiveCBridgeable {
116106

117107
@_semantics("convertToObjectiveC")
118108
public func _bridgeToObjectiveC() -> NSNotification {
119-
if let info = userInfo {
120-
return __NSNotificationCreate(name.rawValue as NSString, object.map { $0 as AnyObject }, _NSUserInfoDictionary.bridgeValue(from: info))
121-
}
122-
123-
return NSNotification(name: name, object: object, userInfo: nil)
109+
return NSNotification(name: name, object: object, userInfo: userInfo)
124110
}
125111

126112
public static func _forceBridgeFromObjectiveC(_ x: NSNotification, result: inout Notification?) {
@@ -130,18 +116,7 @@ extension Notification : _ObjectiveCBridgeable {
130116
}
131117

132118
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNotification, result: inout Notification?) -> Bool {
133-
if let userInfo = __NSNotificationUserInfo(x) {
134-
if let info : [String : Any]? = _NSUserInfoDictionary.bridgeReference(from: userInfo) {
135-
result = Notification(name: x.name, object: x.object, userInfo: info)
136-
return true
137-
} else {
138-
result = nil
139-
return false // something terrible went wrong...
140-
}
141-
} else {
142-
result = Notification(name: x.name, object: x.object, userInfo: nil)
143-
}
144-
119+
result = Notification(name: x.name, object: x.object, userInfo: x.userInfo)
145120
return true
146121
}
147122

stdlib/public/SDK/Foundation/NotificationThunks.m

Lines changed: 0 additions & 31 deletions
This file was deleted.

stdlib/public/SDK/Foundation/UserInfo.swift

Lines changed: 0 additions & 224 deletions
This file was deleted.

0 commit comments

Comments
 (0)