前言:
1.此文中的语法会根据Swift的升级变动而更新。
2.如果需要请移步 -> swift2.2 语法(上)、swift 2.2语法(中)
swift会自动释放不需要的实例来达到释放资源的目的
格式:
deinit { 需要执行的操作 }
这个比较好理解,就直接上代码了
class person: NSObject {
// KVC方式下,对象、结构体类型必须是可选类型,否则无法转换
var name : String?
// 自定义构造函数,覆盖init:函数
init(dict : [String : NSObject]) {
// 必须先初始化对象
super.init()
// 调用对象的KVC方法
setValuesForKeysWithDictionary(dict)
}
deinit {
print("移除通知")
print("释放各种资源")
}
}
// 创建person对象
var ps : person? = person(dict:["name" : "laoWang"])
ps = nil // 当赋值为nil时自动引用计数为0,系统将会调用deinit对资源进行释放
swift也是采用自动引用计数来管理内存
循环引用
class Person {
var dog : Dog?
deinit {
print("释放person")
}
}
class Dog {
var master : Person?
deinit {
print("释放Dog")
}
}
// 创建对象
var ps : Person? = Person()
var d : Dog? = Dog()
// 循环引用
ps?.dog = d
d?.master = ps
// 释放资源失败原因:因为person内有个属性强引用着Dog,而Dog内也有个强引用引用着Person,造成了循环引用,所以即使将ps和d赋值为nil也无法释放对象
ps = nil
d = nil
- 解决办法
- swift提供了2中方法来解决循环引用的问题
- 使用weak:这个关键字和OC的__weak一样都是弱引用,当指向的对象呗销毁的时候,会自动将指针指向nil
- 使用unowned:和OC中的__unsafe_unretained相似,当对象销毁时,指针依然指向原来的位置(比较危险,容易引起野指针错误)
<br><br>
```
class Person {
// 声明dog为弱引用
weak var dog : Dog?
deinit {
print("释放person")
}
}
class Dog {
var master : Person?
deinit {
print("释放Dog")
}
}
// 创建对象
var ps : Person? = Person()
var d : Dog? = Dog()
// 循环引用
ps?.dog = d
d?.master = ps
// person和dog对象被释放
ps = nil
d = nil
```
可选链使用
因为可选链的结果可能为nil,所以它返回的值是个可选类型
class Person1 {
var name : String
var dog : Dog?
init(name : String) {
self.name = name
}
}
class Dog {
var ball : Ball?
func yesOrNo() {
print("YES,可选类型有值") // 调用成功
}
}
class Ball {
var price : Double = 0.0
}
// 创建对象并设置相互的关联性
let ps = Person1(name: "LiSi")
let d = Dog()
let ball = Ball()
ball.price = 300.0
// 李四拥有一条狗
ps.dog = d
// 狗有个球
d.ball = ball
// 获取狗的球的价格
let price = ps.dog?.ball?.price
print(price) // 结果:300.0
// 给狗一个新的球
ps.dog?.ball = Ball()
// 如果返回值有值就会继续执行下面这句,如果nil就不会执行
ps.dog?.yesOrNo()
protocol 协议名 { 协议方法 }
class 类名 : 类的父类, 协议名,协议名 {
}
// 比如
class ViewController: UIViewController, UITableViewDelegate {
}
// 定义
protocol testProtocol {
// 协议方法
func test1()
func test2()
}
// 使用(swift中默认情况下所有的协议方法都必须实现,不然会报错)
class Person : testProtocol {
var name : String?
// 实现协议方法
func test1() {
print("test1")
}
func test2() {
print("test2")
}
}
// 定义
protocol testProtocol {
// 协议方法
func test1()
func test2()
}
protocol test2Protocol : testProtocol {
// 协议方法
func test3()
}
// 定义
protocol testProtocol {
// 协议方法
func test1()
}
// 使用(swift中默认情况下所有的协议方法都必须实现,不然会报错)
class Person {
// 定义delegate属性
var delegate : testProtocol
// 自定义构造函数
init(delegate : testProtocol) {
self.delegate = delegate
}
// 方法
func personTest() {
delegate.test1()
}
}
class Dog : testProtocol {
func test1() {
print("调用test1") // 结果:调用test1
}
}
// 设置代理
let p = Person(delegate: Dog())
// 实现代理方法
p.personTest()
// 如果不是每个协议方法都必须实现只需这样写
@objc protocol testProtocol {
// 协议方法
optional func test1()
}
闭包类似于OC中的Block
闭包的格式
(形参列表)->(返回值)
// block形式
- (void)downloadData:(void (^)())block
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"下载数据:%@", [NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
// 调用block
block();
});
});
}
- (void)test
{
[self downloadData:^{
NSLog(@"block块: %@", [NSThread currentThread]);
}];
}
// 闭包形式
func downloadData(block : () -> ()) { dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("下载数据:\(NSThread.currentThread())")
dispatch_sync(dispatch_get_main_queue(), { () -> Void in block() }) } } func test() { downloadData { () -> () in
print("block块:\(NSThread.currentThread())")
}
}
闭包简写
downloadData ({ print("block块:\(NSThread.currentThread())") })
尾随闭包
downloadData(){ () -> () in
print("block块:\(NSThread.currentThread())")
}
downloadData { () -> () in
print("block块:\(NSThread.currentThread())")
}
class download : NSObject {
// 定义变量来强引用block
var block : (()->())?
func downloadData(block : ()->()) {
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("下载数据:\(NSThread.currentThread())")
dispatch_sync(dispatch_get_main_queue(), { () -> Void in
block()
})
// 制造循环引用
self.block = block
}
}
deinit {
print("deinit")
}
}
var d : download? = download()
d?.downloadData { () -> () in
print("调")
}
d = nil
循环引用解决方法
// 且必须是变量,不能是常量
weak var weakSelf = self
unowned var unSelf = self
lazy var 变量名 : 类型 = {
创建代码
}()
lazy var test : [Int] = {
() -> [Int] in
return 27
}()
我们常会定义一个枚举(enum)来确定各种可能出现的错误
来简单模拟下异常情况
// 假定这个方法我们不知道他的实现方式,如果不错任何处理,那么就很难猜中需要传的值
func test(name : String) -> String? {
guard name == "laoWang" else {
return nil
}
guard name == "laoLi" else {
return nil
}
return "true"
}
test("12") // 结果为nil
// 定义异常情况枚举
enum error : ErrorType {
case errorNameNotForLaoWangOrLaoLi
}
// 假定这个方法我们不知道他的实现方式,如果不错任何处理,那么就很难猜中需要传的值
func test(name : String) throws -> String {
guard name == "LaoWang" else {
throw error.errorNameNotForLaoWangOrLaoLi
}
guard name == "LaoLi" else {
throw error.errorNameNotForLaoWangOrLaoLi
}
return "true"
}
// 处理方法一 try!:告诉系统调用没有异常,如果出现异常,程序会崩溃
try! test("lao") // 结果 fatal error: 'try!' expression unexpectedly raised an error: error.errorNameNotForLaoWangOrLaoLi: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.1.101.15/src/swift/stdlib/public/core/ErrorType.swift, line 50
// 处理方法二 try? 出现异常返回nil,没有异常返回对应的值(返回的结果是个可选类型)
let result = try? test("hh") // 结果 nil
// 处理方法三 try 需要手动处理异常
do {
let result = try test("hh")
} catch {
print(error) // 结果 errorNameNotForLaoWangOrLaoLi
}
注释
访问权限