Skip to content

Latest commit

 

History

History
67 lines (46 loc) · 2.72 KB

8.6 defer语法可以让代码更简洁 Clearing Up Using defer.md

File metadata and controls

67 lines (46 loc) · 2.72 KB

错误处理 Error Handling

8.6 defer语法可以让代码更简洁 Clearing Up Using defer

本小节内容比较简单,主要延续之前的文件的有效性查询的Demo来引出defer语法,并介绍一些相关特性

引出defer关键字: 一般在可能抛出异常的方法都会使用 try/finally结构。无论最后是否有抛出异常都会走finally流程。 这个时候我们就可以使用defer语法让代码变得更灵活

defer关键字的作用:实际是一个闭包,在当前声明的作用域结束时执行

defer在文件读写中的使用.

func contents(ofFile ?lename: String) throws -> String {
	 let file = open("test.txt", O_RDONLY)
	 defer { close(file) }
	 let contents = try process(file: file) 
	 return contents 
}
注1:在上面的demo中,如果不用defer关键字 当出现异常,直接就try 提前结束了. 导致当前的文件流没有执行close方法。这个在以后的数据库操作中可算是一个重大bug
注2: defer要写在reture 前面。 虽然它的执行上在return后。 你写在return后面,代码编译 return后的代码看都不看。这个时候你写defer实际上没啥用。

标准库中对defer的使用

下面会写出Enumeratedlterator协议中next()方法的代码实现。

使用场景:增加计数器的值而且需要返回没有增加值之前的值。
	struct EnumeratedIterator<Base: IteratorProtocol>: IteratorProtocol, Sequence { 
		internal var _base: Base 
		internal var _count: Int ...
		func next() -> Element? { 
			guard let b = _base.next() else { return nil } 
			defer { _count += 1 } 
			return (offset: _count, element: b) 
		} 
	}

这里引申一道关于defer很有趣的Swift面试题, 是Objc.io 里面很有名的一道题。

var counter = 5

func increment() -> Int {
    defer { counter += 1 }
    return counter
}

counter = increment()

// What's the value of counter?

可能大部分童鞋都能把答案猜对,但其中具体的原因可能还真不是你想的那样哈哈~ 具体的思路见网页: https://www.objc.io/quiz/19/

多defer方法多使用注意

写一个操作数据库的Demo来讲讲
	guard let database = openDatabase(...) else { return } 
	defer { closeDatabase(database) } 
	guard let connection = openConnection(database) else { return } 
	defer { closeConnection(connection) } 
	guard let result = runQuery(connection, ...) else { return }

类似于压栈操作,前面的后执行,后面的先执行。

上面的demo中的顺序也是在执行完数据库查询之后先```关闭链接```,再去```关闭数据库```。

over~