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 ...
随机推荐
- JVM 中知识
1.栈:(stack) 存放的都是方法中的局部变量 方法的运行一定要在栈当中 局部变量:方法参数,方法{}内部的变量 作用域:一旦超出作用域,立刻从栈中消失 2.堆:(heap) 凡是new出来的东西 ...
- 836. Rectangle Overlap
class Solution { public: bool isRectangleOverlap(vector<int>& rec1, vector<int>& ...
- 通过http.client解析url返回的数据时为什么中文变成了unicode码
今天在解析json数据的时候得到了一堆这样的数据:{"errNum":0,"errMsg":"success","retData& ...
- Javascript php 异常捕获
JavaScript try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块. JavaScript 语句 try 和 cat ...
- CHAPITRE III
Il me fallut longtemps pour comprendre d'où il venait. Le petit prince, qui me posait beaucoup de qu ...
- RNN文章总结
1.RNN 基本结构类型 2. RNN 3.零基础入门深度学习(5) - 循环神经网络 4.
- 基础练习 回形取数 (循环 + Java 输入输出外挂)
基础练习 回形取数 时间限制:1.0s 内存限制:512.0MB 问题描述 回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度.一开始位于矩阵左上角,方 ...
- java编程IO简单回顾和学习
java编程IO操作必不可少的,很久不玩IO,回顾一下,写了几个小程序,记录一下,方便查阅和学习. 1.给出一个整数数组,将其写入一个文件,再从文件中读出,并按整数大小逆序打印. package co ...
- 2018/02/25 PendingIntent使用
https://www.cnblogs.com/liyiran/p/4656821.html http://blog.csdn.net/ydpl2007/article/details/7591642 ...
- 手机开发-Android
Android 语言.JAVA 开发环境.一是JDKjava开发工具包,二是eclipse开发工具IDE,三是Android SDK安卓软件开发包,四是ADT Android开发工具把JDK和Andr ...