我想你一定是在开玩笑。
    源码怎么看,打开看呗!说这话的时候请收下我的轻蔑,哈哈。不过就这个问题我今天在知乎搜索了一通。不要问我为什么在知乎搜索,鬼知道知乎什么都有。
    那么,请收下我的提问:

    如何阅读Swift源码

    知乎果然没有让我失望,结果教程如下;

    如何阅读 Swift 标准库中的源码

    顺便提一下,这次搜索还让我发现了一个比较不错的swift网站,有心的同学请收下:swift.gg

    于是今天搞了下源码的编译,并了解到一个叫做 GYB 的东西,这个东西今天先放一下。源碼編譯的過程無非就是用 brew 下了一些命令行軟件,然後使用 build 腳本跑一下過程,在此也不多說。但是今天的重點當然是我們要從源碼出發搞一些事情。
    续:今天又build,发现也并没有得出什么重要的东西,只是把gyb文件生成为swift文件,其他过程不知道它经历了什么,对我想看源码没有任何作用,还跑了整整一个下午;对于只是想看代码的同学,还是用官网给出的gyb.py脚本做处理吧;
    1. hashable
    前两天写Dictionary时发现想用枚举做key,自定义一个Dictionary,value是#selector,但是在写的过程中发现说key值需要遵循hashable协议。可以看源码来理解一下。
    首先要找到Hashable文件,发现swift的标准核心库被放在 stdlib/public/core 下,有一个 Hashable.swift 文件,打开文件先是一大段的描述,大体内容就是hashable协议作用的场景,以及给出了一个小例子;

    一个Hash类型,提供了一个 hashValue 的属性,它是一个整型常量, 如果有两个相同类型的a,b,如果 a == b,那么 a.hashValue == b.hashValue;但是反过来,如果两个hash值相同,并不表示a 就一定等于 b;
    还有一点非常重要,就是在两次不同的程序执行中hash值并不保证相等,所以不要把hash值用在你的程序中;
    Hashable协议可用于struct,enum,class,它继承于 Equatable,所以遵循Hashable协议需要同时实现Hashable协议方法,以及 Equatable 协议方法;

    /// A point in an x-y coordinate system.
        struct GridPoint {
            var x: Int
            var y: Int
        }
    
         extension GridPoint: Hashable {
             var hashValue: Int {
                return x.hashValue ^ y.hashValue &* 16777619
            }
    
            static func == (lhs: GridPoint,rhs: GridPoint) -> Bool {
                return lhs.x == rhs.x && lhs.y == rhs.y
            }
        }
    
           var tappedPoints: Set = [GridPoint(x: 2,y: 3),GridPoint(x: 4,y: 1)]
           let nextTap = GridPoint(x: 0,y: 1)
           if tappedPoints.contains(nextTap) {
              print("Already tapped at (\(nextTap.x),\(nextTap.y)).")
           } else {
              tappedPoints.insert(nextTap)
              print("New tap detected at (\(nextTap.x),\(nextTap.y)).")
           }
          // Prints "New tap detected at (0,1).")

    在实现的代码里有一些奇怪的符号,暂时还有点摸不清头脑,有些是一些编译符号,大体能看懂点意思,但有些像@_silgen_name("_swift_stdlib_Hashable_isEqual_indirect")就完全看不懂,回头找人再请教;
    这里还要说的一个就是一个UnsafePointer<T>:

    在 Swift 中,指针都使用一个特殊的类型来表示,那就是 UnsafePointer。遵循了 Cocoa 的一贯不可变原则,UnsafePointer 也是不可变的。当然对应地,它还有一个可变变体,UnsafeMutablePointer。绝大部分时间里,C 中的指针都会被以这两种类型引入到 Swift 中:C 中 const 修饰的指针对应 UnsafePointer (最常见的应该就是 C 字符串的 const char * 了),而其他可变的指针则对应 UnsafeMutablePointer。除此之外,Swift 中存在表示一组连续数据指针的 UnsafeBufferPointer,表示非完整结构的不透明指针 copaquePointer 等等。另外你可能已经注意到了,能够确定指向内容的指针类型都是泛型的 struct,我们可以通过这个泛型来对指针指向的类型进行约束以提供一定安全性。

    需要具体了解的看这篇:UnsafePointe

    顺便吐槽句哈,apple的代码也还有这种东西,也不知道是修改过的没有;

    2. Equatable
    * 它是一种可用于值比较的类型;
    * 在序列和集合操作中,可以将一个遵循了Equatable协议的对象传递给contaions(_:)方法,来确定是否包含,用法如下:

    let students = ["nora","Fern","Ryan","Rainer"]
    
    let nametocheck = "Ryan"
    if students.contains(nametocheck) {
        print("\(nametocheck) is signed up!")
    } else {
        print("No record of \(nametocheck).")
    }
       // Prints "Ryan is signed up!"
    
    /// Conforming to the Equatable Protocol
    =
    • 本地类型继承自Equatable协议需要注意:
      1. 对于一个struct类型,它的所有存储属性都需要遵循Equatable协议;
      2. 对于一个enum类型,它的所有关联值都需要遵循Equatable协议;
      3. 如果上述标准不符合,需要在扩展中实现==静态方法;
        例如:
    class StreetAddress {
        let number: String
        let street: String
        let unit: String?
        init(_ number: String,_ street: String,unit: String? = nil) {
            self.number = number
            self.street = street
            self.unit = unit
        }
    }
    
    extension StreetAddress: Equatable {
        static func == (lhs: StreetAddress,rhs: StreetAddress) -> Bool {
            return
                lhs.number == rhs.number &&
                lhs.street == rhs.street &&
                lhs.unit == rhs.unit
        }
    }
    
    let addresses = [StreetAddress("1490","grove Street"),StreetAddress("2119","Maple Avenue"),StreetAddress("1400","16th Street")]
    let home = StreetAddress("1400","16th Street")
    print(addresses[0] == home)
    // Prints "false"
    print(addresses.contains(home))
    // Prints "true"
    • 另外我在这个实现里面看到了以前数学课知识的身影:
    • a == a is always true (Reflexivity) # 自反性
    • a == b implies b == a (Symmetry) # 对称性
    • a == b and b == c implies a == c (transitivity) # 传递性
      所以我们定义的==(两对象相等)完全取决于我们自己实现的静态方法:
    class IntegerRef: Equatable {
        let value: Int
        init(_ value: Int) {
            self.value = value
        }
        static func == (lhs: IntegerRef,rhs: IntegerRef) -> Bool {
            return lhs.value == rhs.value
        }
    }
    let a = IntegerRef(100)
    let b = IntegerRef(100)
    print(a == a,a == b,separator: ",")
    // Prints "true,true"

    而不相等的定义则完全是,自实现的相等操作取反:

    extension Equatable {
      /// Returns a Boolean value indicating whether two values are not equal.
      ///
      /// Inequality is the inverse of equality. For any values `a` and `b`,`a != b`
      /// implies that `a == b` is `false`.
      ///
      /// This is the default implementation of the not-equal-to operator (`!=`)
      /// for any type that conforms to `Equatable`.
      ///
      /// - Parameters:
      /// - lhs: A value to compare.
      /// - rhs: Another value to compare.
      @inlinable // FIXME(sil-serialize-all)
      @_transparent
      public static func != (lhs: Self,rhs: Self) -> Bool {
        return !(lhs == rhs)
      }
    }

    这个实现是已经定义好的!!!
    * =====的区别
    看一下这两者的区别:

    public protocol Equatable {
      /// Returns a Boolean value indicating whether two values are equal.
      ///
      /// Equality is the inverse of inequality. For any values `a` and `b`,
      /// `a == b` implies that `a != b` is `false`.
      ///
      /// - Parameters:
      /// - lhs: A value to compare.
      /// - rhs: Another value to compare.
      static func == (lhs: Self,rhs: Self) -> Bool
    }
    @inlinable // FIXME(sil-serialize-all)
    public func === (lhs: AnyObject?,rhs: AnyObject?) -> Bool {
      switch (lhs,rhs) {
      case let (l?,r?):
        return ObjectIdentifier(l) == ObjectIdentifier(r)
      case (nil,nil):
        return true
      default:
        return false
      }
    }

    从以上可以看出,==只是由实现好的静态函数决定,而===则是可以判断两个对象是否完全相等,这有点像判断两个指针相等一样,同样,我们要注意,如果两个可选对象都是nil,则也是===的;
    3. 搞清楚两个问题
    * UTC 与 GMT
    UTC(Coordinated Universal Time)标准时间参照,协调时间时,世界标准时间;
    GMT(Greenwich Mean Time)时区,即格林尼治时间,位于本初子午线的标界处时间,世界计算时间和经度的起点,GMT是个时区,等同于世界时,所以GMT = UTC + 0,我们国家所在时间均以北京时间计算,北京位于东八区,所以时区为GMT + 8;
    * Locale
    网上找了一圈,最后还是swift源码文档里给出的解释最靠谱:Locale封装了有关语言,文化和技术规范和标准的信息。由语言环境封装的信息示例包括,用于数字中小数点分隔符的符号以及格式化日期的方式。区域设置通常用于根据用户的习俗和偏好提供,格式化和解释信息。它们经常与格式化程序一起使用。虽然可以使用很多语言环境,但通常使用与当前用户关联的语言环境。
    语言环境跟系统的环境设置有关,会涉及到操作系统语言环境设置,个人理解就是一个国际化的东西。
    区域设置中的概念 LANGID & LCID:

    你一定不知道Swift源码怎么看?的更多相关文章

    1. html5利用canvas实现颜色容差抠图功能

      这篇文章主要介绍了html5利用canvas实现颜色容差抠图功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

    2. HTML5自定义视频播放器源码

      这篇文章主要介绍了HTML5自定义视频播放器源码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

    3. HTML5自定义mp3播放器源码

      这篇文章主要介绍了HTML5自定义mp3播放器源码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

    4. html5 canvas手势解锁源码分享

      这篇文章主要介绍了html5 canvas手势解锁源码分享,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下

    5. ios – 无法识别的选择器发送到实例NSTimer Swift

      解决方法让updateTime成为一个类方法.如果它是在一个纯粹的Swift类中,你需要在@objc前面说明该方法的声明,如:

    6. ios – Swift指针算术和解除引用;将一些类似C的地图代码转换为Swift

      我有一点似乎没有工作的Swift代码……解决方法您正在指定locationPointer指向新位置,但仍在下一行中使用ptr,并且ptr的值尚未更改.将您的最后一行更改为:或者你可以改变指向var的指针并推进它:

    7. ios – 类型推断(自动类型检测)如何在swift中工作?

      LLVM如何检测变量是一个字符串?

    8. ios – Swift可选项:语言问题,还是做错了什么?

      应该有可选的类型;type是但是,如果我这样做,它的工作原理:它似乎是基本的替代,但我可能会遗漏一些语言的细微差别.谁能对此有所了解?之后就像暧昧一样,更多,这是我的解决方案:这适用于所有非对象Swift对象,包括Swift字符串,数字等.感谢Viktor提醒我String不是Swift中的对象.如果您知道值的类型,您可以替换任何?使用适当的可选类型,如String?

    9. ios – 如何防止Parse保存PFObject儿童?

      我正面临着Parse和iOS的一个非常普遍的问题.我有一个类POST,具有以下结构:>text(String)>图像(PFFile)>LikesUsers(StringofString)>LikesCount(Int)>从(发布到用户的指针)如果用户(已登录)喜欢帖子.我只是递增喜欢并将用户的Objectid添加到数组中例如:User-2喜欢User-1的帖子.问题在这里.我不能保存PostObj

    10. ios – 覆盖Swift中的超类委托

      我正在开发一个包含两个UIViews的Swift(v1.2)项目.MyView和MyViewSubclass.MyView有一个委托,我想在MyViewSubclass中覆盖它作为一个子协议,类似于UITableViews有一个UITableViewDelegate,它也符合超级uiscrollviewdelegate.我的第一个想法是覆盖超类属性,但这会导致编译器错误,因为子类不能覆盖具有不同类

    随机推荐

    1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

      下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

    2. swift UISlider,UIStepper

      我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

    3. preferredFontForTextStyle字体设置之更改

      即:

    4. Swift没有异常处理,遇到功能性错误怎么办?

      本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

    5. 字典实战和UIKit初探

      ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

    6. swift语言IOS8开发战记21 Core Data2

      上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

    7. swift语言IOS8开发战记22 Core Data3

      上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

    8. swift实战小程序1天气预报

      在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

    9. 【iOS学习01】swift ? and !  的学习

      如果不初始化就会报错。

    10. swift语言IOS8开发战记23 Core Data4

      接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

    返回
    顶部