在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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相同
3、switch(变化很大)
(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 写法 语义 :在一个范围(或集合中)循环遍历出每个个体 ,例:
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)如果一个类中定义了必选属性,必须通过构造函数为这些必选属性分配空间并且设置初始值 4、Optional 可选属性 (1)可选属性不需要设置初始值,默认初始值都是 nil
(2)可选属性是在设置数值的时候才分配空间的,是延迟分配空间的,更加符合移动开发中延迟创建的原则 (3)注意,普通数据类型如Int,在设置为可选,并且没有初始化时,也是nil,在与OC的交互中就会出问题,因为OC的普通类型都有初始值,比如Int = 0 ,所以要根据情况,给可选属性初始化。。。 这种情况出问题的,比如KVC给模型属性赋值。
5、override 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 与 键值编码不兼容
3、KVC 函数调用顺序 (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() (6)init后面有?
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、图示:(子类便利构造函数调用父类便利构造函数的情况没有描述)
十七、懒加载
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'
二十、swift和OC 的桥接
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传入,然后打印这个类的对象就可以显示出准确内容 例: 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) }
|
请发表评论