美文网首页
Swift 3.0基础语法

Swift 3.0基础语法

作者: CoderShmily | 来源:发表于2015-09-28 16:56 被阅读374次

    Swift笔记

    Any AnyObject NSObject

    Int Double String struct都是结构体

    1. Any : 一个协议声明
    2. AnyObject : 一个具体的协议,协议里面没有内容,默认情况下,所有的类,都遵循了这个协议
    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条件成立,继续往下走,不成立执行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与基本数据

    // 必须要加default, 但是有些情况可以不加,例如枚举的各个情况都判断过了
    // 判断类型 可以是浮点型,String,对象。
    let a = 11
    
    switch a {
    case 1, 11:
        print("1, 11")
        fallthrough // 会有穿透效果,如果这个case为true,也执行下个case的内容
    case 2:
        print("2")
    default:
        print("不知道")
    }
    

    2. switch与区间

    let score = 10.0
    switch score {
    case 0 ..< 60:
        print("不及格")
    case 60 ..< 90:
        print("及格")
    case 90 ..< 100:
        print("优秀")
    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也不会执行
    //    print("ss")
    }
    

    4. switch与元组

    let point = (10, 25)
    switch point {
    case (0, 0):
        print("坐标在原点")
    case (1...10, 10...20): // 可以在元组中再加上区间
        print("坐标的X和Y在1~10之间")
    case (_, 0): // X可以是任意数
        print("坐标的X在X轴上")
    case (var x, var y): // x,y来接收参数 一定为true
        print("333")
    case var(x,y): where x > y // x,y来接收参数 x>y则一定为true
        print("1111")
    default:
        print("Other")
    }
    

    循环

    1. for循环

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

    2. while循环

    1. while循环

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

    2. repeat~while循环

    // 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)
    

    数组

    // 数组的声明和初始化
    let arr1 = [2]
    var arr2 : [Any] = [1, 2, "ii", 11, "ss", "w"]
    let arr3 = [1, 1.1, "ss"] as [Any]
    
    // 相同类型的数组可以直接相加
    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)
    
    // 操作数组的区间
    let rang2 = 0 ..< 2
    arr2.removeSubrange(0 ..< 2)
    
    // 获取数组最大最小
    var arr = [1, 2]
    arr.min()
    arr.max()
    var arr4 = ["a", "3.3"]
    // 比的ASCII码
    arr4.min()
    arr4.max()
    
    // 数组的遍历
    for i in 0 ..< arr2.count {
        print(arr2[i])
    }
    
    // 利用元组获取数组的 角标+ 值
    for (key ,value) in arr2.enumerated() {
        print(key, value)
    }
    
    for i in arr2[0...2] {
        print(i)
    }
    
    // 转为OC数组的遍历
    (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? 代表,系统尝试帮你进行转换,转失败了,就为nil
    

    函数

    1. 函数的四种类型

    1. 无参数,无返回值

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

    2. 无参数,有返回值

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

    3. 有参数,无返回值

    func func1(age : Int) {
        
    }
    
    

    4. 有参数,有返回值

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

    函数其他注意

    1. 省略第一个外部参数的名字

    // 省略第一个内部参数(函数内部可以使用的参数)
    // 从swift3.0开始默认第一个参数既是外部参数(函数调用时可以看到的参数)也是内部参数
    func func2(_ name : Int, name2 : Int) -> Int {
        return 0
    }
    

    2. 设置参数默认值

    // 设置默认值,会生成几种组合(带不带第二个参数的)
    func func2(name : Int, name2 : Int = 1) -> Int {
        return 0
    }
    

    3. 设置可变参数

     // 可变参数  类型...
     // 函数内部,把这个参数,当做数组来处理
     // 函数外部,直接可以传递多个值,用逗号隔开
    func addNum(nums : Int...) -> Int {
        var result = 0
        for num in nums {
            result += num
        }
        return result
    }
    addNum(nums: 1, 2, 3)
    

    4. 修改内部参数的值

    // 默认不能修改内部参数的值
    func change(num : Int) {
        // num 为常亮,不能修改
        var num = num
        num = 3
    }
    let a = 0
    change(num: a)
    

    5. 设置参数为地址传递

     // inout设置第一个参数为地址传递
    func func1(name : inout Int, name2 : Int) -> Int {
        return 0
    }
    
    

    6. 函数嵌套

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

    7. 函数的类型

    // (Int, Int) -> Int
    // 函数的类型 : 参数类型 和返回值类型
    func add(num : Int, num2 : Int)  -> Int{
        return num + num2
    }
    
    // (Int, Int) -> Int
    // 函数的类型 : 参数类型 和返回值类型
    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. 区分不同函数

    func test() {   
    }
    // 参数返回值不同
    func test() -> Int {
        return 0
    }
    // 参数类型不同
    func test(age : Int) -> Int {
        return 0
    }
    // 参数名字不同
    func test(_ age : Int) -> Int {
        return 0
    }
    // 参数名字不同
    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. 结构体扩充构造函数

    struct Point {
        // 实例属性
        var x : Double
        var y : Double
        var z : Double?
        
        // 自定义 “构造函数” != 普通函数
        // 不加func,必须使用init作为名称
        // 在构造函数内部,必须要保证,所有的非可选属性,必须有值
        // 如果我们自定义了构造函数,那么系统生成的逐一构造器,就没有了
        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
    // 可以写属性和方法
    // 属性:实例属性,类型属性
    // 方法:实例方法,类型方法
    // 类,默认情况下,不会生成逐一构造器(目的,保证所有的非可选属性有值)
    // 默认情况下,不能保证,所有的非可选属性有值
    // 一个实例对象被创建好以后,必须保证里面所有的非可选属性有值
    // 方案1:在构造函数中入手,给非可选属性初始化
    // 方案2:把非可选 -> 可选
    // 方案3:给非可选的属性赋值默认值
    
    class Person {
        var age : Int
        init(age : Int) {
        // 为了不与age参数冲突才使用self
            self.age = age
        }
        init() {
            age = 2
        }
    }
    // 不会生成逐一构造器
    let p = Person()
    let p2 = Person(age: 3)
    

    2. 类的属性和方法

    class Person {
        // 实例属性 - 存储属性(可以用来存储数值的属性)
        var score = 1
        var score2 : Int = 0  {
            willSet {
                score2 // old
                newValue // new
            }
            
            //        willSet(changeName) {
            //            score2 // old
            //            changeName // new
            //        }
            didSet {
                score2 // new
                oldValue // old
            }
        }
        // 实例属性 - 计算属性(并不是直接用来存储数值的,它是通过某些计算得来的数值)
        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析构函数
        // 析构函数只能被定义在class类中,不能在extension中
        deinit {
            print("类死了")
        }
    }
    

    3. 类的继承之KVC使用

    class Person : NSObject {
    
        var age : Int = 0
        var name : String = ""
    
        init(dic : [String : Any]) {
            
            // KVC实现之前,必须调用父类的init方法初始化
            super.init()
            setValuesForKeys(dic)
        }
    }
    
    let dic : [String : Any] = ["name" : "zhangsan", "age" : 33]
    let stu = Person(dic: dic)
    

    4. 类的循环引用

    class Person {
        var dog : Dog?
        deinit {
            print("人挂了")
        }
    }
    class Dog {
        // 使用weak来避免循环引用 (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. 结构体和类的区别

    1. 结构体有逐一构造器,类没有
    2. 结构体是值类型,类是引用类型
    3. 结构体不能继承(意味着没有多态)

    6. OC中使用Swift的类和结构体

    1. OC与Swift混编,Swift中的函数名要符合OC的规范,重载的方法用@objc指定名字,避免冲突
    2. 如果是类,必须要继承自NSObject,而且用public关键字对类、方法、属性等进行修饰
    3. 如果是协议最好继承自NSObjectProtocol(也就对应OC中的基协议),用标识符@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项目创建OC文件时回生成.h桥接文件,可以在Build SettingsObjective-C Bridging Header中找到,也可以自己创建.h文件,路径跟系统生成的一致
    2. 在.h文件包含对应的OC头文件

    三大特性

    类的三大特性:封装、继承、多态

     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,就代表链条中间至少有一个环节断了
    // () == Void != nil
    p.dog?.toy?.price
    

    协议

    1.协议的基本使用

    protocol work {
        func run()
    }
    // 枚举也可以遵循协议
    enum Direction : work {
        case left
        case right
        
        // 实例方法
        func run() {
            print("Direction run")
        }
    }
    Direction.left.run()
    
    // 协议可以继承,这里不叫遵循,遵循work协议是要实现函数的
    protocol work2 : NSObjectProtocol{
        func run2()
    }
    // 如果遵循了协议,要求,必须实现协议里的所有方法
    // 同时继承 + 遵循协议,不支持多继承
    // NSObject 实现了NSObjectProtocol协议的所有方法
    class Stu : NSObject, work2 {
        func run2() {
            print("Stu run2")
        }
    }
    
    

    2. 协议中使用代理

    1. weak 修饰类,work : class,轻量级
    2. work : NSObjectProtocol也可以,但是遵循work协议的类,都要继承要NSObject
    protocol work : NSObjectProtocol{
        func run()
    }
    //protocol work : class{
    //    func run()
    //}
    
    class Stu {
        weak var delegate : work?
        func run() {
            print("Stu run2")
        }
    }
    

    3. 协议中的可选

    协议中的可选,仅仅是OC的特性,Swift是不支持的
    解决方案:就是让Swift协议,拥有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)
    
    // 参数必须继承自 Person
    exchange2(num1: &p1, num2: &p2)
    

    闭包

    闭包 == 特殊的函数

    1.闭包的基本使用

    // 函数
    func add(num1 : Int, num2 : Int) -> Int {
        return num1 + num2
    }
    
    // 简单的闭包
    // 如果闭包,参数是没有的,可以省略,in和in前面的内容
    var bibao : ()->() = {
        //    ()->() in // 可以省略
    }
    // 带参数的闭包
    var bibao2 : (Int, Int)->(Int) = {
    //    (varg1, varg2) in
        (varg1 : Int, varg2 : Int) in
        return varg1 + varg2
    }
    
    bibao2(10, 20)
    
    // 闭包当做参数
    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. 尾随闭包和逃逸闭包

    //尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。在使用尾随闭包时,你不用写出它的参数标签(此处是bb)
    // 如果一个函数的参数,是一个闭包类型,那么默认情况下,是一个“非逃逸”闭包;(闭包,生命周期,是函数)
    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. 闭包的循环引用(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
    

    懒加载

    只是在第一次访问的时候,会调用相应的函数,获取实例,下次即使值为nil,也不会再次调用相应的函数,获取新的实例

    class Dog {
        var name : String = "wangcai"
        init() {
            print("创建了小狗")
        }
    }
    
    // 懒加载
    // 函数:构造函数,一般的函数,闭包
    // = 后面可以跟的值:具体的指,构造“函数”
    // 所谓的懒加载,是指,在用的时候,再通过后面的函数,获取相应的实例
    class Person {
        lazy var dog : Dog = Dog()
        // 这样的懒加载可以对创建的对象进行修改
        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 {
            // 在这里面,抛出,出现问题的原因
            // 如果想要成为,异常值,必须要遵循一个协议Error
            throw FileError.notExists
    //        return
        }
        
        // 2. 读取文件内容
        // 判定,如果这个构造函数,出现了异常,一般都是格式不正确
        var content : String = ""
        do {
            content = try String(contentsOfFile: path)
        } catch  {
            // 捕捉到异常,会执行这个闭包
            throw FileError.notFormat
        }
        if content.lengthOfBytes(using: String.Encoding.utf8) == 0 {
            throw FileError.notContent
        }
        return content
    }
    

    Playground

    1. Playground异步执行

    // Playground中的代码会从上到下执行,并在执行完毕之后立即停止,如果想要测试异步处理(比如网络请求)
    // 1. 导入PlaygroundSupport
    // import PlaygroundSupport
    // 2. 让Playground永远执行
    //PlaygroundPage.current.needsIndefiniteExecution = true
    // 3. 停止执行
    // 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使用

    点击右上角双环(Show the Assistant editor),在代码中做的动画可以在TimeLine中预览

    4. Playground的Sources目录

    1. 放到Sources目录下的源文件会被编译成模块(module)并自动导入到Playground中,只会编译一次
    2. 使用注意:需要使用public关键字修饰资源文建中,需要暴露给外界的内容

    相关文章

      网友评论

          本文标题:Swift 3.0基础语法

          本文链接:https://www.haomeiwen.com/subject/wrvwcttx.html