swift002

作者: 呦释原点 | 来源:发表于2017-03-12 11:42 被阅读5次

有来写学习swift的笔记了。。。。

函数的默认值
func sum3(x: Int = 1, y: Int = 2) -> Int {
    return x + y;
}
print(sum3()) // 3
//print(sum(x: 10)) // 以前的版本,现在不能用了
没有返回值的函数
//MARK: 函数无返回值, 用于闭包时
/*
 1.直接省略
 2.()
 3. Void
 */
func demo1() {
    print("哈哈")
}
func demo2()-> () {
    print("hehe")
}
func demo3() -> Void {
    print("嘻嘻")
}
使用常量记录函数
func sum(x: Int, y: Int) -> Int {
    return x + y
}
// 1>定义一个常量记录函数
let f = sum  // f的格式  (Int, Int) -> Int
// 2>在需要的时候执行
print(f(20, 40))    // 60

//f(<#T##Int#>, <#T##Int#>)   sum(x: <#T##Int#>, y: <#T##Int#>)   这两个调用是这样的
闭包

在OC中block是匿名的函数
在swift中函数是特殊的闭包

闭包:

  1. 提前准备好代码
  2. 在需要的时候执行
  3. 可以当做参数传递

闭包的应用场景:

  1. 异步执行完成回调
  2. 控制器间回调
  3. 自定义视图回调

回调特点:

  1. 以参数回调处理结果
  2. 返回值为Void
// 1>最简单的闭包

let b1 = {  // b1 的类型  () -> ()    没有参数没有返回值的函数     如果没哟参数,没有返回值,可以省略, 连 in 都一起省略
    print("hello")
}
// 执行闭包
b1()     // hello

 // 最简单的 block
 void(^b1)() = ^{
 NSLog(@"Hello");
 };
 b1();
 

// 2>带参数的闭包 
// 闭包中, 参数、返回值、实现代码 都是写在{}中
// 使用关键字 in  分隔定义和实现
// {形参列表 -> 返回值类型 // 实现代码 }
let b2 = { (x: Int) -> () in
    print(x)
}
b2(3)  // 3
// 3>带参数/ 返回值的闭包

let b3 = {
    (x: Int) -> Int in
    return x + 250
}
print(b3(111));  // 361

// 示例
func loadData(completion:@escaping (_ result:[String])->()) -> () {
        
        // GCD: 将任务添加到队列,指定执行任务的函数
        // ‘队列’调度任务(block/闭包), 以同步/异步的方式执行
 
        // 在异步执行任务,获取结果,通过block/闭包 回调
        
        DispatchQueue.global().async { 
            print("耗时操作 \(Thread.current)")  // 耗时操作 <NSThread: 0x600000071900>{number = 3, name = (null)}
            
            // 休眠
            Thread.sleep(forTimeInterval: 1.0)
            //获得结果
            let json = ["头条", "八卦", "粗大事了"]
            
            // 主队列回调
            DispatchQueue.main.async(execute: { 
                print("主线程更新 UI \(Thread.current)")  // 主线程更新 UI <NSThread: 0x600000067300>{number = 1, name = main}
                //回调 ->执行 闭包(通过参数传递的)
                completion(json)
            })
        }
        
    }
//在另外一个方法里调用
// 尾随闭包
loadData { (result) in
            print("获取的新数据 \(result)")   // 获取的新数据 ["头条", "八卦", "粗大事了"]
        }

        // ‘尾’随闭包
        // 如果函数的最后一个参数是闭包, 函数参数可以提前结束,最后一个参数直接使用{}包装闭包的代码。
        // 嵌套的GCD闭包,系统不会把里面的尾随闭包自动处理,可以自己处理

        //按函数本身编写的结果
        loadData(completion: {
            (result) -> () in
            print(result)
        })
{}的坑
let l = UILabel()
        //(l) 参数结束{尾随闭包}
        view.addSubview(l)
        //报错: Extra argument in call
        // 调用了额外的参数       {}是闭包
        {
            let l = UILabel()
            view.addSubview(l)
        }
闭包的循环引用
class ViewController: UIViewController {

    var completionCallBack:(()->())?   // 定义一个属性
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 闭包对self进行了copy, 闭包执行完以后, 会自动销毁, 同时释放self的引用
        
        // 使用weakSelf打破循环引用
        weak var weakSelf = self      // 只能用var修饰
        // weak 可能会在运行时被修改  -> 指向的对象一旦被释放,会自动设置为 nil
        loadData {
            // 解包两种方式
            // ? 可选解包  如果self已经被释放,不会项对象发送view的消息,更安全合理
            // ! 强制解包  如果self已经被释放,强行解包会崩溃
            
            /*
                weakSelf.view - 只是单纯的发送消息, 没有计算
                强行解包,因为需要计算,可选项不能直接参与运算
            */
            print(weakSelf?.view ?? "")
        }
        
        
        
        // 方法二:swift推荐方法
        // [weak self] 表示 {}中所有self 都是弱引用, 需要注意解包
        loadData { [weak self] in
            print(self?.view ?? "")
        }
        
        // 方法三:
        // [weak self] 表示 {}中所有self 都是assign的,不会强引用,但是,如果对象释放,指针地址不会变化
        // 如果对象被释放,继续调用,就会出现野指针的问题
        loadData { [unowned self] in
            print(self.view)
        }
        
    }

    
    
    func loadData(completion:@escaping () -> ()) -> (){
        
        // 使用属性记录闭包  ->  self对闭包引用了 
        // 循环引用了
        completionCallBack = completion
        
        DispatchQueue.global().async {
            print("耗时操作")
            DispatchQueue.main.async{
             // 回调, 执行闭包
            }
        }
    }
    
    deinit {
        print("over")
    }

}

oc中解决循环引用的两种方法

__weak typeof (self) weakSelf = self;
    [self loadData:^{
        NSLog(@"%@", weakSelf.view);
    }];
    
    /*
     __unsafe_unretained  同样是assign的引用(MRC 中没有 weak)
     在MRC中如果弱引用队形都是使用assign ,不会增加引用计数,但是一旦对象被销毁,地址不会改变,继续访问,会出现野指针错误
     在 ARC weak本质上是一个观察者模式,一旦发现对象不释放,会自动将地址设置为nil, 更加安全
     */
    __unsafe_unretained typeof (self) weakSelf = self;
    [self loadData:^{
        NSLog(@"%@", weakSelf.view);
    }];

相关文章

  • swift002

    有来写学习swift的笔记了。。。。 函数的默认值 没有返回值的函数 使用常量记录函数 闭包 在OC中block是...

网友评论

      本文标题:swift002

      本文链接:https://www.haomeiwen.com/subject/rxsngttx.html