Swfit 里 Array(五)和 NSArray 转换

只看 Swift Array 到 NSArray
Array 里的源代码
extension Array {
@inlinable
public // @SPI(Foundation)
func _bridgeToObjectiveCImpl() -> AnyObject {
return _buffer._asCocoaArray()
}
}
这里看到,调用了_asCocoaArray 函数。
#if _runtime(_ObjC)
/// Convert to an NSArray.
///
/// - Precondition: `Element` is bridged to Objective-C.
///
/// - Complexity: O(1).
@inlinable
internal __consuming func _asCocoaArray() -> AnyObject {
if count == 0 {
return _emptyArrayStorage
}
if _isBridgedVerbatimToObjectiveC(Element.self) {
return _storage
}
return __SwiftDeferredNSArray(_nativeStorage: _storage)
}
#endif
如果是空数组
直接返回了一个空的地址,注意所有的空数组都指向了同一个内存地址。
SWIFT_RUNTIME_STDLIB_API
swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
// HeapObject header;
{
&swift::CLASS_METADATA_SYM(s19__EmptyArrayStorage), // isa pointer
},
// _SwiftArrayBodyStorage body;
{
0, // int count;
1 // unsigned int _capacityAndFlags; 1 means elementTypeIsBridgedVerbatim
}
};
如果元素类型可以直接转为 Objc
返回真正持有元素的类。
如果元素不能直接转为 Objc
返回一个__SwiftDeferredNSArray 类型。
__SwiftDeferredNSArray 是什么

是一个 NSArray 的子类,实现了objectAt(index) 方法。
internal func objectAt(_ index: Int) -> AnyObject {
return withUnsafeBufferOfObjects {
objects in
_precondition(
_isValidArraySubscript(index, count: objects.count),
"Array index out of range")
return objects[index]
}
}
实现的核心在withUnsafeBufferOfObjects方法里。
internal override func withUnsafeBufferOfObjects<R>(
_ body: (UnsafeBufferPointer<AnyObject>) throws -> R
) rethrows -> R {
while true {
var buffer: UnsafeBufferPointer<AnyObject>
// If we've already got a buffer of bridged objects, just use it
if let bridgedStorage = _heapBufferBridged {
let bridgingBuffer = _BridgingBuffer(bridgedStorage)
buffer = UnsafeBufferPointer(
start: bridgingBuffer.baseAddress, count: bridgingBuffer.count)
}
// If elements are bridged verbatim, the native buffer is all we
// need, so return that.
else if let buf = _nativeStorage._withVerbatimBridgedUnsafeBuffer(
{ $0 }
) {
buffer = buf
}
else {
// Create buffer of bridged objects.
let objects = _nativeStorage._getNonVerbatimBridgingBuffer()
// Atomically store a reference to that buffer in self.
if !_stdlib_atomicInitializeARCRef(
object: _heapBufferBridgedPtr, desired: objects.storage!) {
// Another thread won the race. Throw out our buffer.
_destroyBridgedStorage(
unsafeDowncast(objects.storage!, to: __BridgingBufferStorage.self))
}
continue // Try again
}
defer { _fixLifetime(self) }
return try body(buffer)
}
}
这一段的核心在于最后一个else里的内容。
首先创建了一段缓冲区,其中存储了数组中元素被 bridege 到 OC 对象的结果,然后对每一个缓存区中的元素增加一个引用。
分配内存并做转换的代码
/// Bridge array elements and return a new buffer that owns them.
///
/// - Precondition: `Element` is bridged non-verbatim.
override internal func _getNonVerbatimBridgingBuffer() -> _BridgingBuffer {
_internalInvariant(
!_isBridgedVerbatimToObjectiveC(Element.self),
"Verbatim bridging should be handled separately")
let count = countAndCapacity.count
let result = _BridgingBuffer(count)
let resultPtr = result.baseAddress
let p = _elementPointer
for i in 0..<count {
(resultPtr + i).initialize(to: _bridgeAnythingToObjectiveC(p[i]))
}
_fixLifetime(self)
return result
}
下面是对_bridgeAnythingToObjectiveC的注释。
/// Bridge an arbitrary value to an Objective-C object.
///
/// - If `T` is a class type, it is always bridged verbatim, the function
/// returns `x`;
///
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`,
/// returns the result of `x._bridgeToObjectiveC()`;
///
/// - otherwise, we use **boxing** to bring the value into Objective-C.
/// The value is wrapped in an instance of a private Objective-C class
/// that is `id`-compatible and dynamically castable back to the type of
/// the boxed value, but is otherwise opaque.
///
// COMPILER_INTRINSIC
public func _bridgeAnythingToObjectiveC<T>(_ x: T) -> AnyObject {
Swfit 里 Array(五)和 NSArray 转换的更多相关文章
- Python:list 和 array的对比以及转换时的注意事项
Python:list 和 array的对比以及转换时的注意事项 zoerywzhou@163.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2017-6-4 ...
- 【C++自我精讲】基础系列五 隐式转换和显示转换
[C++自我精讲]基础系列五 隐式转换和显示转换 0 前言 1)C++的类型转换分为两种,一种为隐式转换,另一种为显式转换. 2)C++中应该尽量不要使用转换,尽量使用显式转换来代替隐式转换. 1 隐 ...
- oc随笔五:NSArray
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...
- Scala基础:闭包、柯里化、隐式转换和隐式参数
闭包,和js中的闭包一样,返回值依赖于声明在函数外部的一个或多个变量,那么这个函数就是闭包函数. val i: Int = 20 //函数func的方法体中使用了在func外部定义的变量 那func就 ...
- Swift中实现Array数组和NSArray数组的相互转换与遍历
Array是Swift中的数组数据类型.而NSArray是OC中的数组数据类型.两者有差别有联系.在Swift中有时候难免会使用到OC中的一些东西.今天我们就来Swift中使用NSArray和Arra ...
- JavaScript Array和string的转换
Array类可以如下定义: var aValues = new Array(); 如果预先知道数组的长度,可以用参数传递长度 var aValues = new Array(20); -------- ...
- 【不积跬步,无以致千里】五个常用的Linux监控脚本代码
为大家提供五个常用Linux监控脚本(查看主机网卡流量.系统状况监控.监控主机的磁盘空间,当使用空间超过90%就通过发mail来发警告.监控CPU和内存的使用情况.全方位监控主机),有需要的朋友不妨看 ...
- Swift 里 Array (四) Accessing Elements
根据下标取值 关键代码如下: func _getElement( _ index: Int, wasNativeTypeChecked: Bool, matchingSubscriptCheck: _ ...
- Swift 里 Array (三) Inspecting an Array
判断是否为空 使用的是Collection协议里isEmpty的判断. public var isEmpty: Bool { return startIndex == endIndex } start ...
随机推荐
- kbmmw 的HTTPSmartService 上传文件到服务器端
前面我写过了 HTTPSmartService 使用介绍,可以参见以前的文章. 前一向有同学问如何在http 页面表单上上传文件.一直没有时间回答,自己简单做了例子, 发现无法实现功能,今天花了一天时 ...
- idea如何将项目以eclipse保存
会生成 提交到svn eclipse 导入 首先使用TortoiseSVN下载要导入的项目 导入 已经存在的maven 项目 clean install -DskipTests t ...
- C# AOP框架入门(转)
出处:https://www.cnblogs.com/isaboy/p/Csharp_AOP_Log.html AOP面向切面编程(Aspect Oriented Programming),是通过预编 ...
- 解决设置select默认选中不生效的方法
$scope.storageTypeList = ['Glusterfs','NFS','Ceph']; 不生效的方法: <select class="form-control&quo ...
- Jquery 单击_双击_鼠标经过_鼠标离开_背景样式变化
列表页点击.鼠标经过离开背景变化 <script type="text/javascript"> $(function () { $("table tr&qu ...
- C++获取当前进程绝对路径
获取进程的绝对路径(代码同时操作字符串获取了文件目录): 第一种代码: wstring GetProgramDir() { TCHAR exeFullPath[MAX_PATH]; // Full p ...
- Django-配置、静态文件与路由
-----配置文件 1.BASE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 2.DEBU ...
- Video Processing and Communications:(视频处理和通信)
https://max.book118.com/html/2017/1010/136711526.shtm Application of (GAN) of AI faceswap in Music V ...
- 一个封存Id与状态对应键值的神器,BigInteger的setBit和testBit用法实例
1,首先描述一下应用场景 比如,我们要对菜单做权限,控制不同角色菜单显示与不显示,角色为经理时,我们需要菜单id为 4,7,13,24的菜单显示,别的菜单不显示. 就是说,这时候我们要把4,7,13, ...
- CentOS 6.0 安装配置rails 2.3.11 + redmine 1.2.1 笔记
没想到安装过程这么曲折,gem安装时下载经常是不成功的,无耐只好把.gem文件下载回来再本地安装,加上radmine 1.2.1对各组件的版本了也比较挑剔,中间走了不少弯路,折腾了二天时间,终于摸清路 ...