Swift 3.0基礎語法

Swift筆記

Any AnyObject NSObject

Int Double String struct都是結構體

  1. Any : 一個協(xié)議聲明
  2. AnyObject : 一個具體的協(xié)議,協(xié)議里面沒有內容,默認情況下,所有的類,都遵循了這個協(xié)議
  3. NSObjectNSObject

條件判斷

swift中沒有非零即真和零為假的說法,只有嚴格的Bool(true/false)

1. if的使用

let a = 1
if a == 1 {
    print("test")
}else if  a == 2{
    print("sss")
}else {
    print("wwqw")
}

2. 三目運算符

a == 1 ? print("first") : print("hello")

3. guard

  1. guard條件成立,繼續(xù)往下走,不成立執(zhí)行else里面的語句
  2. else后要跳出語句,配合return,continue,break,throw等使用
func funcTest() {
    let a = 1
    guard a == 1 else {
        print("a != 1")
        return
    }
    print("a == 1")
    
}

4. switch的用法

1. switch與基本數(shù)據(jù)

// 必須要加default, 但是有些情況可以不加,例如枚舉的各個情況都判斷過了
// 判斷類型 可以是浮點型,String,對象。
let a = 11

switch a {
case 1, 11:
    print("1, 11")
    fallthrough // 會有穿透效果,如果這個case為true,也執(zhí)行下個case的內容
case 2:
    print("2")
default:
    print("不知道")
}

2. switch與區(qū)間

let score = 10.0
switch score {
case 0 ..< 60:
    print("不及格")
case 60 ..< 90:
    print("及格")
case 90 ..< 100:
    print("優(yōu)秀")
default:
    print("default")
}

3. switch與枚舉

enum Direction {
    case up
    case down
    case left
    case right
}

let rr = Direction.right
switch rr {
case Direction.up:
    print("up")
case Direction.down:
    print("down")
case Direction.left:
    print("right")
case Direction.right:
    print("right")
//default: // 此時可以省略default,因為各個情況都已經判斷過,default也不會執(zhí)行
//    print("ss")
}

4. switch與元組

let point = (10, 25)
switch point {
case (0, 0):
    print("坐標在原點")
case (1...10, 10...20): // 可以在元組中再加上區(qū)間
    print("坐標的X和Y在1~10之間")
case (_, 0): // X可以是任意數(shù)
    print("坐標的X在X軸上")
case (var x, var y): // x,y來接收參數(shù) 一定為true
    print("333")
case var(x,y): where x > y // x,y來接收參數(shù) x>y則一定為true
    print("1111")
default:
    print("Other")
}

循環(huán)

1. for循環(huán)

for i in 0 ..< 10 {
    print(i)
}

// _代表忽略的意思
for _ in 0 ..< 10 {
    print("test")
}

2. while循環(huán)

1. while循環(huán)

var i = 10
while i > 0 {
    i -= 1
    print(i)
}

2. repeat~while循環(huán)

// do 特殊含義,捕捉異常
repeat {
    i += 1
    print(i)
} while i < 10

字符串處理

let str2 = "123"
let int4 = 10

// 字符串拼接
str2 + "\(int4)"

// 遍歷字符串
for i in str2.characters {
    print(i)
}

str2.lengthOfBytes(using: String.Encoding.utf8)
str2.characters.count
String(format: "%02d", 1)

// 截取字符串
str2.substring(from: str2.startIndex)
str2.substring(to: str2.index(after: str2.startIndex))
str2.substring(from: str2.index(str2.startIndex, offsetBy: 2))
str2.substring(from: str2.index(str2.endIndex, offsetBy: -1))
let range = str2.startIndex ..< str2.endIndex
str2.substring(with: range)
str2.replaceSubrange(range, with: "sss")

// 轉為OC的NSString處理
let str3 = (str2 as NSString).substring(to: 2)

數(shù)組

// 數(shù)組的聲明和初始化
let arr1 = [2]
var arr2 : [Any] = [1, 2, "ii", 11, "ss", "w"]
let arr3 = [1, 1.1, "ss"] as [Any]

// 相同類型的數(shù)組可以直接相加
arr2 + arr3

// 獲取
arr2.first
arr2.last
arr2[0]
// 追加
arr2.append(2.0)
// 修改
arr2[0] = 1
// 插入
arr2.insert("sww", at: 2)
// 刪除
arr2.remove(at: 0)
arr2.removeFirst()
arr2.removeFirst(1)

// 操作數(shù)組的區(qū)間
let rang2 = 0 ..< 2
arr2.removeSubrange(0 ..< 2)

// 獲取數(shù)組最大最小
var arr = [1, 2]
arr.min()
arr.max()
var arr4 = ["a", "3.3"]
// 比的ASCII碼
arr4.min()
arr4.max()

// 數(shù)組的遍歷
for i in 0 ..< arr2.count {
    print(arr2[i])
}

// 利用元組獲取數(shù)組的 角標+ 值
for (key ,value) in arr2.enumerated() {
    print(key, value)
}

for i in arr2[0...2] {
    print(i)
}

// 轉為OC數(shù)組的遍歷
(arr2 as NSArray).enumerateObjects({ (value, idx, stop) in
    print(value, idx)
}) 

字典

var dict : [String : Any] = ["key" : 1, "key2" : "value"]
dict["key"] = 2

let index = dict.index(forKey: "key")
// index為nil報錯
dict.remove(at: index!)

// 有則改,無則加
dict.updateValue("value2", forKey: "key2")
dict.removeValue(forKey: "key2")
dict.removeAll()


for value in dict.values {
    print(value)
}

for (key ,value) in dict {
    print(key, value)
}

// 類擴展---字典的相+
extension Dictionary {
    static func +(dic : Dictionary, dic2 : Dictionary) -> Dictionary
    {
        var result = dic
        for (key , value) in dic2 {
            result[key] = value
        }
        return result
    }
}

元組

// 元組類型 (name: String, Int, score: Int), 可以作為返回值
let yz = (name : "zhangsan", _ : 18, score : 2)
yz.0
yz.name
yz.score

let(name, age, score) = ("zhangsan", 2, 2)

可選類型

1. 非可選類型 (使用的時候必須有值)

let sum : Int

2. 可選類型 (才能賦值為nil)

Swift中的nil != OC中的nil,Swift種的nil就是一個特殊含義的字符,表示沒有值

// let sum0 : Int?  
// let sum0 : Optional<Int> = 2

let sum1 : Int!
sum = nil

// sum0 (Int?)需要解包才能使用
// sum1 (Int!)賦值后可以直接使用,不用解包

3. 四種方式使用可選類型的值

1. 判斷 + 直接解包

if sum != nil {
    sum!
}

2. 可選綁定

if let tmp = sum {
    tmp
}

3. guard守護

func funcl(tmp : Int?) {
    guard let test = tmp else {
        return
    }
    test
}

4. 空合運算符

// 如果sum == nil,那么取 ?? 后面的值
// 如果 sum != nil, 取 sum! 強制解包后的值 
let tmp2 = sum ?? 0

類型轉換

var a = 8.8
a is Int
a is Double


let str = "123"
str as NSString
str as Any

// as! 代表,肯定可以轉換成功,轉換的結果,是非可選 不能為nil
// as? 代表,系統(tǒng)嘗試幫你進行轉換,轉失敗了,就為nil

函數(shù)

1. 函數(shù)的四種類型

1. 無參數(shù),無返回值

func func1() {
    
}
func func2() -> Void {
    
}
func func3() -> () {
    
}

2. 無參數(shù),有返回值

func func1() {
    
}
func func2() -> Int {
    return 0
    
}
// 返回元組
func func3() -> (Int, String) {
    return (1, "123")
}

3. 有參數(shù),無返回值

func func1(age : Int) {
    
}

4. 有參數(shù),有返回值

func func3(age : Int) -> (Int, String) {
    return (1, "123")
}

函數(shù)其他注意

1. 省略第一個外部參數(shù)的名字

// 省略第一個內部參數(shù)(函數(shù)內部可以使用的參數(shù))
// 從swift3.0開始默認第一個參數(shù)既是外部參數(shù)(函數(shù)調用時可以看到的參數(shù))也是內部參數(shù)
func func2(_ name : Int, name2 : Int) -> Int {
    return 0
}

2. 設置參數(shù)默認值

// 設置默認值,會生成幾種組合(帶不帶第二個參數(shù)的)
func func2(name : Int, name2 : Int = 1) -> Int {
    return 0
}

3. 設置可變參數(shù)

 // 可變參數(shù)  類型...
 // 函數(shù)內部,把這個參數(shù),當做數(shù)組來處理
 // 函數(shù)外部,直接可以傳遞多個值,用逗號隔開
func addNum(nums : Int...) -> Int {
    var result = 0
    for num in nums {
        result += num
    }
    return result
}
addNum(nums: 1, 2, 3)

4. 修改內部參數(shù)的值

// 默認不能修改內部參數(shù)的值
func change(num : Int) {
    // num 為常亮,不能修改
    var num = num
    num = 3
}
let a = 0
change(num: a)

5. 設置參數(shù)為地址傳遞

 // inout設置第一個參數(shù)為地址傳遞
func func1(name : inout Int, name2 : Int) -> Int {
    return 0
}

6. 函數(shù)嵌套

func test() {
    func test2() {
        print("sss")
    }
}

7. 函數(shù)的類型

// (Int, Int) -> Int
// 函數(shù)的類型 : 參數(shù)類型 和返回值類型
func add(num : Int, num2 : Int)  -> Int{
    return num + num2
}

// (Int, Int) -> Int
// 函數(shù)的類型 : 參數(shù)類型 和返回值類型
func jian(num : Int, num2 : Int)  -> Int{
    return num - num2
}


func exec(n1 : Int, n2 : Int, fun : (Int, Int) -> Int) {
    let result = fun(n1 ,n2)
    print(result)
}

exec(n1: 3, n2: 2, fun: add)
exec(n1: 3, n2: 2, fun: jian)

8. 區(qū)分不同函數(shù)

func test() {   
}
// 參數(shù)返回值不同
func test() -> Int {
    return 0
}
// 參數(shù)類型不同
func test(age : Int) -> Int {
    return 0
}
// 參數(shù)名字不同
func test(_ age : Int) -> Int {
    return 0
}
// 參數(shù)名字不同
func test(name : Int) -> Int {
    return 0
}

枚舉

// 在swift里面,枚舉類型,默認情況,不表示任何類型,就是一個標識
// 類型首字母大寫,元素小寫
enum Direction {
    case east
    case west
}

enum Direction2 {
    case east, west
}

enum Direction3 : Int {
    case east = 1
    case west = 3
    case north // Direction3.north.rawValue = 4 會自己累加
    case south
}

// 只有后邊指定類型才能敲出rawValue
// Direction4.left.rawValue 取出的值就是指定的類型
enum Direction4 : String {
    case left = "left"
    case right = "right"
    case top
    case down
    
    func func1() {
        print("wwwww")
    }

    static func func2() {
        print("rrrr")
    }
}

let rv = Direction3.north.rawValue
let rv2 = Direction3(rawValue: 1)
let rv3 = Direction4(rawValue: "left")

func test(path : Direction4) {
    if path == .left {
        print(path.rawValue)
    }
}

結構體

1. 結構體基本使用

// 類型方法 static func
// 實例方法 func
// 無論是枚舉,還是結構體,都可以寫方法
struct Point {
    // 實例屬性
    var x : Double
    var y : Double
    // 實例方法
    func distance() -> Double {
        return x - y
    }

    mutating func distance2() -> Double {
        x += 2  // 修改實例屬性 方法要加mutating
        print(Point.z) // 訪問類型屬性
        return x - y
    }
    
    // 類型屬性
    static var z : Double = 0 // 需要初始化
    // 類型方法
    static func dis() {
//        print(x) 不能直接訪問x
        print(z)
        print(Point.z)
    }
    
}

2. 結構體擴充構造函數(shù)

struct Point {
    // 實例屬性
    var x : Double
    var y : Double
    var z : Double?
    
    // 自定義 “構造函數(shù)” != 普通函數(shù)
    // 不加func,必須使用init作為名稱
    // 在構造函數(shù)內部,必須要保證,所有的非可選屬性,必須有值
    // 如果我們自定義了構造函數(shù),那么系統(tǒng)生成的逐一構造器,就沒有了
    init(x : Double, y : Double) {
        self.x = x
        self.y = y
    }
    init(x : Double, y : Double, z : Double) {
        self.x = x
        self.y = y
        self.z = z
    }
    
}

1. 類的聲明初始化

// swift類,是可以不繼承父類,那它本身就是rootClass
// 可以寫屬性和方法
// 屬性:實例屬性,類型屬性
// 方法:實例方法,類型方法
// 類,默認情況下,不會生成逐一構造器(目的,保證所有的非可選屬性有值)
// 默認情況下,不能保證,所有的非可選屬性有值
// 一個實例對象被創(chuàng)建好以后,必須保證里面所有的非可選屬性有值
// 方案1:在構造函數(shù)中入手,給非可選屬性初始化
// 方案2:把非可選 -> 可選
// 方案3:給非可選的屬性賦值默認值

class Person {
    var age : Int
    init(age : Int) {
    // 為了不與age參數(shù)沖突才使用self
        self.age = age
    }
    init() {
        age = 2
    }
}
// 不會生成逐一構造器
let p = Person()
let p2 = Person(age: 3)

2. 類的屬性和方法

class Person {
    // 實例屬性 - 存儲屬性(可以用來存儲數(shù)值的屬性)
    var score = 1
    var score2 : Int = 0  {
        willSet {
            score2 // old
            newValue // new
        }
        
        //        willSet(changeName) {
        //            score2 // old
        //            changeName // new
        //        }
        didSet {
            score2 // new
            oldValue // old
        }
    }
    // 實例屬性 - 計算屬性(并不是直接用來存儲數(shù)值的,它是通過某些計算得來的數(shù)值)
    var b : Int {
        get {
            return score + score2
        }
        set {
            newValue
        }
    }
    // 類型屬性
    static var c = 1
    static var d : Int?
    // 實例方法
    func func1() {
        self.score += 1
    }
    
    // 類型方法 - 不可以被子類重寫override
    static func func2() {
        print("rrrr", c)
    }
    // 類型方法 - 可以被子類重寫(結構體不能用class聲明方法)
    class func func3() {
        print("sss")
    }
    // 結構體不能使用deinit析構函數(shù)
    // 析構函數(shù)只能被定義在class類中,不能在extension中
    deinit {
        print("類死了")
    }
}

3. 類的繼承之KVC使用

class Person : NSObject {

    var age : Int = 0
    var name : String = ""

    init(dic : [String : Any]) {
        
        // KVC實現(xiàn)之前,必須調用父類的init方法初始化
        super.init()
        setValuesForKeys(dic)
    }
}

let dic : [String : Any] = ["name" : "zhangsan", "age" : 33]
let stu = Person(dic: dic)

4. 類的循環(huán)引用

class Person {
    var dog : Dog?
    deinit {
        print("人掛了")
    }
}
class Dog {
    // 使用weak來避免循環(huán)引用 (unowned也可以)
    weak var master : Person?
    deinit {
        print("??掛了")
    }
}

var p : Person? = Person()
var d : Dog? = Dog()
p?.dog = d
d?.master = p

p = nil
d = nil

5. 結構體和類的區(qū)別

  1. 結構體有逐一構造器,類沒有
  2. 結構體是值類型,類是引用類型
  3. 結構體不能繼承(意味著沒有多態(tài))

6. OC中使用Swift的類和結構體

  1. OC與Swift混編,Swift中的函數(shù)名要符合OC的規(guī)范,重載的方法用@objc指定名字,避免沖突
  2. 如果是類,必須要繼承自NSObject,而且用public關鍵字對類、方法、屬性等進行修飾
  3. 如果是協(xié)議最好繼承自NSObjectProtocol(也就對應OC中的基協(xié)議),用標識符@objc,而且聲明為public
  4. Build Settings搜索-Swift,找到 Objective-C Generated Interface Header Name 里面的.h文件即為OC調用時,要包含的頭文件 #import "XXX-Swift.h"
public class Person : NSObject {
    public var name : String = ""
    public func getAge() {
        print("hello age")
    }
}

@objc
public protocol work : NSObjectProtocol{
    func goWork()
}

7. Swift中調用OC

  1. Swift項目創(chuàng)建OC文件時回生成.h橋接文件,可以在Build SettingsObjective-C Bridging Header中找到,也可以自己創(chuàng)建.h文件,路徑跟系統(tǒng)生成的一致
  2. 在.h文件包含對應的OC頭文件

三大特性

類的三大特性:封裝、繼承、多態(tài)

 class Test : NSObject {
    // 類繼承NSObject后,下面兩個方法會報錯,說是轉換到OC以后兩個方法有沖突
    func chongzai(a : Int) {
    }
    
    func chongzai(a : Double) {  
    }
}

解決辦法:

public class Test : NSObject {
    public func chongzai(a : Int) {    
    }
    
    // 通過此標識,自定義生成的方法名,解決重復沖突
    @objc(chongzai:)
    public func chongzai(a : Double) {
        
    }
}
// 項目名稱為app,彈框選擇的是不橋接
// Build Settings搜索-Swift,找到 Objective-C Generated Interface Header Name 里面的.h文件即為要包含的頭文件
#import "app-Swift.h"
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    Test *t = [[Test alloc] init];
    [t chongzaiWithA:(NSInteger)];
}

可選鏈

class Person {
    var dog : Dog?
}

class Dog {
    var name : String = "wangcai"
    var toy : Toy?
}

class Toy {
    var price : Double = 0.0
}
let p = Person()
// 如果可選鏈的結果是nil,就代表鏈條中間至少有一個環(huán)節(jié)斷了
// () == Void != nil
p.dog?.toy?.price

協(xié)議

1.協(xié)議的基本使用

protocol work {
    func run()
}
// 枚舉也可以遵循協(xié)議
enum Direction : work {
    case left
    case right
    
    // 實例方法
    func run() {
        print("Direction run")
    }
}
Direction.left.run()

// 協(xié)議可以繼承,這里不叫遵循,遵循work協(xié)議是要實現(xiàn)函數(shù)的
protocol work2 : NSObjectProtocol{
    func run2()
}
// 如果遵循了協(xié)議,要求,必須實現(xiàn)協(xié)議里的所有方法
// 同時繼承 + 遵循協(xié)議,不支持多繼承
// NSObject 實現(xiàn)了NSObjectProtocol協(xié)議的所有方法
class Stu : NSObject, work2 {
    func run2() {
        print("Stu run2")
    }
}

2. 協(xié)議中使用代理

  1. weak 修飾類,work : class,輕量級
  2. work : NSObjectProtocol也可以,但是遵循work協(xié)議的類,都要繼承要NSObject
protocol work : NSObjectProtocol{
    func run()
}
//protocol work : class{
//    func run()
//}

class Stu {
    weak var delegate : work?
    func run() {
        print("Stu run2")
    }
}

3. 協(xié)議中的可選

協(xié)議中的可選,僅僅是OC的特性,Swift是不支持的
解決方案:就是讓Swift協(xié)議,擁有OC特性

@objc
protocol work {
  @objc optional  func run()
}

class Stu : work {
    func run() {
        print("Stu run2")
    }
}

泛型

// 泛化的類型,不是某一個具體的類型, <T>中的T可以自定義名字
func exchange<T>(num1 : inout T, num2 : inout T) {
    let tmp = num1
    num1 = num2
    num2 = tmp
}

class Person {  
}

// 限制 T 必須繼承自 Person
func exchange2<T>(num1 : inout T, num2 : inout T) -> Int  where T : Person  {
    let tmp = num1
    num1 = num2
    num2 = tmp
    return 0
}

var a = 3
var b = 9
var p1 = Person()
var p2 = Person()
exchange(num1: &a, num2: &b)

// 參數(shù)必須繼承自 Person
exchange2(num1: &p1, num2: &p2)

閉包

閉包 == 特殊的函數(shù)

1.閉包的基本使用

// 函數(shù)
func add(num1 : Int, num2 : Int) -> Int {
    return num1 + num2
}

// 簡單的閉包
// 如果閉包,參數(shù)是沒有的,可以省略,in和in前面的內容
var bibao : ()->() = {
    //    ()->() in // 可以省略
}
// 帶參數(shù)的閉包
var bibao2 : (Int, Int)->(Int) = {
//    (varg1, varg2) in
    (varg1 : Int, varg2 : Int) in
    return varg1 + varg2
}

bibao2(10, 20)

// 閉包當做參數(shù)
func exec(n1 : Int, n2 : Int, block : (Int, Int)->(Int)) -> Int {
    return block(n1, n2)
}
exec(n1: 20, n2: 30, block: add)
exec(n1: 20, n2: 30, block: bibao2)
exec(n1: 20, n2: 30, block: {
    (a : Int, b : Int)->(Int) in
    return a * b
})

2. 尾隨閉包和逃逸閉包

//尾隨閉包是一個書寫在函數(shù)括號之后的閉包表達式,函數(shù)支持將其作為最后一個參數(shù)調用。在使用尾隨閉包時,你不用寫出它的參數(shù)標簽(此處是bb)
// 如果一個函數(shù)的參數(shù),是一個閉包類型,那么默認情況下,是一個“非逃逸”閉包;(閉包,生命周期,是函數(shù))
func test(a : Int, bb : (Int, Int)->(Int)) {
    let result = bb(a, 3)
    print(result)
}

test(a: 20) { (sum1, sum2) -> (Int) in
    return sum1 - sum2
}

// @escaping : 代表,這個閉包,是逃逸閉包,以后,有可能,會被其他的閉包,延長生命周期(強引用)
func test2(bb : @escaping (Int, Int)->(Int)) {
    bb(23, 3)
    let queue = DispatchQueue(label: "xx")
    let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
    queue.asyncAfter(deadline: time) { 
        // 此處編譯器會提示添加 @escaping
        _ = bb(10, 3)
    }
}
test2 { (sum, sum2) -> (Int) in
    return sum * sum2
}

3. 閉包的循環(huán)引用(4中解決方式)

class Person {
class Person {
    var resultBlock : (()->())?
    var age : Int = 0
    func test() {
        // weak 對象最后會被置為 nil,所以var
        weak var weakSelf = self
        resultBlock = {
            print("222",weakSelf?.age)
        }
        resultBlock?()
    }
    func test2() {
        resultBlock = {
            [weak self] in
            print(self?.age)
        }
        resultBlock?()
    }
    
    func test3() {
        // unowned == __unsafe_unretained 最后不會置為nil,編譯器建議為let
        unowned let weakSelf = self
        resultBlock = {
            print(weakSelf.age)
        }
        resultBlock?()
    }

    
    func test4() {
        resultBlock = {
            [unowned self] in
            print(self.age)
        }
        resultBlock?()
    }
    deinit {
        print("人被釋放了")
    }
}
var p : Person? = Person()
p?.test()
p = nil

懶加載

只是在第一次訪問的時候,會調用相應的函數(shù),獲取實例,下次即使值為nil,也不會再次調用相應的函數(shù),獲取新的實例

class Dog {
    var name : String = "wangcai"
    init() {
        print("創(chuàng)建了小狗")
    }
}

// 懶加載
// 函數(shù):構造函數(shù),一般的函數(shù),閉包
// = 后面可以跟的值:具體的指,構造“函數(shù)”
// 所謂的懶加載,是指,在用的時候,再通過后面的函數(shù),獲取相應的實例
class Person {
    lazy var dog : Dog = Dog()
    // 這樣的懶加載可以對創(chuàng)建的對象進行修改
    lazy var dog2 : Dog = Person.getDog()
    // 懶加載內容放到閉包,最后調用閉包
    lazy var dog3 : Dog = {
        let d = Dog()
        d.name = "dog3"
        return d
    }()
    lazy var dog4 : Dog = {
        $0.name = "dog4"
        return $0
    }(Dog())
    
    
    static func getDog() -> Dog {
        let d = Dog()
        d.name = "getDog"
        return d
    }
}

注釋

// MARK: - ARC
// TODO: - todo
// FIXME: 解決bug

訪問權限

  1. Swift中的訪問控制模型基于模塊和源文件、類這三個概念
  2. Swift訪問權限,作用于類,屬性,方法等
  3. Swift中的訪問級別遵循一個基本原則:不可以在某個實體中定義訪問級別更高的實體(類如果都不能訪問,里面的屬性方法就算開放了也不能訪問)

訪問修飾符

  1. internal : 在本模塊中都可以訪問,(默認),子類也可以繼承
  2. private : 當前類私有
  3. fileprivate : 在當前源文件中可以訪問
  4. public : 跨模塊時,如果修飾類,則無法繼承。修飾方法,不能被override
  5. open : 跨模塊時,如果修飾類,可以繼承。修飾方法,可以被override

方法拋出異常

// Error 就是在告訴編譯器,這個枚舉,可以充當具體的異常值
enum FileError : Error{
    case notExists
    case notFormat
    case notContent
}

// path 不存在 nil
// path存在,但是,路徑對應的文件格式不對 .png
func readFile(path : String) throws -> String {
    // 1. 判斷文件路徑是否存在
    let isExists = FileManager.default.fileExists(atPath: path)
    if !isExists {
        // 在這里面,拋出,出現(xiàn)問題的原因
        // 如果想要成為,異常值,必須要遵循一個協(xié)議Error
        throw FileError.notExists
//        return
    }
    
    // 2. 讀取文件內容
    // 判定,如果這個構造函數(shù),出現(xiàn)了異常,一般都是格式不正確
    var content : String = ""
    do {
        content = try String(contentsOfFile: path)
    } catch  {
        // 捕捉到異常,會執(zhí)行這個閉包
        throw FileError.notFormat
    }
    if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
        throw FileError.notContent
    }
    return content
}

Playground

1. Playground異步執(zhí)行

// Playground中的代碼會從上到下執(zhí)行,并在執(zhí)行完畢之后立即停止,如果想要測試異步處理(比如網絡請求)
// 1. 導入PlaygroundSupport
// import PlaygroundSupport
// 2. 讓Playground永遠執(zhí)行
//PlaygroundPage.current.needsIndefiniteExecution = true
// 3. 停止執(zhí)行
// PlaygroundPage.current.finishExecution()

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "xx")
let time = DispatchTime.now() + DispatchTimeInterval.seconds(2)
queue.asyncAfter(deadline: time) {
    print("finish")
    PlaygroundPage.current.finishExecution()
}
print("first")

2. MarkDown語法

從Xcode右邊文件屬性,選中Render Documentation看渲染效果

//: [Previous](@previous) 
//: [Next](@next)

//PageName為頁名字不能有空格
//: [Go to AnyPage](PageName)

3. TimeLine使用

點擊右上角雙環(huán)(Show the Assistant editor),在代碼中做的動畫可以在TimeLine中預覽

4. Playground的Sources目錄

  1. 放到Sources目錄下的源文件會被編譯成模塊(module)并自動導入到Playground中,只會編譯一次
  2. 使用注意:需要使用public關鍵字修飾資源文建中,需要暴露給外界的內容
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,861評論 1 10
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應用程序 ...
    大L君閱讀 3,271評論 3 25
  • 136.泛型 泛型代碼讓你可以寫出靈活,可重用的函數(shù)和類型,它們可以使用任何類型,受你定義的需求的約束。你可以寫出...
    無灃閱讀 1,494評論 0 4
  • 擴展 擴展就是向一個已有的類、結構體、枚舉類型或者協(xié)議類型添加新功能。這包括在沒有權限獲取原始源代碼的情況下擴展類...
    cht005288閱讀 472評論 0 0
  • 常量與變量使用let來聲明常量,使用var來聲明變量。聲明的同時賦值的話,編譯器會自動推斷類型。值永遠不會被隱式轉...
    莫_名閱讀 461評論 0 1