NSNumber
reference type, for e.g. Int32
, U
_ObjectiveCBridgeable
(The following answer is based on using Swift 2.2 and XCode 7.3.)
Just as I was pondering over whether to post or simply skip this question, I stumbled over swift/stdlib/public/core/BridgeObjectiveC.swift in the Swift source code, specifically the protocol _ObjectiveCBridgeable
. I've briefly noticed the protocol previously at Swiftdoc.org, but in its current (empty) blueprint form in the latter, I've never given much thought to it. Using the blueprints for _ObjectiveCBridgeable
from the Swift source we can, however, swiftly let some native of custom type conform to it.
Before proceeding, note that _ObjectiveCBridgeable
is an internal/hidden protocol (_UnderScorePreFixedProtocol
), so solutions based on it might break without warning in upcoming Swift versions.
Enabling Int64
bridging to Foundation class NSNumber
As an example, extend Int64
to conform to _ObjectiveCBridgeable
, and subsequently test if this quite simple fix is sufficient for the implicit type conversion (bridging) from Int64
to Foundation class NSNumber
holds.
import Foundation
extension Int64: _ObjectiveCBridgeable {
public typealias _ObjectiveCType = NSNumber
public static func _isBridgedToObjectiveC() -> Bool {
return true
}
public static func _getObjectiveCType() -> Any.Type {
return _ObjectiveCType.self
}
public func _bridgeToObjectiveC() -> _ObjectiveCType {
return NSNumber(longLong: self)
}
public static func _forceBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) {
result = source.longLongValue
}
public static func _conditionallyBridgeFromObjectiveC(source: _ObjectiveCType, inout result: Int64?) -> Bool {
self._forceBridgeFromObjectiveC(source, result: &result)
return true
}
}
Test:
/* Test case: scalar */
let fooInt: Int = 42
let fooInt64: Int64 = 42
var fooAnyObj : AnyObject
fooAnyObj = fooInt // OK, natively
fooAnyObj = fooInt64 // OK! _ObjectiveCBridgeable conformance successful
/* Test case: array */
let fooIntArr: [Int] = [42, 23]
let fooInt64Arr: [Int64] = [42, 23]
var fooAnyObjArr : [AnyObject]
fooAnyObjArr = fooIntArr // OK, natively
fooAnyObjArr = fooInt64Arr // OK! _ObjectiveCBridgeable conformance successful
Hence, conformance to _ObjectiveCBridgeable
is indeed sufficient to enable automatic by-assignment bridging to the corresponding Foundation class; in this case, NSNumber
(in Swift, __NSCFNumber
).
Enabling Int8
, UInt8
, Int16
, UInt16
, Int32
, UInt32
, (Int64
), and UInt64
bridging to NSNumber
The above conformance of Int64
to _ObjectiveCBridgeable
can easily be modified to cover any of the Swift-native integer types, using the NSNumber
conversion table below.
/* NSNumber initializer: NSNumber native Swift type property
-------------------------------- -----------------------------------
init(char: <Int8>) .charValue
init(unsignedChar: <UInt8>) .unsignedCharValue
init(short: <Int16>) .shortValue
init(unsignedShort: <UInt16>) .unsignedShortValue
init(int: <Int32>) .intValue
init(unsignedInt: <UInt32>) .unsignedIntValue
init(longLong: <Int64>) .longLongValue
init(unsignedLongLong: <UInt64>) .unsignedLongLongValue */