您的位置:首页 > 移动开发 > IOS开发

iOS关于block使用的注意和探讨

2015-07-03 14:05 337 查看
没有过多的研究block ,最近几天,有人提到了 使用block 有可能会出现内存泄露的问题,这个问题确实存在,如果不注意的话。

现在目前block内存泄露的原因,目前自己弄出了二个原因,一个是出现是引用循环,二就是 对象未被销毁。

引用循环这个问题还是比较的好控制,在block里面加弱引用,或者是用__block,要看具体情况。我主要是说一下第二点,我也看了 人家的博客仔细研究了一下

感觉别人没有说对,自己经过实践,总结了一下还有一些不明白的。

创建3个viewcontroller viewcontroller01 viewcontroller02 viewcontroller03

viewController01 跳转viewcontroller02 viewcontroller02 跳转到 viewcontroller03

我自己自定义了一个 button 主要是要调用delloc 的方法

viewcontroller02

@interface ViewController ()
{
UIButton *button;
// __block ImButton * im;
}
//自定义 button
@property (nonatomic,strong)ImButton *im;

@end

@implementation ViewController
@synthesize im;

- (void)viewDidLoad {
[superviewDidLoad];
//一个返回按钮一个 进入下个controller的按钮
button = [[UIButtonalloc]initWithFrame:CGRectMake(100,200,
50,50)];
button.backgroundColor = [UIColorgrayColor];
self.view.backgroundColor = [UIColorwhiteColor];
[self.view
addSubview:button];

[buttonaddTarget:selfaction:@selector(buttonAction)forControlEvents:UIControlEventTouchUpInside];

im = [[ImButtonalloc]initWithFrame:CGRectMake(100,100,
50,50)];

im.backgroundColor=[UIColorblackColor];
[imaddTarget:selfaction:@selector(rele)forControlEvents:UIControlEventTouchUpInside];
[self.view
addSubview:im];

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

-(void)rele{

[selfdismissViewControllerAnimated:YEScompletion:nil];
}

-(void)buttonAction{

ViewController03 *viewcontroller03 = [[ViewController03 alloc]init];
//打印引用计数
NSLog(@"1------%p---%ld",im,CFGetRetainCount((__bridgeCFTypeRef)im));
[viewcontroller03 setBlock:^{
im.backgroundColor = [UIColorblueColor];
}];
[selfpresentViewController:viewcontroller03 animated:YEScompletion:nil];
}

然后就是viewcontroller03

这是一种会出现内存泄露的情况 原因还在研究中

//就是这样定义block 会出现很坑人的情况就是 会出现viewcontroller2中的那个button不会释放掉 而且viewcontroller2 也不会释放掉

我尝试几种方法

void (^myblock)();
@implementation ViewController03
-(void)setBlock:(void(^)())block{
myblock = block;
}

- (void)viewDidLoad {
[superviewDidLoad];
}

- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonAction:(id)sender {
myblock();
[selfdismissViewControllerAnimated:YEScompletion:nil];

}
-(void)dealloc{
NSLog(@"delloc%@",self.class);
}

//解决方案一

-(void)buttonAction{

ViewController02 *viewcontroller02 = [[ViewController02alloc]init];
NSLog(@"1------%p---%ld",im,CFGetRetainCount((__bridgeCFTypeRef)im));
__weak UIButton *imbutton =im;
//__block UIButton *imbutton = im; //如果使用__block 需要将imbutton 变为空 如果不为nil会导致button引用计数加一并且viewcontroller02 退出后 button不会被释放 viewcontroller02 会被释放 我擦 好神奇

[viewcontroller02 setBlock:^{
imbutton.backgroundColor = [UIColorblueColor];
// imbutton = nil;
}];
[selfpresentViewController:viewcontroller02
animated:YEScompletion:nil];
}

//解决方案二 这个是我最不能理解的了 让我不得不去研究变量,属性这些东西了

viewcontroller03.h的定义block

typedef void(^Myblock)();

@interface ViewController02 :
UIViewController

-(void)setBlock:(void(^)())block;

//设置成为一个属性 然后viewcontroller02 和最上面的代码一样 这样居然不会内存泄露 有的时候我很难理解。这也是需要去研究和 思考的问题
@property (nonatomic,strong)Myblock myblock;

在开发的过程中还有很多这种自己感觉很神奇的情况,有的时候现在的知识储备难以去解释这是为什么,但是很多时候要养成一些好的习惯
每个类里面最好都写上dealloc,里面可以什么都没有,遇到有block的最好在dealloc里面输出一些信息,看是否是被释放了。这样还是会比较的保险一些
目前就是研究了这些 。
经过研究 发现这个跟变量的生命周期有关系,这样定义应该属于全局变量,一般来说不这么干,定义到@implementation里面也不行也不推荐这么干,主要现在用的是objective-c

不是。生命周期当然不会随着viewcontroller的消失而消失,也就出现了这种情况,这就是为什么不行的原因,全局变量block没有结束,所以里面的 im变量引用计数无法减一,导致了 无法释放。所以在编程的过程中最好不要这么干,很容易出问题,也给我们这些程序员提了个醒,博客很多有可能他是错的需要你去实践,去思考。基础也是非常的关键,就说这个问题其实也非常的好理解就说脑袋短路了 开始没有想到那里去,说白了还是基础功不扎实,还有就是原来压根没有那么用过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: