zoukankan      html  css  js  c++  java
  • Swift备忘录

    Swift 备忘录 2015-4

    一、简介

    1、Swift 语言由苹果公司在2010年7月开始设计,在 2014 年6月推出,在 2015 年 12 月 3 日开源 

    2、特点(官方):

    (1)苹果宣称 Swift 的特点是:快速、现代、安全、互动,而且明显优于 Objective-C 语言

    (2)可以使用现有的 Cocoa 和 Cocoa Touch 框架

    (3)Swift 取消了 Objective-C 的指针及其他不安全访问的使用

    (4)舍弃 Objective-C 早期应用 Smalltalk 的语法,全面改为句点表示法

    (5)提供了类似 Java 的名字空间(namespace)、泛型(generic)、运算对象重载(operator overloading)

    (6)Swift 被简单的形容为 “没有 C 的 Objective-C”(Objective-C without the C)

    3、强语法规范以及一些注意点

    (1)空格的使用(对比OC)

    (2)数据类型的异常严格的要求

    (3)不用导入头文件,使用pod时例外

    二、常量变量

    1、 let :定义常量,一经赋值不允许再修改

           var: 定义变量,赋值之后仍然可以修改

    使用技巧:优先选择 let 定义常量/变量, Xcode7.0以后如果变量没有修改,会给出警告,提示使用let代替var

    2、未赋值的常量有一次赋值的机会,例:

    let x1: Int

    x1 = 30

    3、关于自动推导

    (1)swift 可以根据右边的类型准确推导出变量的类型,例如  var num  = “张三”  ,num就是一个字符串类型

    (2)开发中一般不用指定变量类型

    (3)如果要指定,跟在后面,例如  var num : String = “张三”

    4、option + 左键点击  的使用:查看变量的类型

    5、没有隐式转换,不同数据类型间的运算,必须统一数据类型(显式强转换),例:

    let x2 = 100

    let y2 = 10.5

    let num1 = Double(x2) + y2

    let num2 = x2 + Int(y2)

    Optional 可选类型

    1、定义:swift一大特色,表示一个变量的值可以是nil,也可以是一个指定的值。

    2、表示方式:在类型后面加? 例如: var num : Int ?

    3、被设置成可选类型的变量,默认值是nil

    4、被设置成可选类型的常量,没有默认值,其意义也不大,例:

    let url = NSURL(string: "http://www.baidu.com")

    let num: Int? = 10

    关于可选项的解包判断是否为nil

    1、不可参与运算&&可以打印:如果 Optional 值是 nil,不允许参与计算,只有解包(unwrap)后才能参与计算,但是解包前是可以打印的

    2、解包方式:

    (1)在变量后添加一个 !     可以强行解包

          注意:必须要确保解包后的值不是 nil,否则会报错 

    例(错误提示):unexpectedly found nil while unwrapping an Optional value

    (2)简单的 if 判断,但还是需要使用到强行解包

    if url != nil {

        let request = NSURLRequest(URL: url!)

    }

    (3)使用 if let 、guard let等特殊处理方式

    (4)可选链,使用一个 ?给对象进行 “弱” 解包,有值则正常返回,无值则返回nil

    (5)空合并运算符??

    3、避免强解包造成崩溃、不使用强制解包————> 详解

    (1)if  let 判断

    例:如果可选项num为空,则不执行if分支的代码,也就不会崩溃

    if let n = num {

        let r = n + 10

    }

    (2)where子句  

    语义:如果判断的条件不止一个,判断的条件具备从属关系,又要避免多层的(难看的)嵌套if,可以使用where 

    if let 不能与 &&、|| 等条件判断方式一同使用,如果要增加条件,可以使用 where 子句(where 子句没有智能提示)

    例:

    if let u = url where u.host == "www.baidu.com" {

        let request = NSURLRequest(URL: u)

    }

    (3) guard 判断,与 if  let 语义相反,Swift 2.0 推出 (在真正的逻辑代码部分,可以省掉一层嵌套)

    语义:如果变量为nil 则执行 分支中的代码 。  

    例:

    let oName: String? = "张三"

    let oNum: Int? = 18

    guard let name = oName else {

        return

    }

    guard let num = oNum else {

        return

    }

    // 代码如果能执行至此,name & num 都是一定不为nil的,此处也没有if let中的嵌套(少了一层),随便写~~

    print(name)

    print(num)

    (4)空合并运算符 ?? 

    语义:如果为nil,则使用??后面的值代替,简化了代码,例如:

    let num: Int? = nil

    let r1 = (num ?? 0) + 10

    print(r1)

    (5)多个可选类型判断(避免多个可选项为nil)

    方法:可以使用 “  ,” 同时判断多个可选类型是否为空

    let oName: String? = "张三"

    let oNo: Int? = 100

    if let name = oName, let no = oNo {

        print("姓名:" + name + " 学号: " + String(no))

    }

    (6)可选链 “  ?”的使用,对比 “  !” 

    语义:如当对象为可选类型时,对其属性的访问,要先解包,但如果使用!,有可能因为nil造成崩溃,这时可以使用?,如果对象存在,则解包调用,如果对象为nil则不进行后续操作。

    例:

            var p : person?

            let  name  = (p?.name) ?? ""

            print(name)

    控制流

    1、if 的注意点:

    (1)没有OC中非零及真的概念

    (2)明确显式的指出 true  或  false 进行逻辑判断

    (3)()可以省略,{}不可以省略

    2、三目运算符与OC相同

    3switch(变化很大)

    (1)switch 不再局限于整数, 可以针对任意数据类型进行判断

      示例:

    let score = "优"

    switch score {

    case "优":

        let name = "学生"

        print(name + "80~100分")

    case "良": print("70~80分")

    case "中": print("60~70分")

    case "差": print("不及格")

    default: break

    }

    (2)可以省略 break

    (3)每一个 case后面必须有可以执行的语句,不能什么都不写

    (4)要保证处理所有可能的情况,不然编译器直接报错,不处理的条件可以放在 default (不可省)分支中

    (5)每一个 case 中定义的变量仅在当前 case 中有效,而 OC 中需要使用 {},swift可以省略

    (6)同样有穿透,使用关键字 fallthrough,只穿透一层, 而且case语句中不能定义变量或常量

    (7)switch 中同样能够赋值和使用 where 子句

      示例:

    let point = CGPoint(x: 10, y: 10)

    switch point {

    case let p where p.x == 0 && p.y == 0:

        print("中心点")

    case let p where p.x == 0:

        print("Y轴")

    case let p where p.y == 0:

        print("X轴")

    case let p where abs(p.x) == abs(p.y):

        print("对角线")

    default:

        print("其他")

    }

    (8)如果只希望进行条件判断,赋值部分可以省略,使用 _  ,  表示“不关心”

    示例:

    switch score {

    case _ where score > 80: print("优")

    case _ where score > 60: print("及格")

    default: print("其他")

    }

    循环

    1、for 循环

    (1)仿OC写法 ,()可以省略

    var sum = 0

    for var i = 0; i < 10; i++ {

        sum += i

    }

    print(sum)

    (2)for - in  写法 

    语义  :在一个范围(或集合中)循环遍历出每个个体 ,例:

    • 范围 0..< 10 表示从0到9 , i 就是 0、1、2 ……9 的个体,一个循环10次,,对比0...10

    sum = 0

    for i in 0..<10 {

        sum += i

    }

    print(sum)

    • 遍历子控件集合,打印每一个子控件

         for myView in view.subviews {      

           print(myView)

            }

    (3)for - in 省略下标写法

    语义:忽略_ 对应位置的值

    for _ in 0...10 {

        print("hello")

    }

    2、do - while 循环

    (1)swift2.0以后把do-while 改成了repeat- while

    例:

          var index = 3

          repeat {

              index--

              print(index)

          } while index > 0

    3、while 循环,和OC一样,可以省略()

    字符串

    1、结构体类型 Sting

    (1)let 定义不可变字符串

    (2)var 定义可变字符串

    (3)定义空字符串:

    var a: String = String()

    2、与NSString比较:

    (1)String 是一个结构体,性能更高,具有了绝大多数 NSString 的功能

    (2)String 支持直接遍历

    (3)NSString 是一个 OC 对象,性能略差

    (4)Swift 提供了 String 和 NSString 之间的无缝转换

    3、遍历字符串(characters属性)

    示例:

    for s in str.characters {

        print(s)

    }

    4、字符串长度

    (1)返回以字节为单位的字符串长度,一个中文占 3 个字节,根据编码方式

    let len1 = str.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)

    (2) 返回实际字符的个数

    let len2 = str.characters.count

    (3) 返回 utf8 编码长度

    let len3 = str.utf8.count

    5字符串拼接

    (1)直接在 "" 中使用 (变量名) 的方式可以快速拼接字符串

    let str1 = "Hello"

    let str2 = "World"

    let i = 32

    str = "(i) 个 " + str1 + " " + str2

    (2)可选项的拼接,如果变量是可选项,拼接的结果中会有 Optional字符,使用空合并运算符

    let str1 = "Hello"

    let str2 = "World"

    let i: Int? = 32

    str = "(i ?? 0) 个 " + str1 + " " + str2

    (3)格式化字符串

            在实际开发中,如果需要指定字符串格式,可以使用 String(format:...) 的方式

    let h = 8

    let m = 23

    let s = 9

    let timeString = String(format: "%02d:%02d:%02d", arguments: [h, m, s])

    let timeStr = String(format: "%02d:%02d:%02d", h, m, s)

    6、截取字符串(复杂一些) 

    关键词 : startIndex、endIndex、startIndex.advancedBy、substringToIndex、substringWithRange

    例:

    首先定义常量 :  let str = "hello"

    (1)占位符  + substring  方式   

    //”hel"只是一个占位字符串,可以随便写,   startIndex 是光标的开始索引

            let startIndex = "hel".startIndex

            let endIndex = "hel".endIndex

            

    //从起点开始一直截取到末尾

            let result = str.substringFromIndex(startIndex)

    //截取到结束位数

            let result1 = str.substringToIndex(endIndex)

           

    (2) advancedBy + range  方式

            //advancedBy 如果传入的是正数则是往后加多少为

            let strStartIndex = str.startIndex.advancedBy(1)

            let strEndIndex = str.endIndex.advancedBy(-1)

            let result2 = str.substringWithRange(strStartIndex..<strEndIndex)

            

    (3)转成OC + range 方式

            let result3 = (str as NSString).substringWithRange(NSMakeRange(1, str.characters.count-2))

    let.result4=(str as NSString).substringWithRange(NSMakeRange(2, 3))

    数组

    1、定义、获取元素与OC相同

    例:

    let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    let num1 = numbers[0]

    2、let 、var 区分可变和不可变数组

    3、遍历使用 for - in ,例:

    for num in numbers {

        print(num)

    }

    4、追加元素、删除元素

    array1.append(“张三”)

    array1.removeAtIndex(3)

    array1.removeAll()

    5、数组的定义和实例化

    (1)使用  :   可以只定义数组的类型 , 例:

    var array: [String]

    (2)实例化之前不允许添加值

    (3)使用 [类型]() 可以实例化一个空的数组 ,例:

    array = [String]()

    array.append(“老王”)

    6、数组的类型

    (1)如果初始化时,所有内容类型一致,则数组中保存的是该类型的内容,后续添加的元素必须类型一致

    (2)如果初始化时,所有内容类型不一致,则数组中保存的是 NSObject

    (3)swift 中 数字可以直接加入集合中,不用包成NSNumber

    (4)swift 中 将结构体添加到集合中,还是需要包成NSValue,例:

    array.append(NSValue(CGPoint: CGPoint(x: 10, y: 10)))

    7、数组的合并

    (1)必须是相同类型的数组才能够合并

    (2)开发中,通常数组中保存的对象类型都是一样的!

    8、内存分配

    (1)如果向数组中追加元素,超过了容量,会直接在现有容量基础上 * 2,例:

    var list = [Int]()

    for i in 0...16 {

        list.append(i)

        print("添加 (i) 容量 (list.capacity)")

    }

    一个奇怪的现象:添加第一个元素时,数组容量为 2

    (2)数组移除元素后,保持容量

    字典

    1、定义字典

    (1)使用 [ ]   : var dict = ["name": "zhangsan", "age": 18]

    (2)var dict : [String : NSObject] = [String : NSObject]( )

    dict[key] = value

    2、最常用的类型  

    (1)[String : NSObject] 

    (2)AnyObject 的范围要比NSObject大

    3、赋值

    (1)赋值直接使用 dict[key] = value 格式

    (2)如果 key 不存在,会设置新值

    (3)如果 key 存在,会覆盖现有值

    4、遍历

    (1)使用(key,value)+  for-in 的方式,key,value可以随便写

    (2)前面的是 key,后面的是 value

        例:

    for (k, v) in dict {

        print("(k) ~~~ (v)")

    }

    5、增删改,例:

    (1)增、改:如果key不存在,则进行添加,如果key存在,则进行修改

      var dic1 = ["name": “老王”,”age": 18]     

    dic1["sex"] = "男"

        dic1["name"] = “老李”

    (2)删

            dic1["age"] = nil

            dic1.removeValueForKey("name")

            

    (3)改

            dic1.updateValue(28, forKey: "age")

            

    6、合并字典

    (1)如果 key 不存在,会建立新值,否则会覆盖现有值

    var dict1 = [String: NSObject]()

    dict1[“nickname"] = "大老虎"

    dict[“age"] = 100

    for (k, v) in dict1 {

        dict[k] = v

    }

    print(dict)

    函数

    1、函数的定义

    (1)格式 func 函数名(行参列表) -> 返回值 {代码实现}

    (2)调用 let result = 函数名(值1, 参数2: 值2...)

    2、没有返回值的函数,一共有三种写法

    (1)省略

    (2)—> ()

      (3)  —>Void

    3、外部参数

    (1)在形参名前再增加一个外部参数名,能够方便调用人员更好地理解函数的语义

    (2)格式:func 函数名(外部参数名 形式参数名: 形式参数类型) -> 返回值类型 { // 代码实现 }

    例:

    func sum1(num1 a: Int, num2 b: Int) -> Int {

        return a + b

    }

    sum1(num1: 10, num2: 20)

    (3)Swift 2.0 中,默认第一个参数名省略

    (4)闭包中也有外部参数

    4、swift 可以在函数中定义函数,函数也可以作为其他函数的参数

    十一闭包

    1、定义:闭包类似于 OC 中的 Block

    (1)预先定义好的代码块

    (2)在需要时执行

    (3)可以像变量一样当作参数传递

    (4)可以像函数一样有返回值

    (5)包含 self 时需要注意循环引用

    2、作用:与 OC 中的 Block 类似,闭包主要用于异步操作执行完成后的代码回调,网络访问结果以参数的形式传递给调用方

    3、格式:闭包 = { (行参) -> 返回值 in // 代码实现 },例:

    let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in

        return x + y

    }

    sumFunc(num1: 10, num2: 20)

      最简单的闭包,直接就是 闭包 = {代码实现 }

    4、尾随闭包:函数的最后一个参数是一个闭包,则小括号可以提前关闭,闭包放在小括号外面

    5、 如果函数的参数只有一个闭包,函数的小括号可以省略,例:

    loadData { (result:String) -> () in

                           

    print(result)

        }

    6、闭包回调简单应用示例

    (1)  override func viewDidLoad() {

            super.viewDidLoad()

           

        //  调用带有闭包作为参数的函数(尾随闭包效果)

            loadData() { (result) -> () in

                print(result)

            }

        }

        

    (2)  //  函数需要传入一个闭包 闭包的类型是有参数无返回值得闭包

        func loadData(callbackClosure: (result: String) -> ()) {

            

            dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in

                

                //  模拟耗时操作

                NSThread.sleepForTimeInterval(2)

                

                let result = "办证:137xxxx"

                

                dispatch_async(dispatch_get_main_queue(), { () -> Void in

                    

                    callbackClosure(result: result)

                    

                })

                

            }

            

        }

    十二闭包的循环引用

    1、原因,类似于OC中的block:

      <1> OC中

    (1)对象A 有一个 block 的属性, self 通过调用A的方法,将定义好的block 传递给对象A ,说明对象A 引用了这个block

    (2)对象A 又作为 self 的一个属性, 说明 self 引用了对象A

    (3)block 中出现 self , 说明这个block 引用了 当前 self 

    (4)到此 : 引用循环形成

      <2> swift中(最简单的循环引用)

    (1)闭包中 出现self , 说明闭包持有(引用)了self

    (2)self 中 定义了这个闭包,说明self 引用了这个闭包

    2、示例

    (1)“全局”的闭包变量

    var closure: (()->())?

    (2)给闭包赋值,并且在闭包中引用了self

        override func viewDidLoad() {

            super.viewDidLoad()

            

            closure = { 

                

                dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in

                    NSThread.sleepForTimeInterval(2)

                    dispatch_async(dispatch_get_main_queue(), { () -> Void in

                          print(self.view)

                    })

                })

            }

            

            closure?()

    }

    (3)循环形成

    3、解决

     <1> OC中

    (1)使用弱引用,破除环

    (2)iOS5.0 推出:__weak typeof(self) weakSelf = self;

    (3)iOS4.0 推出:__unsafe_unretained typeof(self) weakSelf = self;

    (4)区别:__unsafe_unretained 如果当前对象self销毁后,weakSelf执行的地址不变,而这个地址对应对象已经销毁了,所以再去访问该对象就崩溃,形成野指针了,相当于assign。然而前者在self销毁后,会自动把weakSelf的地址设置成nil,所以不会有野指针

     <2> swift中

    (1)仿OC写法:

      weak var weakSelf = self

    (2)swift写法:

            [weak self] 相当于 之前__weak 对象销毁后 self指向的地址为nil

            [unowned self] 相当于 之前的 __unsafe_retain  对象销毁后 self执行的地址不变

          

            

            closure = { [unowned self] in

                //  判断weakSelf是否有值,如果有值则执行,否则直接返回nil

                

                dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in

                    NSThread.sleepForTimeInterval(2)

                    dispatch_async(dispatch_get_main_queue(), { () -> Void in

                          print(self.view)

                    })

                })      

            }

            closure?()

        }

    (2)析构函数,对象释放后会执行这个函数,类比OC的dealloc

        deinit {

            //  移除通知

            //  移除kvo

            //  移除NSTimer

            

            print("ViewController over")

        }

    十三构造函数

    1、定义:是一种特殊的函数,主要用来:

    (1)在创建对象时初始化对象

    (2)为对象成员变量设置初始值

    2、和OC的对比:

    (1)在 OC 中的构造函数是 initWithXXX,在 Swift 中由于支持函数重载,所有的构造函数都是 init,不用写func

    (2)构造函数的作用

    分配空间 alloc

    设置初始值 init

    3、必选属性

    1非可选属性就是必选属性

    2如果一个类中定义了必选属性,必须通过构造函数为这些必选属性分配空间并且设置初始值

    4Optional 可选属性

    (1)可选属性不需要设置初始值,默认初始值都是 nil

    (2)可选属性是在设置数值的时候才分配空间的,是延迟分配空间的,更加符合移动开发中延迟创建的原则

    (3)注意,普通数据类型如Int,在设置为可选,并且没有初始化时,也是nil,在与OC的交互中就会出问题,因为OC的普通类型都有初始值,比如Int = 0 ,所以要根据情况,给可选属性初始化。。。  这种情况出问题的,比如KVC给模型属性赋值。

    5override init() 方法的特殊性  (其中有些争议)

    (1)先给自己的必选属性赋值

    (2)再调用super.init()初始化父类的属性

    (3)其他重载的构造函数不是这个顺序,要先调用super实例化对象,再给自己的必选属性赋值

    4关于系统提供的默认构造函数Xcode 7 beta 5之后,父类的构造函数会被自动调用(也就是说,可以不用写super.init()),强烈建议写 super.init(),保持代码执行线索的可读性(这里应该是只有父类系统会自动调用。。)

    (5)重载的构造函数,系统不会调用默认构造函数  ( 这句话有待商榷,实验中,也是调了,个人感觉,只要是继承自NSObject的父类,系统都会帮我们调默认的构造函数,而子类就不会,因为默认的构造函数满足不了需求)

    十四、重载与重写

    1、重载定义:

    (1)面向对象的一个重要特征,oc里面没有

    (2)函数名相同,参数名或者参数个数不同就是重载,不仅限于构造函数

     (3) 函数重载能够简化程序员的记忆

    2、重写定义:

    (1)必须有继承关系的函数,对父类函数功能的重写和完善

    (2)override关键字

    3、注意事项

    (1)如果重载了构造函数,但是没有实现默认的构造函数 init(),则系统不再提供默认的构造函数。原因,在实例化对象时,必须通过构造函数为对象属性分配空间和设置初始值,对于存在必选参数的类而言,默认的 init() 无法完成分配空间和设置初始值的工作(这里也是有待商榷,实验证明,父类不管是否实现 init(),重载了构造函数,系统依然会调用默认的构造函数)

    (2)在子类中,如果是重载的构造函数,必须 super 以完成父类属性的初始化工作

    (3)重写时,子类需要在父类拥有方法的基础上进行扩展,需要 override 关键字,父类没有方法,重写不了!

    (4)重写的是构造方法时,也要注意super一下,除非你是父类,系统帮你super.init(这是实验结果)

    十五、KVC构造函数

    1、KVC本质

    (1)KVC 是 OC 特有的,KVC 本质上是在运行时,动态向对象发送 setValue:ForKey: 方法,为对象的属性设置数值

    (2)在使用 KVC 方法之前,需要确保对象已经被正确实例化

    2、关于基本数据类型

    (1)在 Swift 中,如果属性是可选的,在初始化时,不会为该属性分配空间

    (2)OC 中基本数据类型就是保存一个数值,不存在可选的概念,比如Int 默认是0,不是nil

    (3)使用KVC进行属性赋值时,如果基本数据类型的属性没有初始化,就会报错,所以,需要初始化一个数值

    报错举例:this class is not key value coding-compliant for the key age. ->这个类的键值 age 与 键值编码不兼容

    3KVC 函数调用顺序

      (1) setValuesForKeysWithDictionary 会按照字典中的 key 重复调用 setValue(value, forKey) 函数

      (2) 如果没有实现 forUndefinedKey 函数,程序会直接崩溃,NSObject 默认在发现没有定义的键值时,会抛出 NSUndefinedKeyException 异常

           如果实现了 forUndefinedKey,会保证 setValuesForKeysWithDictionary 继续遍历后续的 key

      (3) 如果父类实现了 forUndefinedKey,子类可以不必再实现此函数

    (4)补充:setValue(value, forKeyPath) 这个方法默认也是调用 setValue(value, forKey),不要在后者中去实现前者,否则死循环

    (5)如果实现setValue(value, forKey)方法,不要忘记super

    4、补充:通过KVC给只读属性赋值,例:自定义tabBar

       

         //自定义tabBar    

         let tab = ZQTabBarView()

            

         //使用kvc,给readonly属性赋值

            

         setValue(tab, forKey: "tabBar")

            

    十六convenience 便利构造函数

    1、定义

    1)可以返回nil的构造函数(可失败的构造函数)

    2)有关键字convenience

    3)不能被重写

    4)不能使用super

    5)使用self 来调用自己的其他指定构造函数,比如:self.init()

    6init后面有?

    2指定构造函数

    1默认情况下,所有的构造方法都是指定构造函数 Designated

    (2)除了便利构造函数

    3示例    (在 Xcode 中,输入 self.init 时没有智能提示)

    convenience init?(name: String, age: Int) {

        if age < 20 || age > 100 {

            return nil

        }

        self.init(dict: ["name": name, "age": age])

    }

    4便利构造函数应用场景

    (1)根据给定参数判断是否创建对象,而不像指定构造函数那样必须要实例化一个对象出来

    (2)在实际开发中,可以对已有类的构造函数进行扩展,利用便利构造函数,简化对象的创建

    5、再次注意

    (1)指定构造函数必须调用其直接父类的的指定构造函数(除非没有父类,系统调),也就是必须调一下指定构造函数

    (2)便利构造函数可以返回 nil

    (3)便利构造函数不能被重写

    (4)便利构造函数必须调用同一类中定义的其他指定构造函数,如果自己没有指定构造函数,则用 self. 的方式调用父类的便利构造函数,再或者通过self.的方式调用父类的指定构造函数(子类从父类继承)

    6、图示:(子类便利构造函数调用父类便利构造函数的情况没有描述)

    Pasted Graphic.tiff

    十七懒加载

    1、意义如同OC中的懒加载,swift懒加载本质上是一个闭包,在使用的时候才会创建

    2、懒加载的格式:关键字  lazy

    (1)闭包写法:定义一个闭包,并执行了,这里语句  “ ()-> Person in” 省略了,只有懒加载可以

    lazy var person: Person = {

        return Person()

    }()

    (2)同上

    let personFunc = { () -> Person in

        return Person()

    }

    lazy var demoPerson: Person = self.personFunc()

    (3)懒加载的简单写法 :定义个变量,前面加上lazy

    lazy var demoPerson: Person = Person()

    3、注意:与 OC 不同的是,lazy 属性即使被设置为 nil 也不会被再次调用

    十八只读属性和重写set方法

    1、swift的 set和get方法

    (1)在 Swift 中 getter & setter 很少用

    (2)示例:

    private var _name: String?

    var name: String? {

        get {

            return _name

        }

        set {

            _name = newValue

        }

    }

    3)经常使用的重写set方法

        var person: Person? {

            didSet {

                nameLabel.text = person?.name

                ageLabel.text = "(person?.age ?? 0)"

            }

        }

    2存储型属性

    1需要开辟空间,以存储数据

    3、计算型属性(只读)

    1执行函数返回其他内存地址

    (2)只实现 getter 方法的属性被称为计算型属性,等同于 OC 中的 ReadOnly 属性

    var title: String {

        get {

            return "Mr " + (name ?? "")

        }

    }

    简写

    var title: String {

        return "Mr " + (name ?? "")

    }

    (3)计算型属性本身不占用内存空间

    (4)不可以给计算型属性设置数值

    5)只读型更像一个函数,不过不能接收参数,同时必须有返回值

    (6)每次调用时都会被执行,这里和懒加载不同

    十八、网络访问(不使用AFN

    1、同OC ,在iOS7.0以后,默认使用https,要设置白名单(ATS)强制访问

    <key>NSAppTransportSecurity</key>

    <dict>

      <!--Include to allow all connections (DANGER)-->

      <key>NSAllowsArbitraryLoads</key>

          <true/>

    </dict>

    2、JSON的反序列化:与OC略不同

     (1)try! 向系统保证我的数据一定是一个json

           let result = try! NSJSONSerialization.JSONObjectWithData(data, options: [])

        

    (2) try? 如果是json就反序化成功,否则直接返回nil

           let result = try? NSJSONSerialization.JSONObjectWithData(data, options: [])

               

    (3) try catch   判断序列化的时候是否出现异常,如果有异常则进入catch,否则反序列化成功

               

    do {

              let result = try NSJSONSerialization.JSONObjectWithData(d, options: [])

                    print(result)

             } catch {

                    print(error)

             }

    十九swift使用pod

    1、如同OC正常安装pod

    2、在podfile文件中贴入(可以使用vim编辑器),第一行不可少,使用OC框架可以不用桥接(不知道什么鬼。。)

    use_frameworks!

    platform :ios, '8.0'

    pod 'SDWebImage'

    pod 'SVProgressHUD'

    pod 'SnapKit'

    pod 'FMDB'

    pod 'AFNetworking'

    二十swiftOC 的桥接

    1、正常情况下,swift想要使用oc的文件需要桥接

    2、步骤:

    (1)创建一个 header.h 文件(要求和 info.plist同级)

    (2)找到bridge的配置路径,把 header.h路径放入配置文件里:

    配置文件步骤  buildSettings - > 查找bridge  - > 设置路径(和info.plist同级)

    (3)到 header.h 文件里 ,导入 OC框架的头文件,需要哪个导入哪个

       

    二十一extension description

    1、extension 类似于 OC 的 Category,可以按照函数类型区分代码,能够让代码结构具有更好的可读性

    2、重写 description 属性(只读属性),便于调试。 在类中定义如下,将成员属性作为key传入,然后打印这个类的对象就可以显示出准确内容

    例:
    override var description: String {

      let keys = ["name", "age"]

        return dictionaryWithValuesForKeys(keys).description

    }

    二十二、自定义DEBUG

    1、如同OC中的PCH文件,设置自定义的DEBUG,可以随时调整关闭DEBUG

    2、步骤

    (1)创建swift file 文件

    (2)贴入下面内容

    /// 输出日志

    /// - parameter message:  日志消息

    /// - parameter logError: 错误标记,默认是 false,如果是 true,发布时仍然会输出

    /// - parameter file:     文件名

    /// - parameter method:   方法名

    /// - parameter line:     代码行数

    func printLog<T>(message: T,

            logError: Bool = false,

        file: String = __FILE__,

        method: String = __FUNCTION__,

        line: Int = __LINE__)

    {

        if logError {

                 print("((file as NSString).lastPathComponent)[(line)], (method): (message)")

        } else {

            

    #if DEBUG

                print("((file as NSString).lastPathComponent)[(line)], (method): (message)")

            #endif

        }

    }

    (3)配置:buildingSetting  -> 查找 swift flags  - >在下方设置debug标记  - >    点击加号  ->  添加  :  -D DEBUG

    (4)程序发布前,删掉 DEBUG即可

    (5)另外,在此文件中定义的变量、常量,可以全局访问,类似PCH文件

    二十三、SpanKit 和 SVProgressHUD 的使用

    1、SpanKit用来进行页面布局的三方控件(约束),等同于OC中的 masnory

    示例

          registerButton.snp_makeConstraints { (make) -> Void in

                make.left.equalTo(noticeLabel.snp_left)

                make.top.equalTo(noticeLabel.snp_bottom).offset(10)

                make.width.equalTo(100)

                make.height.equalTo(30)

            }

    2、SVProgressHUD 简单使用

    示例

    func webViewDidStartLoad(webView: UIWebView) {

        SVProgressHUD.show()

    }

    func webViewDidFinishLoad(webView: UIWebView) {

        SVProgressHUD.dismiss()

    }

    ///  关闭

    func close() {

        SVProgressHUD.dismiss()

        dismissViewControllerAnimated(true, completion: nil)

    }

  • 相关阅读:
    数据仓库的一些理解(转)
    常见ETL工具一览,你知多少?
    dhcpv6开源软件配置
    svn
    js原型模式
    combo扩展:禁止手工改变输入框的值
    SQLite错误总结 error code 19: constraint failed
    ntp源码解读(一)
    ntp-keygen.c
    6.2.2认证
  • 原文地址:https://www.cnblogs.com/cleven/p/5366067.html
Copyright © 2011-2022 走看看