Swift语言编程技巧集

如何在函数内部修改非 inout 参数

如果需要实现已被废弃的 var 参数的功能(在函数内部修改参数值,函数外部不可见),可以采用声明变量覆盖同名参数的办法

func f(i: Int) {
//  i += 1 // ERROR
    var i = i
    i += 1
}
let x = 3
f(x)
// x == 3
试比较:
func f(i: inout Int) {
    i += 1
}
var x = 3
f(&x)
// x == 4

注意无参数闭包的写法

无参数的闭包在形式上可以和代码块相同,需要根据上下文加以区分。

let a = 3
let f1 = { () -> Bool in return a % 2 == 0 } // 闭包
let f2 = { () -> Bool in a % 2 == 0 } // 闭包
let f3 = { () in return a % 2 == 0 } // 闭包
let f4 = { () in a % 2 == 0 } // 闭包
let f5 = { return a % 2 == 0 } // 闭包(形式上和代码块相同)
let f6 = { a % 2 == 0 } // 闭包(形式上和代码块相同)
func f7() -> Bool { // 函数
    return a % 2 == 0
}
let b = f1() || f2() || f3() || f4() || f5() || f6() || f7()
// b == false

如何实现 Mixin 功能(行为继承)

Introducing Protocol-Oriented Programming in Swift 2

  1. 将 Mixin 实现为协议。
  2. 通过协议扩展来为 Mixin 提供缺省实现。
  3. 采纳该协议以完成 Mixin 功能。
protocol SampleMixin {
    var sampleProperty: Int { get }
    func sampleMethod()
}
extension SampleMixin {
    var sampleProperty: Int { return 42 }
    func sampleMethod() {
        print("default implementation")
    }
}
class SampleClass : SampleMixin {}
let c = SampleClass()
c.sampleMethod() // default implementation
print(c.sampleProperty) // 42

?. 与 ??

// n的值为a,b,c,4当中第一个不是nil的数
let n = a ?? b ?? c ?? 4
abcn
1//1
nil2/2
nilnil33
nilnilnil4
// n的值为a.b.c,条件是a,a.b,a.b.c都不是nil。否则n的值为4。
let n = a?.b?.c ?? 4
aa.ba.b.cn
nil//4  
!= nilnil/4
!= nil!= nilnil4
!= nil!= nil33

if case语句

模式匹配并不仅仅局限于switch语句,在if,guard以及for语句中也能进行模式匹配。
Swift 2: Pattern Matching with “if case”
Pattern Matching, Part 4: if case, guard case, for case

// if case语句实现模式匹配
enum Media {
  case book(title: String, author: String, year: Int)
  case movie(title: String, director: String, year: Int)
  case webSite(urlString: String)
}
let m = Media.movie(title: "Captain America: Civil War", director: "Russo Brothers", year: 2016)
if case let Media.movie(title, _, _) = m {
  print("This is a movie named \(title)")
}
// 相当于
switch m {
  case let Media.movie(title, _, _):
    print("This is a movie named \(title)")
  default: break
}
// if case语句实现模式匹配
if case 1...255 = x {}
// 相当于
if 1 <= x && x <= 255 {}

模式匹配运算符 ~=

// pattern ~= value
if 1...255 ~= x && 1...255 ~= y {}
// 相当于
if 1 <= x && x <= 255 && 1 <= y && y <= 255 {}

在if guard 语句中使用逗号

在if guard 语句中逗号相当于与运算
if case 1...255 = x, case 1...255 = y {}
if 1...255 ~= x, 1...255 ~= y {}
// 相当于
if 1...255 ~= x && 1...255 ~= y {}

不带 catch 的 do 语句

需要新开一个作用域时,不能像其他C系列语言那样直接写大括号,不然会出现如下错误:
statement cannot begin with a closure expression(语句不能以闭包表达式开头)
正确方法是使用不带 catch 的 do 语句。

defer语句

defer语句在当前作用域即将结束时执行指定的代码块,相当于其他语言的try...finally。
如果某个作用域内存在多个defer语句时,该作用域即将结束时排在后面的defer语句所指定的代码块先执行,排在前面的defer语句所指定的代码块后执行。
The defer keyword in Swift 2: try/finally done right

// do语句 + defer语句
print("Step 1")
do {
    defer { print("Step 2") }
    defer { print("Step 3") }
    print("Step 4")
    print("Step 5")
}
print("Step 6")
/*
Step 1
Step 4
Step 5
Step 3
Step 2
Step 6
*/

private(set)

使用 public private(set) 创建 public 只读 private 可写的变量。
Public Read-only Variables

// private(set)
public class Person {
    public private(set) var name: String
    // ...
}

用模式匹配声明并交换两个变量的值

// 声明并交换两个变量的值
var (a, b) = (1, 2) // a == 1, b == 2
(a, b) = (b, a) // a == 2, b == 1
// 相当于
var a = 1, b = 2
let temp = a; a = b; b = temp

用元组比较多个值

// 比较两对值
if (a1, b1) == (a2, b2) {}
if (a1, b1) < (a2, b2) {}
// 相当于
if a1 == a2 && b1 == b2 {}
if a1 < a2 || a1 == a2 && b1 < b2 {}
// 比较三对值
if (a1, b1, c1) == (a2, b2, c2) {}
if (a1, b1, c1) < (a2, b2, c2) {}
// 相当于
if a1 == a2 && b1 == b2 && c1 == c2 {}
if a1 < a2 || a1 == a2 && b1 < b2 || a1 == a2 && b1 == b2 && c1 < c2 {}

如何比较两个带相关值的枚举

使用元组+模式匹配或者字符串形式来比较两个带相关值的枚举。
How to test equality of Swift enums with associated values

// 比较两个带相关值的枚举
enum SimpleToken : Equatable {
    case name(String)
    case number(Int)
}
let t1 = SimpleToken.number(123) // the string representation is "number(123)"
let t2 = SimpleToken.number(123)
let t3 = SimpleToken.name("bob") // the string representation is "name(\"bob\")"
// 字符串形式
print(String(describing: t1) == String(describing: t2)) // true
print(String(describing: t1) == String(describing: t3)) // false
// 元组+模式匹配
func == (lhs: SimpleToken, rhs: SimpleToken) -> Bool {
    switch (lhs, rhs) {
    case let (.name(a), .name(b)): return a == b
    case (.name, _): return false
    case let (.number(a), .number(b)): return a == b
    case (.number, _): return false
    }
}
print(t1 == t2) // true
print(t1 == t3) // false

空语句

Swift 中最短的空语句不是分号而是一对小括号。

switch true {
default:
//  ; // error: ';' statements are not allowed
    ()
    do{}
    {}()
    break
}

究竟如何使用枚举

Advanced & Practical Enum usage in Swift

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值