Swift 源码解读 - Print.swift

从 Swift 开源以来,一直说要看下源码的,结果现在都拖到 Swift 4.x 了,今天抽时间编译了 Swift 的源码,如何编译这里就不介绍了,可以参考 如何阅读 Swift 标准库中的源码

这里给自己定了个小目标,晚上抽空阅读下 Swift 源码,作为夜读系列,来扩展下自己的知识面。

先看下 print() 的源码:

@inline(never)
public func print(
  _ items: Any...,
  separator: String = " ",
  terminator: String = "\n"
) {
  if let hook = _playgroundPrintHook {
    var output = _TeeStream(left: "", right: _Stdout())
    _print(
      items, separator: separator, terminator: terminator, to: &output)
    hook(output.left)
  }
  else {
    var output = _Stdout()
    _print(
      items, separator: separator, terminator: terminator, to: &output)
  }
}

@inline(never) 说明了这个函数 never 编译成 inline 的形式,@inline(__always) 则刚好相反。

没有阅读源码前,一直都是靠习惯写着代码,并没有去看过 print() 的 api,一开始还真不知道 separator 和 terminator 两个参数,这两个参数也不用解析了,分割符和终止符。有没有想起曾经的 println() 了呢。

if let hook = _playgroundPrintHook {}

这句应该是判断是否 playground,然后再设置相应的 output,这里可以看出 playground 中通过 TeeStream 来 output,而其它则是 Stdout. 这个方法里面,实质调用的还是 _print() 方法:

@_versioned
@inline(never)
internal func _print<Target : TextOutputStream>(
  _ items: [Any],
  separator: String = " ",
  terminator: String = "\n",
  to output: inout Target
) {
  var prefix = ""
  output._lock()
  defer { output._unlock() }
  for item in items {
    output.write(prefix)
    _print_unlocked(item, &output)
    prefix = separator
  }
  output.write(terminator)
}

上面代码可以看出,_print 是通过 _print_unlocked 输出内容的,我们再跳转到 -print_unlock 中查看:

internal func _print_unlocked<T, TargetStream : TextOutputStream>(
  _ value: T, _ target: inout TargetStream
) {
  // Optional has no representation suitable for display; therefore,
  // values of optional type should be printed as a debug
  // string. Check for Optional first, before checking protocol
  // conformance below, because an Optional value is convertible to a
  // protocol if its wrapped type conforms to that protocol.
  if _isOptional(type(of: value)) {
    let debugPrintable = value as! CustomDebugStringConvertible
    debugPrintable.debugDescription.write(to: &target)
    return
  }
  if case let streamableObject as TextOutputStreamable = value {
    streamableObject.write(to: &target)
    return
  }

  if case let printableObject as CustomStringConvertible = value {
    printableObject.description.write(to: &target)
    return
  }

  if case let debugPrintableObject as CustomDebugStringConvertible = value {
    debugPrintableObject.debugDescription.write(to: &target)
    return
  }

  let mirror = Mirror(reflecting: value)
  _adHocPrint_unlocked(value, mirror, &target, isDebugPrint: false)
}

通过:

rintableObject.description.write(to: &target)

可以看出来,如果输入的对象如果实现 TextOutputStreamable,则打印出来的是它的值,如果它实现的是 CustomStringConvertible 或者 CustomDebugStringConvertible 时,print 实际打印出来的 description 内容。

CustomStringConvertible 和 CustomDebugStringConvertible 我们都是比较熟悉的,但是 TextOutputStreamable 这个并不多见,这时候就需要我们去查下文档了:

F776601F-EF83-4A07-89D8-7C7B61DEE27A.png

如果是字符类型的,直接打印的就是它们的内容,但如果是整形、enum 这一些类型的怎么处理呢,看该方法最后两句代码:

let mirror = Mirror(reflecting: value)
 _adHocPrint_unlocked(value, mirror, &target, isDebugPrint: false)

这里做了一个映射的处理,根据不同的类型,按照不同的格式打印,这里就不继续说下去了,直接看下 _adHocPrint_unlocked 方法的源码就可以理解了。

推荐阅读
Swift 解读 - 前言
Swift 解读 - Collection 大家族(上篇)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 关于 Swift 重要这个文档所包含的准备信息, 是关于开发的 API 和技术的。这个信息可能会改变, 根据这个文...
    无沣阅读 4,271评论 1 27
  • 世不容吾,吾抗世而行 ,天不容吾,吾以天为仇,命不容吾,吾以血破命 ,还吾面目,现吾本真
    紫耀职场阅读 48评论 0 0
  • 4 你是不是对我有意思啊? 安娜的家族是世界上都排的上号的黑道世家,虽然从她父母那里继承了一副好皮囊,可行事作风却...
    余晖皆烬阅读 432评论 2 6