探索Swift標準庫源代碼

您是否發現本身沒法理解框架或庫,並但願您能看到源代碼?Apple沒有共享源代碼,UIKit但若是您正在努力理解的方法是Swift標準庫的一部分,那麼您很幸運。git

訪問GitHub存儲庫

Apple在公共GitHub存儲庫中發佈Swift編程語言的源代碼,包括標準庫:github

您可能會發如今GitHub上瀏覽存儲庫已足以快速查看但我喜歡克隆並下載本地副本:編程

$ mkdir swift-source
$ cd swift-source/
$ git clone https://github.com/apple/swift.git
Cloning into 'swift'...
remote: Enumerating objects: 915646, done.
remote: Total 915646 (delta 0), reused 0 (delta 0), pack-reused 915646
Receiving objects: 100% (915646/915646), 415.74 MiB | 6.42 MiB/s, done.
Resolving deltas: 100% (742664/742664), done.
Checking out files: 100% (16802/16802), done.

複製代碼

您能夠將swift文件夾放入Xcode項目中進行瀏覽,但這會使個人Mac旋轉沙灘球幾分鐘。我更喜歡用BBEdit打開文件夾,它既快又有更好的多文件搜索工具。swift

Swift repo文件夾層次結構

您將在core子目錄中找到標準庫的源代碼:bash

$ cd swift/stdlib/public/core

複製代碼

值得花時間瀏覽源代碼。我發現它有很好的記錄和信息。讓咱們看一個源代碼有助於咱們理解的示例。app

一個問題 String

我最近寫了關於在Swift中測試空字符串的文章。在那篇文章中,我聲稱你應該使用isEmpty而不是count避免迭代整個字符串。一位讀者問我這是否是真的?個人說法來自String文件:框架

要檢查字符串是否爲空,請使用其isEmpty屬性,而不是將其中一個視圖的長度與0進行比較。與isEmpty不一樣,計算視圖的count屬性須要迭代字符串的元素。dom

咱們能比信任文檔更好嗎?咱們可使用標準庫源代碼來查看字符串的工做方式isEmptycount工做方式嗎?編程語言

StringCharacterView

在標準庫源代碼中查找的位置並不老是很明顯。搜索core目錄最終會帶您到正確的地方,但也能夠帶走一些兔子洞。有一個String.swift文件,但它不包含任何一個isEmptycount工具

回想一下個人Swift String備忘單,您可能還記得Swift 4將字符串的默認視圖設置爲一組字符。目錄中有一個StringCharacterView.swift文件core擴展String爲採用BidirectionalCollection協議:

// StringCharacterView.swift
extension String: BidirectionalCollection {

複製代碼

StringCharacterView沒有定義isEmpty,但咱們發現count

public var count: Int {
    return distance(from: startIndex, to: endIndex)
  }

複製代碼

distance方法調用咱們仍須要查找的內部方法,但它是一個開始:

public func distance(from start: Index, to end: Index) -> IndexDistance {
    return _distance(from: start, to: end)
  }

複製代碼

BidirectionalCollection

雙向集合擴展了集合,以在集合上添加向後遍歷:

// BidirectionalCollection.swift
public protocol BidirectionalCollection: Collection
where SubSequence: BidirectionalCollection, Indices:
BidirectionalCollection {

複製代碼

這是咱們找到實現的地方,_distance而且能夠看到它對集合進行迭代(向前或向後):

internal func _distance(from start: Index, to end: Index) -> Int {
  var start = start
  var count = 0

  if start < end {
    while start != end {
      count += 1
      formIndex(after: &start)
    }
  }
  else if start > end {
    while start != end {
      count -= 1
      formIndex(before: &start)
    }
  }

  return count
}

複製代碼

讓咱們繼續前進,看看可否找到isEmpty

採集

Collection協議的基礎上Sequence,並增長了startIndexendIndex朋友與咱們共同的屬性isEmptycount

// Collection.swift (details omitted)
public protocol Collection: Sequence {

  var startIndex: Index { get }
  var endIndex: Index { get }

  var isEmpty: Bool { get }
  var count: Int { get }

複製代碼

源代碼中的註釋爲咱們提供了更多提示:

對於不符合的集合RandomAccessCollection,訪問該count屬性會迭代集合的元素。

由於count有這個警告:

複雜性:O(1)若是集合符合RandomAccessCollection; 不然,O(n),其中n是集合的長度。

評論確認了咱們的理解,String但也告訴咱們爲何會這樣。重要的是該系列是否符合RandomAccessCollection。相似的類型Array容許隨機訪問,但String不容許。有關完整列表,請參閱RandomAccessCollection

Collection.swift文件的下方,咱們找到了一個協議擴展,它最終爲咱們提供瞭如下的默認實現isEmpty

public var isEmpty: Bool {
  return startIndex == endIndex
}

複製代碼

因此對於a String,咱們最好isEmpty不要使用而不是count


轉載自:www.jianshu.com/p/dfab3739c…

相關文章
相關標籤/搜索