您的位置:首页 > 其它

代理block(一)

2016-02-25 21:57 330 查看
最重要的是先判断清楚谁是委托方,谁是代理方。委托方和代理方其实是相对的。谁让谁做什么,谁需要谁做什么,谁想做什么需要告诉谁

代理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标志,MyBlock是block的变量名,后面括号是传入的参数
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型、参数为BOOL的block变量: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);操作的函数执行部分
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: