Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

避免block的循环引用

$
0
0

前言

循环引用:

 *对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:

 *对于ARC下
 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1
eg.:

内存泄露例子:

当在block内部使用成员变量的时候。那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。

修正

- (void)addGroup0{
    //        1.弱引用成员变量或者控制器本事,防止block的循环引用


    __weak HLShareViewController *share = self;
    HLSettingItemGroupModel *group = [[HLSettingItemGroupModel alloc]init];
    HLSettingArrowItemModel *sinaItem = [HLSettingArrowItemModel itemModelWithTitle:@"新浪分享" icon:@"WeiboSina" destVCClass:nil];
    HLSettingArrowItemModel *smsItem = [HLSettingArrowItemModel itemModelWithTitle:@"短信分享" icon:@"SmsShare" destVCClass:nil];
    //短信分享
    [smsItem setOptionBlock:^{

        //方式一:不能指定短信内容,不能自动回到原应用
//        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://188740548"]];
        //方式二 :MessageUI框架--modal方法进行控制器间的切换
        MFMessageComposeViewController *vc= [[MFMessageComposeViewController alloc]init];
        // 设置短信内容
        vc.body = @"lydia,中心藏之, 何以忘之";
        // 设置收件人列表
        vc.recipients = @[@"1887405", @"487"];
        // 设置代理
        vc.messageComposeDelegate = share;
        // 显示控制器
        if (vc) {
            [share presentViewController:vc animated:YES completion:nil];//真机调试
        }
    }];
#define weakSelf(weakSelf)  __weak __typeof(&*self)weakSelf = self;

block的好处:运行时才定义

block的定义格式

这里写图片描述

//block 的作用:保存一段代码,到恰当的时候调用,很多时候block是代理的一种优化方案
/*

 0.block的介绍

 Blocks可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针很类似,但是有区别:blocks是inline的,并且它对局部变量是只读的。

 1、定义

 <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {

 <#statements#>



};

 2.声明

 typedef <#returnType#>(^<#name#>)(<#arguments#>);



 3、内存管理--block本身是像对象一样可以retain,和release

 1)block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。

 他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃

 2)解决这个问题的方法就是在创建完block的时候需要调用copy的方法。copy会把block从栈上移动到堆上,那么就可以在其他地方使用这个block了

 4、循环引用

 *对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象:

 *对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对象。原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该变量的引用计数+1//定义weakself,方便在block中使用self
#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;

    eg.:

  __weak WebViewController *blockSelf = self; // 声明对象赋值self,使用__weak修饰,目的是在block内部使用的时候不会造成控制器引用计数+1

 内存泄露例子:

 当在block内部使用成员变量的时候。那么block是会对内部的对象进行一次retain。也就是说,self会被retain一次。当self释放的时候,需要block释放后才会对self进行释放,但是block的释放又需要等self的dealloc中才会释放。如此一来变形成了循环引用,导致内存泄露。

 5、blocks 访问权限

 1)blocks可以访问局部变量a,但是不能修改。

 原因是在编译期间确定的,编译器编译的时候把a的值复制到block作为一个新变量(假设是a‘ = 10),此时a'和a是没有关系的。

 2)如果要修改就要加关键字:__block或者static

 6、block调用就像调用函数一样 
//执行block
    if (self.block) {
        self.block(self.selectedBtn.tag);
    }
 7、block的定义
 //定义block,通知导航控制器切换控制器

 [tabBar setBlock:^(int index){

 [self setSelectedIndex:index];//切换控制器

 }];

 //    [tabBar.block copy];

 */

typedef void(^HLTabBarBlock)(int selectIndex);

@interface HLTabBar : UIView

@property (nonatomic,copy) HLTabBarBlock block;//--通知TabBar切换控制器
作者:u011018979 发表于2017/7/3 16:01:43 原文链接
阅读:70 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>