五、swift3.0闭包和懒加载

一、闭包的使用
与 OC中的Block类似,闭包主要用于异步操作执行完成后的代码回调,网络访问结果以参数的形式传递给调用方
在OC中block是匿名的函数;在swift中闭包是特殊的函数
回调的特点:以参数回调处理结果;返回值为Void

1、闭包的定义

闭包 = { (行参) -> 返回值 in
    // 代码实现
}

//1、定义一个常量记录函数
func sum(n : Int, m : Int) -> Int {
    return m + n
}
//swift中函数本身就可以当作参数被定义和传递
let f = sum

f(10, 20)

//2、定义一个最简单的闭包,() -> () 没有参数,没有返回值
let p = {
    print("hhah")
}
p()

//3、定义一个带参数的闭包
//通过“in”关键字,对闭包的定义和实现进行分割,没有参数没有返回值可以省略in
// {形参列表   返回值类型  -> in  实现代码}
let p2 = {(x : Int) -> () in
    print(x)
}
p2(123)


//4、定义一个带参数和返回值的闭包
let p3 = {(x : Int) -> Int in
    return x + 10
}
print(p3(23))
let p1 = { () -> () in
    print("没有参数,没有返回值的闭包")
}

let p2 = {
    print("没有参数,没有返回值的闭包简写")
}

//注:在OC中{}用来分隔作用域的,而在swift中,表示一个闭包

2、闭包的使用
//作为函数的返回值,进行回调操作
class Human: NSObject {
    
    func loadData(callBack : @escaping () -> ()) {
        DispatchQueue.global().async { () -> Void in
            
            print("加载数据的线程:\(Thread.current)");
            
            DispatchQueue.main.async(execute: {
                
                print("更新UI的线程:\(Thread.current)")
                
                callBack()
            })
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    
    let per = Human()
    
    per.loadData {
        print("获取到数据,刷新UI")
    }
}

//结果:
加载数据的线程:{number = 3, name = (null)}
更新UI的线程:{number = 1, name = main}
获取到数据,刷新UI

3、尾随闭包
如果一个函数的最后一个参数是闭包,则函数的参数可以提前结束,最后一个参数直接使用{}包装闭包的代码

let per = Human()
        
        //1、正常调用对象的函数
        per.loadData(callBack: { () -> () in
            print("获取到数据,刷新UI")
        })
        
        //2、尾随闭包的改进:函数的参数可以提前结束,后面直接跟上一个闭包包装代码
        per.loadData() { () -> () in
            print("获取到数据,刷新UI")
        }
        
        //3、简写
        per.loadData {
            print("获取到数据,刷新UI")
        }

4、闭包的循环引用

class ViewController: UIViewController {
    
    //定义一个闭包属性
    var completion : (() -> ())?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //如果记录了闭包属性,然后在闭包中又使用了self,则产生了循环引用
        //解决闭包中的循环引用
        //方法一:
        //weak只能修饰var,不能修饰let,因为如果weak的指针在运行时会被修改,会自动设置为nil
        weak var weakself = self
        loadData {
            //!:强制解包,必须有值,如果解包的值为nil,则崩溃
            //?:可选解包,如果解包为nil,则不会执行后面的内容
            print(weakself?.view ?? "")
        }
        
        //方法二:推荐
        //[weak self]表示闭包中的self都是若引用
        loadData { [weak self] in
            print(self?.view ?? "")
        }
        
        //方法三:类似OC中的unsafe_unretained,常用
        //[unowned self]表示闭包中的self为assign,如果self被释放,则指针地址不会被释放,容易导致出现野指针
        loadData { [unowned self] in
            print(self.view)
        }
    }
    
    func loadData(complete: @escaping () -> ()) -> () {
        //使用属性记录闭包
        //completion = completion
        
        DispatchQueue.global().async {
            print("耗时操作")
            
            DispatchQueue.main.async {
                //回调
                complete()
            }
        }
    }
    
    deinit {
        print("和dealloc一样")
    }
    
}
//在ARC中,weak本质是一个观察者模式,一旦对象释放,则把对象置为nil
//在MRC中,是通过assign进行若引用的,如果对象释放,assign的指针还是指向该内地地址,会造成野指针
__weak typeof(self) weakSelf = self;
//__unsafe_unretained相当于assign,
__unsafe_unretained typeof(self) weak1Self = self;

二、懒加载

注:懒加载只会在第一次调用时执行创建对象,后面如果对象被释放了,则不会再次创建。而oc中会再次创建。

//1、懒加载的定义
    //懒加载的本质就是闭包
    lazy var person : Human = {
        print("懒加载的定义")
        return Human()
    }()
    
    //2、懒加载改写为闭包形式
    let personFunc = { () -> Human in
        print("懒加载 --> 闭包")
        return Human()
    }
    
    lazy var personDemo : Human = self.personFunc()
    
    //3、懒加载的简单写法
    lazy var person2 : Human = Human()

三、UITableView的使用

import UIKit

class ViewController: UIViewController {

    // MARK:- 懒加载
    lazy var tableView : UITableView = {
        let tempTableView = UITableView()
        //可以做些事情
        
        return tempTableView;
    }()
    
    lazy var tableView2 : UITableView = UITableView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupUI()
    }
    
    
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }


}
// MARK:- 设置UI
extension ViewController {
    ///设置UI
    func setupUI() {
        //1、设置tableView的属性
        tableView.frame = CGRect.init(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height)
        
        //2、设置数据源
        tableView.delegate = self;
        tableView.dataSource = self;
        
        //3、加入到控制器view
        view.addSubview(tableView)
        
    }
}
// MARK:- UITableView的代理方法
//extension:类扩展只能扩充方法,不能扩充属性
extension ViewController : UITableViewDelegate, UITableViewDataSource {
    /// UITableViewDelegate
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("点击了\(indexPath)")
    }
    
    /// UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 20
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //1、创建cell
        let idenftify = "cellID"
        var cell = tableView.dequeueReusableCell(withIdentifier: idenftify)
        if cell == nil {
            cell = UITableViewCell.init(style: .default, reuseIdentifier: idenftify)
        }
        //2、赋值
        
        cell?.textLabel?.text = "测试\(indexPath.row)"
        
        //3、返回
        return cell!
    }
}


    //使用运行时获取当前类所有属性数组
    class func propertyList() -> [String] {
        //1、获取类的属性列表
        var count : UInt32 = 0
        //返回属性列表数组
        let list = class_copyPropertyList(self, &count)
        
        print("属性的数量:\(count)")
        
        //2、遍历属性列表
        for i in 0...Int(count) {
            
            //3、根据下标获取属性
            let pty = list?[i]
            
            //4、获取属性的名称
            
            let cName = property_getName(pty!)
            
            //5、转String
            let name = String.init(cString: cName!)
//            let name = String.init(describing: cName!)
            print(name)
        }
        
        //3、释放c语言的对象
        free(list)
        
        return []
    }

//网络请求数据举例
        let url = URL.init(string: "https://www.baidu.com")

        URLSession.shared.dataTask(with: url!) { (data, _, error) in
            if error != nil {
                print("网络加载失败!")
            }
            
            guard let data = data else {
                print("网络请求失败")
                return
            }
            
            let html = String.init(data: data, encoding: .utf8)
            print(html ?? "")
        }.resume()




 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(swift)