Swift高级分享 - 探索Swift标准库源代码

15 篇文章 0 订阅

您是否发现自己无法理解框架或库,并希望您能看到源代码?Apple没有共享源代码,UIKit但如果您正在努力理解的方法是Swift标准库的一部分,那么您很幸运。

访问GitHub存储库

Apple在公共GitHub存储库中发布Swift编程语言的源代码,包括标准库:

您可能会发现在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 repo文件夹层次结构

您将在core子目录中找到标准库的源代码:

$ cd swift/stdlib/public/core

值得花时间浏览源代码。我发现它有很好的记录和信息。让我们看一个源代码有助于我们理解的示例。

一个问题 String

我最近写了关于在Swift中测试空字符串的文章。在那篇文章中,我声称你应该使用isEmpty而不是count避免迭代整个字符串。一位读者问我这是不是真的?我的说法来自String文件:

要检查字符串是否为空,请使用其isEmpty属性,而不是将其中一个视图的长度与0进行比较。与isEmpty不同,计算视图的count属性需要迭代字符串的元素。

我们能比信任文档更好吗?我们可以使用标准库源代码来查看字符串的工作方式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


点击此处进交流群 ,来一起交流或者发布您的问题,意见或反馈,让我知道您想要分享的任何建议和更正。

谢谢阅读~点个赞再走呗!?

原文地址:https://useyourloaf.com/blog/exploring-the-swift-standard-library-source-code/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值