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 {

posted on 2019-03-22 00:48  花老🐯  阅读(651)  评论(0编辑  收藏  举报

导航