自己选择的路,跪着也要把它走完

341 1

Lock

无并发,不编码。而只要一说到多线程或者并发的代码,我们可能就很难绕开对于锁的讨论。简单来说,为了在不同线程中安全地访问同一个资源,我们需要这些访问顺序进行。Cocoa 和 Objective-C 中加锁的方式有很多,但是其中在日常开发中最常用的应该是 @synchronized,这个关键字可以用来修饰一个变量,并为其自动加上和解除互斥锁。这样,可以保证变量在作用范围内不会被其他线程改变。举个...
- 阅读全文 -
277 0

delegate

Cocoa 开发中接口-委托 (protocol-delegate) 模式是一种常用的设计模式,它贯穿于整个 Cocoa 框架中,为代码之间的关系清理和解耦合做出了不可磨灭的贡献。 在 ARC 中,对于一般的 delegate,我们会在声明中将其指定为 weak,在这个 delegate 实际的对象被释放的时候,会被重置回 nil。这可以保证即使 delegate 已经不存在时,我们也不会由...
- 阅读全文 -
435 1

代码组织和 Framework

Apple 为了 iOS 平台的安全性考虑,是不允许动态链接非系统的框架的。因此在 app 开发中我们所使用的第三方框架如果是以库文件的方式提供的话,一定都是需要链接并打包进最后的二进制可执行文件中的静态库。最初级和原始的静态库是以 .a 的二进制文件加上一些 .h 的头文件进行定义的形式提供的,这样的静态库在使用时比较麻烦,我们除了将其添加到项目和配置链接外,还需要进行指明头文件位置等工作...
- 阅读全文 -
326 0

Protocol Extension

Swift 2 中引入了一个非常重要的特性,那就是 protocol extension。在 Swift 1.x 中,extension 仅只能作用在实际的类型上 (也就是 class, struct 等等),而不能扩展一个 protocol。在 Swift 中,标准库的功能基本都是基于 protocol 来实现的,举个最简单的例子,我们每天使用的 Array 就是遵守了 Collectio...
- 阅读全文 -
445 0

indirect 和嵌套 enum

在涉及到一些数据结构的经典理论和模型 (没错,就是链表,树和图) 时,我们往往会用到嵌套的类型。比如链表,在 Swift 中,我们可以这样来定义一个单向链表: class Node<T> { let value: T? let next: Node<T>? init(value: T?, next: Node<T>?) { ...
- 阅读全文 -
268 0

Associated Object

不知道是从什么时候开始,“是否能通过 Category 给已有的类添加成员变量” 就成为了一道 Objective-C 面试中的常见题目。不幸的消息是这个面试题目在 Swift 中可能依旧会存在。 得益于 Objective-C 的运行时和 Key-Value Coding 的特性,我们可以在运行时向一个对象添加值存储。而在使用 Category 扩展现有的类的功能的时候,直接添加实例变量这...
- 阅读全文 -
314 0

尾递归

递归在程序设计中是一种很有用的方法,它可以将复杂的过程用易于理解的方式转化和描述。举个例子,比如我们想要写一个从 0 累加到 n 的函数,如果我们不知道等差数列求和公式的话,就可以用递归的方式来做: func sum(n: UInt) -> UInt { if n == 0 { return 0 } return n + sum(n - 1) }...
- 阅读全文 -
255 0

列举enum类型

设想我们有这样一个需求,通过对于一副扑克牌的花色和牌面大小的 enum 类型,凑出一套不含大小王的扑克牌的数组。 扑克牌花色和牌面大小分别由下面两个 enum 来定义: enum Suit: String { case Spades = "黑桃" case Hearts = "红桃" case Clubs = "草花&...
- 阅读全文 -
233 0

兼容性

作为一门新兴语言,Swift 必然会经常性地发生变化。可以预见到在未来的一到两年内 Swift 必然会迎来很多的修正和特性强化。现在的 Swift 作为一门 app 开发语言,最终的运行环境会是各式各样的电子设备。在语言版本不断更新变化的同时,如何尽可能地使更多的设备和系统可以使用这门语言开发的 app,是最大的问题之一。 Apple 通过将一个最小化的运行库集成打包到 app 中这样的方式...
- 阅读全文 -
258 0

泛型扩展

Swift 对于泛型的支持使得我们可以避免为类似的功能多次书写重复的代码,这是一种很好的简化。而对于泛型类型,我们也可以使用 extension 为泛型类型添加新的方法。 与为普通的类型添加扩展不同的是,泛型类型在类型定义时就引入了类型标志,我们可以直接使用。例如 Swift 的 Array 类型的定义是: public struct Array<Element> : Colle...
- 阅读全文 -
896 2

闭包歧义

Swift 的闭包写法很多,但是最正规的应该是完整地将闭包的输入和输出都写上,然后用 in 关键字隔离参数和实现。比如我们想实现一个 Int 的 extension,使其可以执行闭包若干次,并同时将次数传递到闭包中: extension Int { func times(f: Int -> ()) { print("Int") ...
- 阅读全文 -
728 0

Core Data

相信大多数开发者第一次接触到 Objective-C 的 @dynamic 都是在和 Core Data 打交道的时候。Objective-C 中的 @dynamic 和 Swift 中的 dynamic 关键字完全是两回事。在 Objective-C 中,如果我们将某个属性实现为 @dynamic 的话,就意味着告诉编译器我们不会在编译时就确定这个属性的行为实现,因此不需要在编译期间对这个...
- 阅读全文 -
618 0

Swift 中的测试

在软件开发中,测试的重要性不言而喻。Xcode 中集成了 XCTest 作为测试框架,Swift 代码的测试默认也使用这个框架进行。 关于 XCTest 的使用方法,比如像 setUp,tearDown 以及 testxxx 等在 Swift 下和以前也并没有什么不同,作为一本介绍 tip 的书籍,我不打算在此重复这些。如果对测试的理论基础和实践方法感兴趣的话,不妨看看 Objective-...
- 阅读全文 -
563 0

属性访问控制

Swift 中由低至高提供了 private,internal 和 public 三种访问控制的权限。默认的 internal 在绝大部分时候是适用的,另外由于它是 Swift 中的默认的控制级,因此它也是最为方便的。 但是对于一个严格的项目来说,精确的最小化访问控制级别对于代码的维护来说还是相当重要的。对于方法来说比较直接,我们想让同一 module (或者说是 target) 中的其他代...
- 阅读全文 -
651 0

宏定义 define

Swift 中没有宏定义了。 宏定义确实是一个让人又爱又恨的特性,合理利用的话,可以让我们写出很多简洁漂亮的代码,但是同时,不可否认的是宏定义无法受益于 IDE 工具,难以重构和维护,很可能隐藏很多 bug,这对于开发其实并不是一件好事。 Swift 中将宏定义彻底从语言中拿掉了,并且 Apple 给了我们一些替代的建议: 使用合适作用范围的 let 或者 get 属性来替代原来的宏定义值,...
- 阅读全文 -