Block

  • Block格式:
  • 形参:

返回值类型(^Block名称)(形参列表)

  • 值:

^(形参列表){

// 逻辑代码

}



- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{  
    [self loadData:^{
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"回到主线程更新UI");
    }];

}
- (void)loadData:(void(^)())myBlock
{
    // 1.异步获取数据
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@", [NSThread currentThread]);
        NSLog(@"异步获取数据");
        // 2.回到主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            
            myBlock();
        });
        
    });
}



闭包

  • 闭包和OC中的Block很像
  • OC中的Block类似于匿名函数
  • Swift中的闭包就是一个特殊的函数
  • Block一般用于回调,异步准备数据,然后通过Block回调更新UI

闭包的格式:

  • (形参列表) -> 返回值

技巧:

  • 闭包类型,先写上 () -> () 然后再根据具体情况进行定义

值:

  • in的作用就是用于分隔逻辑代码和描述
{

(形参列表) -> 返回值类型

in

  //逻辑代码

}



 

闭包的简写

  • 如果没有返回值也没有参数,那么in和in之前的代码可以删除
  • 如果闭包是形参列表的最后一个参数,那么可以把闭包写到()的后面
  • 如果函数只有一个形参,并且这个形参是一个闭包,那么()可以不写
  • loadData({ () -> () in ***code****})
  • loadData( { ***code*** } )
  • loadData (){ ***code*** } //称为尾随闭包
  • loadData { ***code*** } // 称为尾随闭包  推荐这种写法
//        loadData ({ () -> () in
//            print(NSThread.currentThread())
//            print("回到主线程更新UI")
//        })
        
//        loadData ({
//            print(NSThread.currentThread())
//            print("回到主线程更新UI")
//        })
        
        // 以下两种写法, 我们称之为尾随闭包
//        loadData (){
//            print(NSThread.currentThread())
//            print("回到主线程更新UI")
//        }
        
        // 开发中建议写下面这一种写法
        loadData {
            print(NSThread.currentThread())
            print("回到主线程更新UI")
        }
    }


    func loadData(myBlock: ()->())
    {
        dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
            print(NSThread.currentThread())
            print("异步准备数据")
            
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                myBlock()
            })
        }
    }



 闭包的循环引用

  • OC中Block的循环引用: __weak typeof(self) weakSelf = self ;
  • Swift中闭包的循环引用的解决方法: weak var weakSelf = self  //因为变量是weak的,随时有可能被释放,所以系统推导是可选类型
class ViewController: UIViewController { 

    // 报错的原因: Swift规定一个对象中的属性必须在对象初始化时全部初始化

    // 如果没有在初始化时给所有的属性赋值, 那么就会报错

    // 要想不报错, 那么可以让属性变成可选的

    

    // 注意: 错误写法()->()? , 这中写法代表闭包的返回值是可选的, 而不是闭包是可选的

    // 可选类型的值, 如果没有初始化, 那么默认值就是nil

    var finished: (()->())?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        // Do any additional setup after loading the view, typically from a nib.

        view.backgroundColor = UIColor.purpleColor()

    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {      

/*

  // 方法1

       //  OC中: __weak typeof(self) weakSelf = self;

       // 因为变量是weak的, 随时有可能被释放, 所以系统推导是可选类型

        // Swift中: weak var weakSelf = self 

       weak var weakSelf = self

   loadData { () -> () in

            print(NSThread.currentThread())

            print("回到主线程更新UI")

            weakSelf!.view.backgroundColor = UIColor.redColor()    //weakSelf 强制解包

        }

*/

/*

  //方法2

   loadData { [weak self]() -> () in   //[weak self]

            print(NSThread.currentThread())

            print("回到主线程更新UI")

            self!.view.backgroundColor = UIColor.redColor()    //self 强制解包

        }

*/

        // 方法3   开发中推荐这样写

       //  Swift中的weak对应OC中的__weak, 如果对象释放了, 那么会自动将变量赋值为nil

        // Swift中的unowned对应OC中的__unsafe_unretained,  如果对象释放了, 不会将变量赋值为nil, 如果对象释放了再继续访问会出现野指针错误

 

        loadData { [unowned self] () -> () in   //[unownes self]

            print(NSThread.currentThread())

            print("回到主线程更新UI")

            self.view.backgroundColor = UIColor.redColor()   

        }

    }

    

    func loadData(myBlock: ()->())

    {

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

            print(NSThread.currentThread())

            print("异步准备数据")

            

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

                self.finished = myBlock

                myBlock()

            })

        }

    } 

    // OC : dealloc

    // Swift: deinit

    deinit

    {

        // 只要对象释放就会调用这个方法

        print("滚")

    }

 

}