swift和OC的闭包浅析

swift

自动闭包

自动闭包(@autoclosure) 官方的 ?? || &&就是autoClosure

自动闭包是一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包。它不接受任何实际参数,并且当它被调用时,它会返回内部打包的表达式的值

public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T

func ??<T>(optional: T?, defaultValue: @autoclosure () -> T) -> T {
    optional {
       case .Some(let value):
           return value
       case .None:
           return defaultValue()
       }
}
// 使用
var optionalB: Int?
let a:Int = optionalB ?? 0
逃逸闭包

逃逸闭包的生命周期:

  • 1、闭包作为参数传递给函数;

  • 2、退出函数;

  • 3、闭包被调用,闭包生命周期结束

  • 即逃逸闭包的生命周期长于函数,函数退出的时候,逃逸闭包的引用仍被其他对象持有,不会在函数结束时释放。

		func getData(closure:@escaping (Any) -> Void) {
        print("函数开始执行--\(Thread.current)")
        DispatchQueue.global().async {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+2, execute: {
                print("执行了闭包---\(Thread.current)")
                closure("345")
            })
        }
        print("函数执行结束---\(Thread.current)")
    }

    getData { (data) in
            print("闭包返回结果:\(data)")
        }
    }

// 函数开始执行
// 函数执行结束
// 执行了闭包
// 闭包返回结果:345
尾随闭包:就是函数最后一个参数是闭包。
闭包捕获值 (嵌套函数)

默认情况下,嵌套函数是对外界不可见的,但是可以被它们的外围函数(enclosing function)调用。一个外围函数也可以返回它的某一个嵌套函数,使得这个函数可以在其他域中被使用。

var currentValue = -4
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
      print("\(runningTotal)")
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let makeIn = makeIncrementer(forIncrement: 2)
// makeIn 其实就是()->Int的闭包

while currentValue <= 4{
    currentValue = makeIn()
}
//0
//2
//4

OC

OC block

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    void(^b)(void) = ^() {
        NSLog(@"Block");
    };
    b();
    id a = [b class];
    while (a) {
        NSLog(@"%@",a);
        a = [a superclass];
    }
}
// 打印
// Block
// __NSGlobalBlock__
// NSBlock
// NSObject

创建的局部 Block 变量本身是属于 NSGlobalBlock 类的,而其最终也是继承自 NSObject 类,因此可以明确 Block 与普通的 Obiective-C对象并无本质区别。Obiective-C 中的 Block 有3种类型,分别是 __NSGlobalBlock____NSMallocBlock____NSStackBlock__

NSGlobalBlock 类型的 Block 又被称为全局 Block,类似于我们创建的函数,会被存放在内存区域中的数据区。数据区用来存放全局的变量。
NSStackBlock 类型的 Block 又被称为栈 Block,被存放在内存区域中的栈区。当一个作用域结束后,与之相关的栈中的数据都会被清理,因此对于栈 Blook,超出了其所在的作用域就会被回收。
NSMallocBlock类型的 Block 又被称为堆 Block,堆中的 Block 与 Objective-C对象一样,内存是否释放会受到引用计数的管理。当对一栈 Blook 进行copy操作时,就会创建出堆 Block。

Block中的变量捕获

全局变量 静态变量: Block会直接对其访问,并不会做其他额外的操作。(地址不变)

局部变量:Block会对其进行赋值:如果所使用的的变量是值类型,会直接复制值;如果是引用类型,会复制引用。

在Block内部尝试对外部的局部变量进行修改时,会产生编译错误,这是编译器为我们提供的一种错误预警:因为在Block内部的变量已经和外部的变量不再是同一个变量。在修改是指变量本身,对于变量引用的对象,如果对象可以修改,block内部依然可以对其进行操作。

__block关键字

Block内部对外部的局部变量本身进行修改是不被允许的,需要在Block内部修改外面的局部变量时,需要将局部变量声明成__block关键字。

- (void)viewDidLoad {
    [super viewDidLoad];
   	__block int a = 10;
   	self.block = ^{
   		a = 20;
   	}
   	self.block();
   	NSLog(@"%d", a);
}

你可能感兴趣的:(iOS,Swift,OC,ios,开发语言,swift,objective-c)