代理block(一)

最重要的是先判断清楚谁是委托方,谁是代理方。委托方和代理方其实是相对的。谁让谁做什么,谁需要谁做什么,谁想做什么需要告诉谁


代理6步:

委托方3步:声明协议,声明delegate指针(属性),在需要时让代理执行协议方法

代理方3步:遵守协议,成为代理,实现协议方法


Block传值4步:(反向传值)

在(类似于委托方)中,1.声明block,2.声明block属性(相当于重命名了一下MyBlock,实际上两个是一样的),3.在声明block的.m中调用block,4.在推出委托方里实现block





 3) 协议代理用途

       1. 方法的回调、值的回传

       2. 规范方法的声明(类似接口)

       3. 实现多继承


可以在FirstViewController.m文件中这样

#import "FirstViewController.h"

#import "SecondViewController.h"

也可以在SecondViewController.m文件中这样

#import "SecondViewController.h"

#import "FirstViewController.h"

不存在重复引用的问题,但是这样没意义


【Block】

          【注】Block是管理程序中代码块的对象

          【注】__block关键字,声明一个变量,使变量在Block的内外都能使用。


          【作用】Block实现回调

_block  告诉编译器,block体中的变量可以做值的改变


好吧,关于Block有别于其他语言下的特殊实现点来了!
Block
是一种比较特殊的 Objective-C 对象。跟传统对象不同的是,Block不是在堆上创建的,而是在栈上。主要原因有两 ,首先是因为性能——在栈上分配空间几乎总是比在堆上快;其次是出于访问其他局部变量的需要。

但是,当函数的作用域结束时,栈会被销毁。如果Block被传递给一个方法,此方法会在定义Block的作用域销毁后才调用到这个Block,所以应该复制Block。可以在传递时就copy

[[myBlockA copy] autorelease]

或者像这段代码一样,在调用的方法里copy

Block被复制时,它会从栈移动到堆上。在块引用其作用域中定义的局部变量时,局部变量会随着块一起移动。所有被引用的 NSObject子类对象都会被保留(retain)而不是复制(因为这些对象本来就已经在堆上 ,而保留的耗时要比复制少一些)Objective-C 的运行时环境为Block创建每个局部变量的常量引用(const reference)。这也意味着默认情况下块不能修改上下文数据,如下所示的代码会导致编译错误。

用到这个额外的修饰符是为了命令编译器当Block被复制时也把变量__block 复制过去。复制是比保留和传递常量引用更耗时的操作,所以系统的实现者决定把选择权交给开发者。

总而言之,__block 是复制而不是保留变量

这样还可以避免循环保留导致对象无法被释放的问题。


ARC下:似乎已经没有栈上的block了,要么是全局的,要么是堆上的

在非ARC下:存在这栈、全局、堆这三种形式。


Block存储区域

首先,需要引入三个名词:

● _NSConcretStackBlock

● _NSConcretGlobalBlock

● _NSConcretMallocBlock

正如它们名字显示得一样,表明了block的三种存储方式:栈、全局、堆。block对象中的isa的值就是上面其中一个,下面开始说明哪种block存储在栈、堆、全局。block为何是个对象,参考点击打开链接




Block基本知识补充:

1.声明block

typedef void(^MyBlock)(NSString *name);

void返回值类型,“^”block标志,MyBlockblock的变量名,后面括号是传入的参数

2.声明属性

@property (nonatomic, copy) MyBlock block;

3.实现block

类似于写成self.block = ^(NSString *name){}

svc.block = ^(NSString *text1,NSString *text2){}

second.block1 = ^(NSString *text){

        label1.text = text;

        if ([text isEqualToString:@"123"]) {

            return NO;

        }

        return YES;

    };

/*


    //<3>block实现   block的实现必须写

    //小括号里面的参数为反传回来值

    //大括号里面的代码为所执行的操作

    second.block = ^(NSString *text1,NSString *text2){

        

        //取用block传回来的值

        label1.text = text1;

        label2.text = text2;

    };

*/

//

BOOL isBlock = second.block1(label1.text);

    if (isBlock) {

        self.view.backgroundColor = [UIColor redColor];

    }else{

        self.view.backgroundColor = [UIColor orangeColor];

    }

 //不带参数

    second.block2 = ^(){

        NSLog(@"123456");

    };

4.调用block

self.block(@“11”);

self.block(text1.text,text2.text);

self.block2();



.作为参数

 返回值(^(参数1类型  value1,参数2类型 value2 ……)

 返回值(^(参数1类型 ,参数2类型 ……)

 eg:

 1.-(void)useAblock:(void(^)(BOOL value))block

 也可以写成

 2.-(void)useAblock:(void(^)(BOOL))block

 3.调用参数是block的函数

 eg:

 [self useAblock:^(BOOL value) {

 

 }];


//例子

 - (void)viewDidLoad {

 [super viewDidLoad];

 


 类似于C语言中得函数指针

 int (*pfun)(int x, int y);

 




//声明一个返回值为void型,参数为BOOL型的block变量,变量名是ablock

void(^ablock)(BOOL);

//实现一个block,并赋值给同类型的一个ablock这个变量

ablock = ^(BOOL value){

    if(value)

    {

        NSLog(@"我是被调用的block");

    }

};

//把一个block变量ablock作为一个参数

[self useAblock:ablock];




//用一个返回值为void型、参数为BOOLblock变量:needReturn去接收一个函数的返回值,该函数的返回值为同类型的block

void(^needReturn)(BOOL) = [self returnAblock];

if (needReturn) {

    //调用block

    needReturn(YES);

}

}

-(void)useAblock:(void(^)(BOOL))block

{

    if (block) {

        //调用block

        block(YES);

    }

}

-(void(^)(BOOL))returnAblock

{

    //“ =”之前是声明一个block变量,“ =”之后是实现一个block

    void(^returnBlock)(BOOL) = ^(BOOL value){

        NSLog(@"我是用来返回的block");

    };

    return returnBlock;

}


Block:

1.Block封装了一段代码,可以在任何时候执行

2.Block可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值

3.官方建议多用Block。在多线程,异步任务,集合遍历,集合排序,动画转场用的很多


函数可以保存代码,但是在程序运行之前就已经写死了。


block用来保存一段代码

block的标志:^


block跟函数很像:

1.可以保存代码

2.有返回值

3.有形参

4.调用方式一样



第一种:

没有返回值,没有形参的block

//定义block变量      

void (^myBlock)() = ^{

NSLog(@“……………”);

};

其中void返回值类型,myBlock变量名,后面括号里是形参

//利用block变量调用block内部的代码

myBlock();


第二种:

有返回值,有形参的block

int (^sumBlock)(int, int) = ^(int a, int b){

return a+b;

};

int c = sumBlock(2,5);


第三种:

没有返回值,有形参的block

//用一个block输出n条横线

void (^lineBlock)(int) = ^(int n){

NSLog(@“————————”);

};

lineBlock(5);





使用typedef定义block类型    //以后就可以利用MyBlock这种类型来定义block变量

typedef int (^MyBlock)(int ,int);


int main ()

{

  MyBlock minusBlock = ^(int a, int b) {

return a - b;

}

}



block访问外面变量:

void test ()

{

int a = 10;

__block int b = 20;

void (^block)() = ^{

//block内部可以访问外面的变量

NSLog(@“%@”,a);

//默认情况下,block内部不能修改外面的局部变量

//但是给局部变量加上 __block关键字之后,这个局部变量就可以在block内部修改

b = 32;

};

block();

}



block要掌握的东西

1.如何定义block变量

int (^sumBlock)(int, int);

void (^myBlock)();

2.如何利用block封装代码

^(int a,int b){

  return a - b;

};

^(){

  NSLog(@“……”);

};

^{

 NSLog(@“……”);

}

3.block访问外面变量(见上)

4.使用typedef定义block类型(见上)






函数指针?(了解)

int sum(int a, int b)

{

 return a+b;

}


int main ()

{//指针函数的指针

 int (*p)(int , int) = sum;

int d = p (4,6);

}


写出上面代码的Block的定义。

  typedef void(^animations) (void);

  typedef void(^completion) (BOOL finished);



 试着使用+ beginAnimations:context:以及上述Block的定义,写出一个可以完成

  + (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);操作的函数执行部分

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值