[swift-evolution] [Idea] Improved bridging of NSNumber and NSValue types
Mike Kasianowicz
mike at ap14.com
Sat Feb 27 16:48:56 CST 2016
Hello, I heard this is the place to talk about things we’d like to see in Swift.
There are a few improvements I’d like to see with Objective-C bridging. I find myself repeating the same three code patterns in order to have the best of both Objective-C and Swift worlds.
First, optional primitive types should map to optional NSNumber. Currently, they only map to NSNumber when used in an array or dictionary. The implicitly generated code would look like the following:
var optIntProperty: Int?
@objc(optIntProperty)
var objc_optIntProperty: NSNumber? {
get {
guard let value = self.optIntProperty else {
return nil
}
return NSNumber(integer: value)
}
set {
guard let value = newValue else {
self.optIntProperty = nil
return
}
self.optIntProperty = value.integerValue
}
}
In the code above, you cannot mark the Int? property dynamic - it causes a compiler error - but it would be nice if you could. This feature would allow shared ObjC classes to be more Swifty, and enable existing runtime reflection/serialization code. I could also see utility of NSNull-nil bridging for values in collections, though this is a rarer case.
Second, it would be nice for C-style structs to bridge to NSValue by default. Currently, every C struct has to implement NSValue bridging manually. I think it’s safe to say that if you mark a struct array property as @objc or dynamic that you typically want it to bridge to NSValue. Additionally, the same optional handling as noted above would be useful.
// pretend this struct were declared in C, or if we get struct exporting in the future (?)
public struct MyCStyleStruct {
public var intProp: Int
public var doubleProp: Float
}
extension MyCStyleStruct : _ObjectiveCBridgeable {
public typealias _ObjectiveCType = NSValue
public static func _isBridgedToObjectiveC() -> Bool {
return true
}
public static func _getObjectiveCType() -> Any.Type {
return NSValue.self
}
public func _bridgeToObjectiveC() -> _ObjectiveCType {
var sself = self
// would need compiler to create the @encode()
return NSValue(&sself, withObjCType: "{MyCStyleStruct=if}")
}
public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyCStyleStruct?) {
source.getValue(&result)
}
public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyCStyleStruct?) -> Bool {
_forceBridgeFromObjectiveC(source, result: &result)
return true
}
}
Finally, consider automatic bridging of RawRepresentable types (enums) as well, making the _ObjectiveCBridgeable code implicit in the following:
public enum MyEnum: Int {
case Zero = 0
case One = 1
case Two = 2
case Three = 3
}
extension MyEnum : _ObjectiveCBridgeable {
public typealias _ObjectiveCType = NSNumber
public static func _isBridgedToObjectiveC() -> Bool {
return true
}
public static func _getObjectiveCType() -> Any.Type {
return NSNumber.self
}
public func _bridgeToObjectiveC() -> _ObjectiveCType {
return NSNumber(integer: self.rawValue)
}
public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) {
result = MyEnum(rawValue: source.integerValue)
}
public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: MyEnum?) -> Bool {
_forceBridgeFromObjectiveC(source, result: &result)
return true
}
}
Opinions? Have any/all of these been discussed before?
Thanks!
Mike
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160227/f1ae6901/attachment.html>
More information about the swift-evolution
mailing list