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 ...
随机推荐
- hdu-1255(线段树求面积并)模板
题目链接:传送门 思路: (1)建立线段的信息,每个线段存储l到r的线段的x位置和y的起始点与终点. 建立线段树的节点信息,每个节点代表一个区间的信息,x表示区间的横坐标的位置,l,r表示纵坐标的范围 ...
- Codeforces Round #523 (Div. 2) F. Katya and Segments Sets (交互题+思维)
https://codeforces.com/contest/1061/problem/F 题意 假设存在一颗完全k叉树(n<=1e5),允许你进行最多(n*60)次询问,然后输出这棵树的根,每 ...
- SVD图片有损压缩测试
注意文件名别保持成svd.m,这样与系统的默认svd程序冲突 图片处理函数生成的三组二维数组对应RGB,处理时保留一组 clear all; close all; clc; a1=imread('C: ...
- 一个WCF 数据序列化问题
public class EMMPBaseMsg { public String Data { get; set; } public DateTime AddTime { get; set; } pu ...
- 二叉搜索树、AVL平衡二叉搜索树、红黑树、多路查找树
1.二叉搜索树 1.1定义 是一棵二叉树,每个节点一定大于等于其左子树中每一个节点,小于等于其右子树每一个节点 1.2插入节点 从根节点开始向下找到合适的位置插入成为叶子结点即可:在向下遍历时,如果要 ...
- C++STL 算法
算法部分主要由头文件<algorithm>,<numeric>和<functional>组成. <algorithm>是所有STL头文件中最大的一个,其 ...
- idea使用git提交代码到远程,这里是没有冲突的演示
首先在项目鼠标右键,找到Git,然后在Git选项里找到Add,点击: 添加到暂存区后,再次找到Git,找到Commit Directory,点击: 然后弹出这个界面: 选中你自己修改的记录,一些不必要 ...
- UVa 10828 Back to Kernighan-Ritchie (数学期望 + 高斯消元)
题意:给定一个 n 个结点的有向图,然后从 1 结点出发,从每个结点向每个后继结点的概率是相同的,当走到一个没有后继结点后,那么程序终止,然后问你经过每个结点的期望是次数是多少. 析:假设 i 结点的 ...
- mysql delete from table 失败
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; TRUNCATE TABLE ...
- matlab中的结构体
今天用imfinfo函数 >> K = imfinfo(‘colorbar_copy1.jpg’) K = 包含以下字段的 struct: Filename: 'E:\matlab\col ...