真正的爱情越久越不生锈

536 2

闭包歧义

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

Core Data

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

Swift 中的测试

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

属性访问控制

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

宏定义 define

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

溢出

对于 Mac 开发,我们早已步入了 64 位时代,而对 iOS 来说,64 位的乐章才刚刚开始。在今后一段时间内,我们都需要面临同时为 32 位和 64 位的设备进行开发的局面。由于这个条件所导致的最直接的一个结果就是数字类型的区别。 最简单的例子,在 Swift 中我们一般简单地使用 Int 来表示整数,在 iPhone 5 和以下的设备中,这个类型其实等同于 Int32,而在 64 位设...
- 阅读全文 -
401 0

Optional Map

我们经常会对 Array 类型使用 map 方法,这个方法能对数组中的所有元素应用某个规则,然后返回一个新的数组。我们可以在 CollectionType 的 extension 中找到这个方法的定义: extension CollectionType { public func map<T>(@noescape transform: ...
- 阅读全文 -
398 0

多重 Optional

Optional 可以说是 Swift 的一大特色,它完全解决了 “有” 和 “无” 这两个困扰了 Objective-C 许久的哲学概念,也使得代码安全性得到了很大的增加。但是一个陷阱 -- 或者说一个很容易让人迷惑的概念 -- 也随之而来,那就是多重的 Optional。 在深入讨论之前,可以让我们先看看 Optional 是什么。很多读者应该已经知道,我们使用的类型后加上 ? 的语法只...
- 阅读全文 -
405 0

隐式解包 Optional

相对于普通的 Optional 值,在 Swift 中我们还有一种特殊的 Optional,在对它的成员或者方法进行访问时,编译器会帮助我们自动进行解包,这就是 ImplicitlyUnwrappedOptional。在声明的时候,我们可以通过在类型后加上一个感叹号 (!) 这个语法糖来告诉编译器我们需要一个可以隐式解包的 Optional 值: var maybeObject: MyCla...
- 阅读全文 -
457 0

sizeof 和 sizeofValue

喜欢写 C 的读者可能会经常和 sizeof 打交道,不论是分配内存,I/O 操作,还是计算数组大小的时候基本都会用到。这个在 C 中定义的运算符可以作用于类型或者某个实际的变量,并返回其在内存中的尺寸 size_t (这是和平台无关的一个整数类型)。在 Cocoa 中,我们也有一部分 API 需要涉及到类型或者实例的内存尺寸,这时候就可以使用 sizeof 来计算。一个常见的用例是在从一个...
- 阅读全文 -
531 0

C 代码调用和 @asmname

如果我们导入了 Darwin 的 C 库的话,我们就可以在 Swift 中无缝地使用 Darwin 中定义的 C 函数了。它们涵盖了绝大多数 C 标准库中的内容,可以说为程序设计提供了丰富的工具和基础。导入 Darwin 十分简单,只需要加上 import Darwin 即可。但事实上,Foundation 框架中包含了 Darwin 的导入,而我们在开发 app 时肯定会使用 UIKit ...
- 阅读全文 -
619 0

Log 输出

Log 输出是程序开发中很重要的组成部分,虽然它并不是直接的业务代码,但是却可以忠实地反映我们的程序是如何工作的,以及记录程序运行的过程中发生了什么。 在 Swift 中,最简单的输出方法就是使用 print,在我们关心的地方输出字符串和值。但是这并不够,试想一下当程序变得非常复杂的时候,我们可能会输出很多内容,而想在其中寻找到我们希望的输出其实并不容易。我们往往需要更好更精确的输出,这包括...
- 阅读全文 -
606 0

类型编码 @encode

Objective-C 中有一些很冷僻但是如果知道的话在特定情况下会很有用的关键字,比如说通过类型获取对应编码的 @encode 就是其中之一。 在 Objective-C 中 @encode 使用起来很简单,通过传入一个类型,我们就可以获取代表这个类型的编码 C 字符串: char *typeChar1 = @encode(int32_t); char *typeChar2 = @enco...
- 阅读全文 -
602 0

数组 enumerate

使用 NSArray 时一个很常遇见的的需求是在枚举数组内元素的同时也想使用对应的下标索引,在 Objective-C 中最方便的方式是使用 NSArray 的 enumerateObjectsUsingBlock: 方法。因为通过这个方法可以显式地同时得到元素和下标索引,这会有最好的可读性,并且 block 也意味着可以方便地在不同的类之间传递和复用这些代码。 比如我们想要对某个数组内的前...
- 阅读全文 -
612 0

性能考虑

在 WWDC 14 的 Keynote 上,Swift 相比于其他语言的速度优势被特别进行了强调。但是这种速度优势是有条件的,虽然由于编译器的进步我们可能可以在不了解语言特性的时候随便写也能得到性能上的改善,但是如果能够稍微理解背后的机制的话,我们就能投 “编译器所好”,写出更高效的代码。 相比于 Objective-C,Swift 最大的改变就在于方法调用上的优化。在 Objective-...
- 阅读全文 -