Swifter Tips

字数 2339阅读 22

1.currying + target-action *

2.将 protocol 的方法声明为 mutating *
mutating 关键字修饰方法是为了能在该方法中修改 struct 或是 enum 的变量

3.Sequence - IteratorProtocol + Sequence ***

4.Tuple *

5.@autoclosure && ?? ** 简洁

6.@escaping - *

7.optional chaining *

8.operator * 声明操作符

9.func-params * - var + inout

10.literal *** - ExpressibleByArray/StringLiteral

11.subscript *** 简洁

12.func nesting * 比较有用

13.nameSpacing *

14.typealias *

15.associatedtype **** - 类型占位符

16.variadic ***

17.init * 自动调用父类的 init 方法

18.designated & convenience & required ***
最大的好处,保证依赖于某个 designated 初始化方法的 convenience 一直可用

19.init? *

20.static & class *

21.多类型和容器 ** - [protocol] + case typeValue(type) 两种方式封装进容器

22.default param *

23.regex *

24.pattern-match ****
Swift 的 switch 就是使用了 ~= 操作符进行模式匹配,case 指定的模式作为左参,被 switch 的作为右参

  1. … & ..< * - “a”…”z” + \0…~

26.AnyClass & meta type & .self ***
在将这些元类型存入数组并且传递给别的方法来进行配置这一点上,元类型编程就很难被替代。.Type 表示的是某个类型的元类型

27.protocol & class method ’s Self *** — type(of:)

28.dynamic Type * — 不支持

29.属性观察 *****
— 属性观察的一个重要用处是作为 设置值的验证
— 初始化方法对属性的设定,以及在 willSet 和 didSet 中对属性的再次设定都不会再次触发属性观察的调用
— set & willSet & didSet 不能同时出现,可以通过子类化实现
— didSet -> oldValue -> get

30.final ** 探讨比较有意思
OC 中指定 attribute((objc_requires_super)) 这样的属性来让编译器在子类没有调用父类方法时抛出警告

31.lazy *** — arr.lazy
— 对于那些不需要完全运行,可能提前退出的情况,使用 lazy 来进行性能优化

32.reflection & mirror * 实用性不大
— _Reflectable & _reflect -> Mirror
— dump() -> mirror.description
— KVC

33.ImplicitlyUnwrappedOptional ** — 历史原因
— 最大好处是,对于那些我们能确认的 API 来说,我们可直接进行属性访问和方法调用。不用 optional binding

34.多重 Optional *
— Optional == enum
— fr v -R xxx

35.Optional Map *** 自动解包
— 函子指的是可以被某个函数作用,并映射为另一组结果,而这组结果也是函子的值

36.protocol extension **
— 为 protocol 中定义的方法提供了默认实现
— type inference -> actual Type
<1> type method will be call, if didn’t have, -> extension default
— type inference -> protocol
<1> method in protocol, type method call. if didn’t have, -> extension default
<2> method not in protocol, -> extension default

37.where & pattern-match *

38.indirect & nested enum *

================================================================

1.selector ***
@objc - @objcMembers
使用 #selector 来从暴露给 OC 的代码中获取一个 selector

2.dynamic call instance method **
通过类型取出这个类型的某个实例方法的签名,然后再通过传递实例来拿到实际需要调用的方法。
— Type.instanceMethod -> currying - f(object)(1)

3.singleton *
— 在初始化类变量的时候,Apple 将会把这个初始化包装在一次 swift_once_block_invoke中,
保证它的唯一性。对于所有的全局变量,Apple 都会在底层使用类似 dispatch_once
的方式确保只以 lazy 的方式初始化一次。

4.条件编译 **
— custom flags

5.编译标记 *
— // MARK: - // TODO: // FIXME:

6.@UIApplicationMain *
main.swift

7.@objc & dynamic ***
将需要暴露给 OC 使用的任何地方(类、属性、方法)的声明前面加上 @objc 修饰符
如果需要和 OC 里的动态调用时相同的运行时特性的话,需要使用 dynamic - KVO

8.optional protocol & protocol extension **
— 使用 @objc 修饰的 protocol 就只能被 class 实现了
— 使用 protocol extension 提供默认实现,达到 optional

9.memory management & weak & unowned *
— 如果能够确定在访问时不会被释放的话,尽量用 owned,存在被释放的可能,用 weak

lazy var printName: ()->() = {
    [weak self] in
    if let strongSelf = self {
        print(“name is \(strongSelf.name)”)
    }
}

10.@autoreleasepool *
— 在 app 中,整个主线程其实是跑在一个自动释放池子里的,并且在每个主 Runloop 结束时进行 drain 操作。
这是一种必要的延迟释放的方式,因为我们有时候需要确保在方法内部初始化的生成的对象在被返回后别人还能使用,而不是立即被释放掉。
— 更进一步,其实 @autoreleasepool 在编译时会被展开为 NSAutoreleasePool,并附带 drain 方法的调用。
— autoreleasepool {}
— 实例方法 和 类方法 创建对象不同

  1. value & reference Type ***
    — 写时复制。
    — 将数组和字典设计为值类型最大的考虑是为了线程安全。当存储的元素较少时,会非常高效
    — 使用数组和字典时最佳实践:按照具体的数据规模和操作特点来决定是用值类型OR引用类型
    在需要处理大量数据并且频繁操作时 -> NSMutableArray & NSMutableDictionary。
    在容器条目小而容器本身数目多时 -> Array & Dictionary

  2. String & NSString ***

  3. UnsafePointer **
    — unsafeBitCast

  4. C 指针内存管理 *

  5. COpaquePointer & C convention *
    — @convention

  6. GCD & asyncAfter ***
    — 将一个闭包封装到 DispatchWorkItem 对象中,对其发送 cancel,来取消一个正在等待执行的 block

  7. 获取对象类型 **
    — type(of:)

  8. Introspection *
    — is,也可以用于 struct & enum 类型

  9. KeyPath & KVO *****
    — 像通过监听 model 的值来自动更新 UI 的绑定这样的工作,基本都是 KVO 来完成的
    — Swift 4 之前 ~ dynamic + @objc + method
    — 4 之后 ~ \Foo.bar $$$
    — 子类化重写属性

  10. 局部 scope *
    — local(_ colsure: ()->())
    — do { … }

  11. 判等 *
    == - OC 是判断两个对象是否指向同一块内存地址。
    ===

22.哈希 *

23.类簇 *
简单来说类簇就是使用一个统一的公共的类来订制单一的接口,然后在表面之下对应若干个私有类进行实现的方式。
这么做最大的好处是避免公开很多子类造成混乱。
类簇在子类种类繁多,但是行为相对统一的时候对于简化接口非常有帮助。
Swift 类簇构建,一种有效的方法是使用工厂方法

24.调用 C 动态库 *
MD5

25.输出格式化 *

26.Options * - OptionSet

27.数组 enumerate * - .enumerated()

28.类型编码 @encode * - .objCType
NSValue 设计的初衷就是被作为那些不能直接放入 NSArray 的值的容器来使用的。
存入 NSUserDefaults 可能有用。

29.C 代码调用 和 @asmname *
Darwin

30.delegate * - : class

31.Associated Object *

32.Lock *
其实 @synchronized 在幕后做的事情是调用了 objc_sync 中的 objc_sync_enter & objc_sync_exit 方法,并且加入了一些异常判断。

33.Toll-Free Bridging & Unmanaged<T> *
CF 现在也在 ARC 的范围内。
将这些返回 CF 对象的 API 导入 Swift 时,类型会对应为 Unmanaged<T>

================================================================

34.Swift 命令行工具 *
REPL Read-Eval-Print Loop
swift —help swiftc —help

35.随机数生成 *

36.print & debugPrint * - CustomStringConvertible & CustomDebugStringConvertible
这种按照特性进行分离的设计理念对于功能的可扩展性的提升很有帮助。

37.错误和异常处理 *
异常只是一个同步方法专用的处理机制。对于异步 API 出错时,保留了原来的 Error 的机制。

38.断言 *

39.fatalError *
抽象类型或者抽象函数
在面对这种情况时,为了确保子类实现这些方法,而父类中的方法不被错误地调用,
我们就可以利用 fatalError 来在父类中强制抛出错误,以保证使用这些代码的开发者
留意到他们必须在自己的子类中实现相关方法

相比起 模拟的抽象函数 的方式,面向协议编程能够提供编译时的保证,而不需要将检查推迟到运行的时候。

40.代码组织和 Framework **
.framework
lipo - 合并多个架构

41.安全的资源组织方式 * SwiftGen

42.Playground 延时运行 *
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

43.Playground 与 项目协作 *

44.Playground 与 可视化开发 *

45.数学和数字 *

46.JSON & Codable ***

47.NSNull *

48.文档注释 * alt + cmd + /

49.性能考虑 *

50.Log输出 **
#file #line

51.溢出 32 64 *

52.宏定义 define *
使用合适作用范围的 let 或者 get 属性来替代原来的宏定义值
对于宏定义的方法,类似地在同样作用域写为 Swift 方法

53.属性访问控制 *
open 标记的内容才能在别的框架中被继承或者重写。

54.Swift 中的测试 * @testable

55.Core Data * @dynamic == @NSManaged

56.闭包歧义 *

57.泛型扩展 *

58.兼容性 *

59.列举 enum 类型 *

60.尾递归 *