Swift命令行工具
終端上可以使用Swift的REPL(Real-Eval-Print Loog)環(huán)境,輸入一句語(yǔ)句就立即執(zhí)行和輸出。
xcrun swift
可以啟動(dòng)它:
// Terminal
xcrun swift
然后就可以愉快地做一點(diǎn)小嘗試昌罩,直接寫swift代碼,它會(huì)編譯再運(yùn)行:
print("hello")
// hello
swiftc
可以脫離Xcode直接編譯Swift文件灾馒,生成可執(zhí)行文件茎用,比如有兩個(gè)Swift文件:
// MyClass.swift
class MyClass {
let name = "XiaoMing"
func hello() {
print("Hello \(name)")
}
}
// main.swift
let object = MyClass()
object.hello()
這時(shí)可以編譯它們:
swiftc MyClass.swift main.swift
將在當(dāng)前目錄下生成一個(gè)叫main的可執(zhí)行文件。
以后就可以用這個(gè)方法寫一些命令行程序了~
print 和 debugPrint
通過(guò)遵守CustomStringConvertible
協(xié)議睬罗,可以改變print的輸出轨功。
debugPrint對(duì)應(yīng)的是CustomDebugStringConvertible
。
錯(cuò)誤和異常處理
錯(cuò)誤(error)和異常(exception)是有區(qū)別的容达。
在預(yù)想之外古涧,不應(yīng)該發(fā)生的叫異常,比如程序員寫錯(cuò)了代碼花盐。它應(yīng)該在開(kāi)發(fā)階段就被解決羡滑。
而在預(yù)想之內(nèi),合理存在的可能問(wèn)題算芯,叫錯(cuò)誤柒昏。它是開(kāi)發(fā)階段不能保證的。比如網(wǎng)絡(luò)請(qǐng)求出錯(cuò)熙揍、寫文件失敗职祷。
如果一個(gè)方法可能發(fā)生錯(cuò)誤,則可以在其聲明時(shí)添加throws
關(guān)鍵字,然后在實(shí)現(xiàn)時(shí)發(fā)生錯(cuò)誤后拋出錯(cuò)誤對(duì)象堪旧,如NSData
的write
方法:
func write(toFile path: String, options writeOptionsMask: NSData.WritingOptions = []) throws
在調(diào)用帶有throws的方法時(shí)削葱,需要加try
關(guān)鍵字,然后放在do
塊里淳梦,并catch
"異常":
let data = NSData()
do {
try data.write(toFile: "Hello", options: [])
} catch let error {
print(error.localizedDescription)
}
如果不想理會(huì)錯(cuò)誤信息析砸,也可以不寫do-catch
,而使用下面2個(gè)辦法:
-
try!
表示強(qiáng)制執(zhí)行爆袍,代表了你確定知道這次調(diào)用不會(huì)拋出異常首繁,如果一旦出現(xiàn)異常,程序?qū)?huì)崩潰陨囊。 -
try?
會(huì)返回一個(gè)Optional值弦疮,如果成功,它會(huì)包含這條語(yǔ)句的返回值蜘醋,否則它是nil胁塞。
對(duì)于同步執(zhí)行的代碼,使用拋異常的方式?jīng)]什么問(wèn)題压语。但是對(duì)于異步API啸罢,拋出異常是不可用的。這時(shí)可以使用泛型枚舉胎食,封裝成錯(cuò)誤對(duì)象來(lái)返回:
enum Result<T> {
case success(T)
case failure(Error)
}
斷言
Swift提供了assert
方法出使用斷言扰才,比如:
assert(false, "斷言失敗")
assertionFailure("直接引發(fā)運(yùn)行時(shí)錯(cuò)誤")
默認(rèn)情況下,斷言只在Debug編譯的時(shí)候有效厕怜,在Release是不會(huì)執(zhí)行的衩匣,所以它不會(huì)消耗程序發(fā)布后的運(yùn)行時(shí)性能。
當(dāng)然你也可以強(qiáng)制指定斷言的啟動(dòng)或禁用粥航,無(wú)視當(dāng)前是Debug還是Release:
// Build Settings
// Swift Compiler - Custom Flags
// Other Siwft Falgs
// 強(qiáng)制啟動(dòng)
-assert-config Debug
// 強(qiáng)制禁用
-assert-config Release
斷言失敗可以令程序崩潰退出琅捏,但如果你真的想讓它退出,應(yīng)該選擇fatalError
递雀。
fatalError
對(duì)于我們不希望別人隨意調(diào)用柄延,但是又不得不去實(shí)現(xiàn)的方法,應(yīng)該使用fatalError
來(lái)避免可能的誤會(huì)映之。比如
required init(coder: NSCoder) {
fatalError("NSCoding not supported")
}
以及一些抽象用的父類方法,也可以使用fatalError
蜡坊,要求子類必須實(shí)現(xiàn)杠输,而不得直接調(diào)用父類方法。
log輸出
編譯器內(nèi)置了幾個(gè)符號(hào)秕衙,可以直接輸出一些信息:
// 文件
print(#file)
// 當(dāng)前行
print(#line)
// 當(dāng)前列
print(#column)
// 當(dāng)前方法名
print(#function)
泛型擴(kuò)展
對(duì)一個(gè)類聲明泛型之后蠢甲,其泛型標(biāo)記可以直接作用到擴(kuò)展中:
class MyClsaa<XX> {
}
extension MyClsaa {
func printXX(_ x: XX) {
print("\(x)")
}
}
泛型標(biāo)記XX
在擴(kuò)展中被直接使用了。
擴(kuò)展不能再定義作用于整個(gè)類的泛型据忘,但是可以定義某個(gè)方法使用的泛型:
extension MyClsaa {
func echo<T>(_ obj: T) {
print("echo:\(obj)")
}
}
測(cè)試:
let cls = MyClsaa<String>()
cls.printXX("hello")
cls.echo(333)
// hello
// echo:333