block
来源:互联网 发布:大型投资理财网站源码 编辑:程序博客网 时间:2024/06/08 08:41
/*
如果【block内部】使用【外部声明的强引用】访问【对象A】,那么【block内部】会自动产生一个【强引用】指向【对象A】
如果【block内部】使用【外部声明的弱引用】访问【对象A】,那么【block内部】会自动产生一个【弱引用】指向【对象A】
*/
1.指向函数的指针
void printPodium()
{
printf("Chris Froome\n");
printf("Richie Porte\n");
printf("Fabio Aru\n");
}
int main(int argc,constchar * argv[])
{
// (*podiumP)代表podiumP是一个指向函数的指针
// podiumP :代表指针变量的名称,区分
// (*podiumP) :代表将来指向一个函数
// void : 代表将来指向的函数没有返回值
// () : 代表将来指向的函数没有参数
void (*podiumP) ();
podiumP = printPodium;
printPodium();
}
///////
int sum(int value1,int value2)
{
return value1 + value2;
}
int minus(int value1,int value2)
{
return value1 - value2;
}
typedef int (*calculte)(int,int);
// 注意:利用typedef给block起别名,和指向函数的指针一样, block变量的名称就是别名
typedef int (^calculteBlock)(int ,int);
返回值类型 (^block的变量名)(形参类型列表) = ^(形参列表) {
// block代码
};
block的变量名(实参列表);
int main(int argc,constchar * argv[]) {
/*
// int (*sumP)(int, int);
// sumP = sum;
calculte sumP = sum;
NSLog(@"sum = %i", sumP(20, 10));
// int (*minusP)(int, int);
// minusP = minus;
calculte minusP = minus;
NSLog(@"minus = %i", minusP(20, 10));
*/
// int (^sumBlock)(int , int );
calculteBlock sumBlock = ^(int value1,int value2){
return value1 + value2;
};
NSLog(@"sum = %i", sumBlock(20,10));
// int (^minusBlock)(int , int);
calculteBlock minusBlock = ^(int value1,int value2){
return value1 - value2;
};
NSLog(@"minus = %i", minusBlock(20,10));
return 0;
}
///////int main(int argc,constchar * argv[]) {
// 1.block中可以访问外面的变量
/*
int a = 10;
void (^myBlock)() = ^{
NSLog(@"a = %i", a);
};
myBlock();
int a=10;
void( ^myBlock)()=^{
Nslog(@"a= %i",a);
}
myBlock();
*/
// 2.block中可以定义和外界同名的变量,并且如果在block中定义了和外界同名的变量,在block中访问的是block中的变量
/*
int a = 10;
void (^myBlock)() = ^{
int a = 20;
NSLog(@"a = %i", a);
};
myBlock();
*/
// 3.默认情况下,不可以在block中修改外界变量的值
// 因为block中的变量和外界的变量并不是同一个变量
// 如果block中访问到了外界的变量, block会将外界的变量拷贝一份到堆内存中
// 因为block中使用的外界变量是copy的,所以在调用之前修改外界变量的值,不会影响到block中copy的值
/*
int a = 10;
NSLog(@"&a = %p", &a);
void (^myBlock)() = ^{
// a = 50;
NSLog(@"&a = %p", &a);
NSLog(@"a = %i", a);
};
a = 20;
myBlock();
*/
/*
// 如果想在block中修改外界变量的值,必须在外界变量前面加上__block
// 如果在block中修改了外界变量的值,会影响到外界变量的值
__block int a = 10;
NSLog(@"&a = %p", &a);
void (^myBlock)() = ^{
a = 50;
NSLog(@"&a = %p", &a);
NSLog(@"a = %i", a);
};
myBlock();
NSLog(@"a = %i", a);
*/
/*
// int a = 10; // 如果没有添加__block是值传递
// void (*myBlock)() = &__main_block_impl_0( __main_block_func_0, &__main_block_desc_0_DATA, a);
// (myBlock)->FuncPtr)(myBlock);
// 为什么不加__block不能在block中修改外界变量的值
int a = 10;
void (^myBlock)() = ^{
// a = 10;
NSLog(@"a = %i", a);
};
myBlock();
*/
/*
// a = 10; // 如果加上__block之后就是地址传递,所以可以在block中修改外界变量的值
// void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344);
// 为什么加了__block就可以在block中修改外界变量的值
__block int a = 10;
void (^myBlock)() = ^{
a = 10;
NSLog(@"a = %i", a);
};
myBlock();
*/
// block是存储在堆中还是栈中
// 默认情况下block存储在栈中,如果对block进行一个copy操作, block会转移到堆中
// 如果block在栈中, block中访问了外界的对象,那么不会对对象进行retain操作
// 但是如果block在堆中, block中访问了外界的对象,那么会对外界的对象进行一次retain
// 如果在block中访问了外界的对象,一定要给对象加上__block,只要加上了__block,哪怕block在堆中,也不会对外界的对象进行retain
// 如果是在ARC开发中就需要在前面加上__weak
__block Person *p = [[Personalloc]init];// 1
// 如果在做iOS开发时,在ARC中不这样写容易导致循环引用
// Person *p = [[Person alloc] init];
// __weak Person *weakP = p;
NSLog(@"retainCount = %lu", [pretainCount]);
void (^myBlock)() = ^{
NSLog(@"p = %@", p);// 2
// NSLog(@"p = %p", weakP);
NSLog(@"block retainCount = %lu", [pretainCount]);
};
Block_copy(myBlock);
myBlock();
[p release]; // 1
return 0;
}
//////////
// 2.可以使用copy保存block,这样可以保住block中使用的外界对象的命
/*
// 避免以后调用block的时候,外界的对象已经释放了
Dog *d = [[Dog alloc] init]; // 1
NSLog(@"retainCount = %lu", [d retainCount]);
Person *p = [[Person alloc] init];
p.pBlock = ^{
// 2
NSLog(@"%@", d);
};
NSLog(@"retainCount = %lu", [d retainCount]); // 2
// 如果狗在调用block之前释放了,那么程序就会崩溃
[d release]; // 1
p.pBlock();
[p release];
*/
// 3.注意点: copy block之后引发循环引用
// 如果对象中的block又用到了对象自己,那么为了避免内存泄露,应该将对象修饰为__block
__block Person *p = [[Personalloc]init];// 1
p.name = @"lnj";
NSLog(@"retainCount = %lu", [pretainCount]);
p.pBlock = ^{
NSLog(@"name = %@", p.name);// 2
};
NSLog(@"retainCount = %lu", [pretainCount]);
p.pBlock();
[p release]; // 1
// 1.如果没有对block进行copy操作,block就存储于栈空间
// 2.如果对block进行copy操作,block就存储于堆空间
// 3.如果block存储于栈空间,不会对block内部所用到的对象产生强引用
// 4.如果block存储于堆空间,就会对block内部所用到的对象产生强引用
//////////
block循环引用
// 定义一个weakSelf,self的弱指针
// typeof:会自动识别参数的类型
__weak typeof(self) weakSelf =self;
// 注意:
// block尽量少使用self,容易造成循环引用
// block尽量少使用下划线(_)直接访问成员属性
// block机制:block会把里面代码块的所有强指针都强引用
item.operationBlock = ^(NSIndexPath *indexPath){
// 点击cell就会调用
// self:强指针
// self:间接强引用block
// 获取点击的cell
// UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UITableViewCell *cell = [weakSelf.tableViewcellForRowAtIndexPath:indexPath];
// 弹出键盘
UITextField *textField = [[UITextFieldalloc]init];
[textField becomeFirstResponder];
[cell addSubview:textField];
};
- Block
- block
- Block
- block
- block
- block
- block
- block
- block
- Block
- block
- Block
- Block
- Block
- Block
- block
- Block
- block
- 2016 Multi-University Training Contest 2 Acperience
- 动脑筋 + 动脑筋 + 动脑筋 + …… + 动脑筋 = 科学画报
- android开发中常用的快捷键
- HTTP请求与响应码
- Hbuider hybrid app开发之地图位置信息操作方法
- block
- 录入学生成绩并写出到磁盘文件
- sqlserver查看死锁
- POJ 2251Dungeon Master
- JAVA发送HTTP请求,并接受返回内容
- css3 box-sizing属性
- Hdu 5744 Keep On Movin【思维】
- iOS开发-自定义控件的方式及注意
- ffmpeg使用参数的中文说明