iOS 中block结构的简单用法(一)

简介: iOS 中block结构的简单用法

自从block出现之后,很多API都开始采用这样的结构,由此可见,block确实有许多优势存在,这里将一些简单用法总结如下:


一、如何声明一个block变量


我们通过^符号来声明block类型,形式如下:


void (^myBlock)();


其中第一个void是返回值,可以是任意类型,中间括号中^后面的是这个block变量的名字,我把它命名为myBlock,最后一个括号中是参数,如果多参数,可以写成如下样式:


int (^myBlock)(int,int);


同样,你也可以给参数起名字:


int (^myBlock)(int a,int b);


很多时候,我们需要将我们声明的block类型作为函数的参数,也有两种方式:


1、-(void)func:(int (^)(int a,int b))block;


第二种方式是通过typedef定义一种新的类型,这也是大多数情况下采用的方式:


2、typedef int (^myBlock)(int a,int b) ;


-(void)func:(myBlock)block ;


二、如何实现一个block


既然block可以被声明为变量,那么就一定可以实现它,就像其他类型变量的赋值。我自己对block的理解为它是一断代码块,所以给它赋值赋便是一段代码段:


typedef int (^myBlock)(int,int) ;

@interface ViewController ()

{

   myBlock block1;

}

@end


@implementation ViewController


- (void)viewDidLoad {

   [super viewDidLoad];

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

   block1 =^(int a, int b){

       return a+b;

   };

  NSLog(@"%d",block1(1,1));

}

这里打印的结果是2,从这里可以发现block和函数的功能很像。


注意:1、在上面的代码里 block1是一个对象,如果直接打印将打印对象地址


       2、block(),加上后面的括号才是执行block语句块


三、block中访问对象的微妙关系


1、如果你在一个block块中仅仅访问对象,而不是对他进行修改操作,是没有任何问题的:


- (void)viewDidLoad {

   [super viewDidLoad];

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

   int tem=2;

   block1 = ^(int a,int b){

       int count= tem+1;

       return count;

   };

   NSLog(@"%d",block1(1,1));

}

而如果我在block块中直接修改,编译器会报错:


 block1 = ^(int a,int b){

       tem+=1;

       return tem+1;

   };

为什么会出现这样的情况,根据猜测,可能是block内部将访问的变量都备份了一份,如果我们在内部修改,外部的变量并不会被修改,我们可以通过打印变量的地址来证明这一点:


- (void)viewDidLoad {

   [super viewDidLoad];

   int tem=2;

   NSLog(@"%p",&tem);

   block1 = ^(int a,int b){

       NSLog(@"%p",&tem);

       return tem+1;

   };

   NSLog(@"%d",block1(1,1));

}

打印结果如下:

image.png



可以看出,变量的地址已经改变。


2、__block 做了什么


为了可以在block块中访问并修改外部变量,我们常会把变量声明成__block类型,通过上面的原理,可以发现,其实这个关键字只做了一件事,如果在block中访问没有添加这个关键字的变量,会访问到block自己拷贝的那一份变量,它是在block创建的时候创建的,而访问加了这个关键字的变量,则会访问这个变量的地址所对应的变量。我们可以通过代码来证明:


- (void)viewDidLoad {

   [super viewDidLoad];

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

   int tem=2;

   block1 = ^(int a,int b){  

       return tem+a+b;

   };

   tem=4;

   NSLog(@"%d",block1(1,1));

 

   block1 = ^(int a,int b){  

       return tem+a+b;

   };

    __block int tem2=2;

   tem2=4;

    NSLog(@"%d",block1(1,1));

}

结果:

image.png

目录
相关文章
|
9月前
|
Swift iOS开发
iOS @available 和 #available 的用法
iOS @available 和 #available 的用法
220 0
|
4月前
|
JSON 安全 数据安全/隐私保护
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
20 0
|
5月前
|
JSON 安全 数据安全/隐私保护
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
iOS Class Guard是一个用于OC类、协议、属性和方法名混淆的命令行工具。它是class-dump的扩展。这个工具会生成一个symbol table,这个table在编译期间会包含进工程中。iOS-Class-Guard能有效的隐藏绝大多数的类、协议、方法、属性和 实例变量 名。iOS-Class-Guard不是应用安全的最终解决方案,但是它绝对能让攻击者更难读懂你的程序。iOS-Class-Guard会加大代码分析和runtime检查的难度,这个工具可以认为是一个简单基础的混淆方法。由于OC的架构决定了iOS应用程序的剖析相当简单,check out一下链接就知晓了:
|
9月前
|
iOS开发
iOS block修饰符用copy还是strong
iOS block修饰符用copy还是strong
103 0
|
iOS开发 开发者
iOS开发 - 如何写出漂亮的block
iOS开发 - 如何写出漂亮的block
78 0
|
iOS开发
iOS开发- 关于Block的几种应用
iOS开发- 关于Block的几种应用
94 0
|
iOS开发 Python
iOS小技能:lldb打印block参数签名
iOS逆向时经常会遇到参数为block类型,本文介绍一个lldb script,可快速打印出Objective-C方法中block参数的类型。
159 0
iOS小技能:lldb打印block参数签名
|
自然语言处理 iOS开发
IOS——Block
IOS——Block
64 0
|
iOS开发
iOS代理 通知 block传值的规范写法
iOS代理 通知 block传值的规范写法
117 0
|
程序员 API iOS开发
iOS开发:个人对于textView基础用法的总结(其一)
从事了这么久ios开发,对于textView的使用并不陌生,它和textfield有相似的地方,也有不同的地方,这里只对textView的一些基础用法进行描述,textfield不在这里描述。
301 0