tripleCC的技术博客

ʕ•̫͡•ʔ-̫͡-ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ-̫͡-ʕ•͓͡•ʔ-̫͡-ʔ

Swift源码阅读Runtime

Swift开源之后,虽然大部分代码对于作为应用程序猿的我来说,花费大量时间去阅读,性价比有点不高,但是阅读下Foundation,学习学习Swift的编码范式还是不错的。

NSEnumerator.swift
1.遵循多个约束

其中范型NSGeneratorEnumerator定义如下:

1
2
3
4
5
6
7
8
9
10
internal class NSGeneratorEnumerator<Base : GeneratorType where Base.Element : AnyObject> : NSEnumerator {
    var generator : Base
    init(_ generator: Base) {
        self.generator = generator
    }

    override func nextObject() -> AnyObject? {
        return generator.next()
    }
}

上面有一点,就是范型类型的约束:遵守协议GeneratorType,并且是AnyObject类型。这个上次写的时候忘了,刚好这次记下这种写法。

NSObjCRuntime.swift
1.实现OC中NS_OPTIONS效果的swift形式的Option
1
2
3
4
5
6
7
public struct NSSortOptions : OptionSetType {
    public let rawValue : UInt
    public init(rawValue: UInt) { self.rawValue = rawValue }

    public static let Concurrent = NSSortOptions(rawValue: UInt(1 << 0))
    public static let Stable = NSSortOptions(rawValue: UInt(1 << 4))
}

以上是swift中很典型的Options,包括常见的UIViewAnimationOptions等。Concurrent和Stable是以静态属性存在的,所以可以直接使用NSSortOptions.属性名访问,在知道类型后,也可以简写.属性名

遵守OptionSetType表示NSSortOptions可以进行集合及位运算,也就是[.Concurrent, .Stable]等。所以为了实现以前OC中的NS_OPTIONS的位与效果,可以实现一个遵循OptionSetType协议的结构体:

1
2
3
4
5
6
7
public struct AnyOption: OptionSetType {
  public let rawValue: UInt
  public init(rawValue: UInt)  { self.rawValue = rawVale }  // 这个struct会自动构造,可以省略
  
  public static let TypeOne = AnyOption(rawValue: UInt(1 << 0))
  ...
}

值得注意的一点是,在OC中使用kNilOptions来表示NoneOption,swift中则是实用[]
所以可以进行位与操作的选项最好创建成遵守OptionSetType的struct,而不是enum。

2.范型协议
1
2
3
4
internal protocol _CFBridgable {
    typealias CFType
    var _cfObject: CFType { get }
}

在swift中,协议的范型是通过typealias关键字来实现的,而类、数组、方法和函数则是通过类型参数来实现:

1
2
3
func geneticFunction<T>(p: [T]) -> Bool {
  return true
}

遵守范型协议后可以这样来实现相应的属性:

1
2
3
4
5
6
class MyClass: Type {
    typealias MyType = String // 这句也可以省略
    var _type: String {
        return ""
    }
}

可以使用Self表示遵守范型协议的类型:

1
2
3
4
5
6
7
8
9
10
protocol EquatableSelf {
  func equals(other: Self) -> Bool
}

struct ImplicitStruct: EquatableSelf {
  var val: Int64
  func equals(other: ImplicitStruct) -> Bool {
      return self.val == other.val
  }
}

在不使用Self关键字的情况下,可以使用以下方式实现同样的类型:

1
2
3
4
5
6
7
8
9
10
11
12
protocol EquatableTypealias {
  typealias EquatableType
  func equals(other : EquatableType) -> Bool
}

struct ExplicitStruct : EquatableTypealias {
  typealias EquatableType = ExplicitStruct
  var val : Int64
  func equals(other: ExplicitStruct) -> Bool {
      return self.val == other.val;
  }
}

这里有一篇不错的文章,对范型协议进行了介绍Swift Generic Protocols

NSObject.swift
1.运算符重载
1
2
3
public func ==(lhs: NSObject, rhs: NSObject) -> Bool {
    return lhs.isEqual(rhs)
}

重载了两个NSObject对象的==运算符,实际上是使用swift中的===判断对象是否相等:

1
2
3
public func isEqual(object: AnyObject?) -> Bool {
  return object === self
}

需要注意的是上面对于NSObject重载的等价运算符是全局函数

在实现运算符重载时,需要注意对前后缀运算符重载,需要添加prefixpostfix关键字:

1
2
3
prefix func - (vector: Vector2D) -> Vector2D {
  return Vector2D(x: -vector.x, y: -vector.y)
}

改变左表达式的复合运算符,需要在对应的参数中添加inout关键字:

1
2
3
func += (inout left: Vector2D, right: Vector2D) {
  left = left + right
}
NSSwiftRuntime.swift

这个文件主要实现了Swift对于NS基础类型映射(基本也只能摸个大概,大部分还是不懂= =)。

其中有一个__CFInitializeSwift函数,本分函数体如下:

1
2
3
4
5
6
7
8
9
10
internal func __CFInitializeSwift() {
    _CFRuntimeBridgeTypeToClass(CFStringGetTypeID(), unsafeBitCast(_NSCFString.self, UnsafePointer<Void>.self))
    _CFRuntimeBridgeTypeToClass(CFArrayGetTypeID(), unsafeBitCast(_NSCFArray.self, UnsafePointer<Void>.self))
    _CFRuntimeBridgeTypeToClass(CFDictionaryGetTypeID(), unsafeBitCast(_NSCFDictionary.self, UnsafePointer<Void>.self))
    ....
    __CFSwiftBridge.NSObject.isEqual = _CFSwiftIsEqual
    __CFSwiftBridge.NSObject.hash = _CFSwiftGetHash
    __CFSwiftBridge.NSObject._cfTypeID = _CFSwiftGetTypeID
    ....
}

其中_CFRuntimeBridgeTypeToClass主要作用是使用对应ID为索引,将对应的类地址,存入一个全局的数组中。类似Objective-C中实例对象中的isa指向的东西,这样就可以根据这个索引对应的内容,来创建实例对象了。

1
2
3
4
5
void _CFRuntimeBridgeTypeToClass(CFTypeID cf_typeID, const void *cls_ref) {
    __CFLock(&__CFBigRuntimeFunnel);
    __CFRuntimeObjCClassTable[cf_typeID] = (uintptr_t)cls_ref;
    __CFUnlock(&__CFBigRuntimeFunnel);
}

_CFSwiftBridge是一个全局变量,其类型定义如下:

1
2
3
4
5
6
7
8
9
10
11
struct _CFSwiftBridge {
    struct _NSObjectBridge NSObject;
    struct _NSArrayBridge NSArray;
    struct _NSMutableArrayBridge NSMutableArray;
    struct _NSDictionaryBridge NSDictionary;
    struct _NSMutableDictionaryBridge NSMutableDictionary;
    struct _NSSetBridge NSSet;
    struct _NSMutableSetBridge NSMutableSet;
    struct _NSStringBridge NSString;
    struct _NSMutableStringBridge NSMutableString;
};

可以看到其成员对应的NS基础类型。取NSObject,类型定义如下:

1
2
3
4
5
struct _NSObjectBridge {
    CFTypeID (*_cfTypeID)(CFTypeRef object);
    CFHashCode (*hash)(CFTypeRef object);
    bool (*isEqual)(CFTypeRef object, CFTypeRef other);
};

可以看到其成员都是函数指针,在__CFInitializeSwift中对它们进行了初始化。比如_CFSwiftIsEqual,就是用Swift定义的判断两个对象是否相等的函数,其定义如下:

1
2
3
internal func _CFSwiftIsEqual(cf1: AnyObject, cf2: AnyObject) -> Bool {
    return (cf1 as! NSObject).isEqual(cf2)
}

最后__CFInitializeSwift在CFRuntime.c文件中的__CFInitialize函数即CoreFoundation初始化函数中进行调用:

1
2
3
4
....
extern void __CFInitializeSwift();
__CFInitializeSwift();
....

好了…但是基本还是云里雾里…

Comments