是否可以将(U)Int8 / 16/32/64类型的Swifts自动数值桥接到Foundation(NSNumber)?
题
- 是否有可能重复雨燕数值桥接基金会:■
NSNumber
引用类型,例如Int32
,UInt32
,Int64
和UInt64
类型?具体来说,复制下面介绍的自动预分配桥接。
这种解决方案的预期用法示例:
let foo : Int64 = 42
let bar : NSNumber = foo
/* Currently, as expected, error:
cannot convert value of type 'Int64' to specified type 'NSNumber */
背景
一些本机Swift数(值)类型可以自动桥接到NSNumber
(引用)类型:
迅数字结构类型的实例,例如
Int
,UInt
,Float
,Double
,和Bool
,不能由所表示的
AnyObject
类型,因为AnyObject
仅代表一个类类型的实例。但是,Foundation
启用桥接到时,可以将Swift数值分配给常量和AnyObject
类型变量,
作为 类的 桥接实例NSNumber
。…
Swift会自动将某些本机数字类型(例如
Int
和)桥Float
接到NSNumber
。通过这种桥接,您可以NSNumber
从以下类型之一创建 :let n = 42 let m: NSNumber = n
它还允许您将类型的值传递
Int
给例如 期望为的参数NSNumber
。…以下所有类型都会自动桥接到NSNumber:
- Int - UInt - Float - Double - Bool
那么,为什么要尝试为IntXX
/ UIntXX
类型复制呢?
主要是:
好奇心,这是由于最近看到一些问题而引起的,这些问题涉及一些困惑,这些困惑涵盖了为什么一个Int
值类型似乎可以由一个AnyObject
(引用)变量表示,而例如Int64
,不能;这自然可以通过上面提到的桥接来解释。
上面的问答均未提及从非桥接类型实际实现到AnyObject
(NSNumber
)的这种自动桥接的可能性Int64
,UInt16
依此类推。这些线程中的答案(正确地)集中在解释为什么AnyObject
不能保存值类型,以及如何不桥接IntXX
/
UIntXX
类型以将其自动转换为基础的基础Foundation类型。
其次:
对于同时在32位和64位体系结构上运行的应用程序,存在一些狭窄的用例-AnyObject
在某些情况下使用隐式转换为的Swift本机数字类型-
在使用egInt32
或Int64
type优先Int
。一个(有点)这样的例子:
-
是(可能):通过遵守协议
_ObjectiveCBridgeable
(以下答案基于使用 Swift 2.2 和XCode 7.3的情况。)
正如我在考虑是发布还是跳过该问题时,我偶然发现了
swift/stdlib/public/core/BridgeObjectiveC.swift
Swift源代码,尤其是协议_ObjectiveCBridgeable
。我之前在Swiftdoc.org上已经简短地注意到了该协议,但是在后者的当前(空)蓝图形式中,我从没有对此进行过多考虑。_ObjectiveCBridgeable
但是,使用来自Swift来源的蓝图,我们可以迅速让一些自定义类型的本机遵循它。在继续之前,请注意这
_ObjectiveCBridgeable
是一个内部/隐藏协议(_UnderScorePreFixedProtocol
),因此在即将发布的Swift版本中,基于该协议的解决方案可能会在没有警告的情况下中断。
启用
Int64
桥接至基金会类NSNumber
作为一个示例,扩展
Int64
以符合_ObjectiveCBridgeable
,然后测试此非常简单的修复程序是否足以将隐式类型转换(桥接)从Int64
Foundation类NSNumber
保留。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 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
因此,符合
_ObjectiveCBridgeable
确实足以使自动预分配桥接到相应的Foundation类。在这种情况下NSNumber
(在Swift中__NSCFNumber
)。
启用
Int8
,UInt8
,Int16
,UInt16
,Int32
,UInt32
,(
Int64
)和UInt64
桥接NSNumber
使用下面的转换表
Int64
,_ObjectiveCBridgeable
可以轻松地修改to
的上述一致性,以涵盖任何Swiftn本地整数类型NSNumber
。/* 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 */
-
无法将NSNumber桥接到Float Swift 3.3
2021-01-31 关注 0 浏览191 1答案
-
int8量化:32位浮点数 float32 转化成 8位定点数 int8一...
2022-03-02 关注 0 浏览36 1答案
-
32 位和 64 位的 JVM,int 类型变量的长度是多数?
2021-11-25 关注 0 浏览114 1答案
-
32 位和 64 位的 JVM,int 类型变量的长度是多数?
2021-09-18 关注 0 浏览200 1答案
-
关于将uint8转换为int8的困惑
2021-02-01 关注 0 浏览233 1答案
-
将字符串转换为int8数组
2021-01-31 关注 0 浏览80 1答案
-
与Go语言中的特定类型(int64 / uint64)相比,常规类型(int / uint)有什么优势?
2021-02-01 关注 0 浏览137 1答案
-
如何自动将强类型枚举转换为 int?
2022-07-28 关注 0 浏览15 1答案
-
将参考bean按类型自动连接到列表中
2021-01-31 关注 0 浏览84 1答案
-
将float64类型的np.array转换为uint8缩放值类型
2021-01-29 关注 0 浏览283 1答案