在管理完框架内存泄漏的主题素材后,双向引用导致的IOS内部存款和储蓄器泄漏(中)-

折腾二:将宏定义指向三个函数

比方说那样定义:

#define sagit [Sagit share].Layout

下一场跑到Sagit那么些类里定义一个UIView* Layout属性,举个例子那样:

公海手机版 1

然后,就是在1壹基类(STController或S电视iew)开始化时,将自作者的self.baseView赋值给它。

PS:baseView是对UIView和UIViewController扩充的二天质量,都指向View。

比如:

公海手机版 2

看起来有点成效,但是,要用那种情势,还得商量的更完美:

1:架框中每个STView都是baseView。

2:STView可以无限嵌套STView。

3:因此:在STView被初时化时,设置它为baseView,加载完后,如果STView有父的STView,交还控制权,(这里就涉及到嵌套的控制流程,如果各个子View是异步加载,那就悲催了)。

4:没有继承自STView的情况呢,怎么拦截View的开始和结束呢?(Sagit已经慢慢弱化基类的功能,多数功能都是在原生的上做扩展,所以不用STView,很多功能也可以正常使用)

好啊,写这么多,正是说那个点子是能够的,但必须思虑的更加细致诸多些!!!!

还要以此方法,只是逃避了self,self仍旧不一样意被存在。

就此,那一个主意,先暂放,看看有未有点子,打破self的轮回引用先。

前言:

在管理完框架内部存款和储蓄器泄漏的主题素材后,见上篇:讲述Sagit.Framework消除:双向引用导致的IOS内部存储器泄漏(中)-
IOS鲜为人知的Bug

意识事情代码有一个地方的内部存款和储蓄器没释放,原因很也大概:

公海手机版 3

在block里用到了self,形成双向引用,然后就开头企图怎么管理那一个标题。

好端端则合计,正是改代码,block不要用到self,或只用self的弱引用。

只是框架那里尤其,有3个特好用的各个,STLastXXX种类,是用宏定义的,而且该宏指向了self。

这么好用的STLastXXXX宏定义体系,小编期望它能够不受限制的随地使用。

于是乎从头折腾之路:

前言:

在管理完框架内部存款和储蓄器泄漏的难题后,见上篇:讲述Sagit.Framework消除:双向引用导致的IOS内部存款和储蓄器泄漏(中)-
IOS无人问津的Bug

发觉专门的职业代码有二个地方的内部存款和储蓄器没释放,原因很也轻便:

公海手机版 4

在block里用到了self,变成双向引用,然后就初阶讨论怎么管理这些标题。

好端端则合计,便是改代码,block不要用到self,或只用self的弱引用。

只是框架那Ritter别,有三个特好用的层层,STLastXXX种类,是用宏定义的,而且该宏指向了self。

那样好用的STLastXXXX宏定义种类,作者盼望它能够不受限制的三街陆巷使用。

于是早先折腾之路:

折腾壹:在代码中重新定义宏?

上边的代码,说白了正是利用了self,我们看一下宏定义:

公海手机版 5

万般的做法,遭受block,都陪伴有WeakSelf那东东,像这么:

公海手机版 6

STWeakSelf的默料定义:

//block块中用的引用
#define STWeakSelf __weak typeof(self) selfWeak = self;__weak typeof(selfWeak) this = selfWeak;
#define STWeakObj(o) __weak typeof(o) o##Weak = o;
#define STStrongObj(o) __strong typeof(o) o = o##Weak;

轻巧,宏定义就是编绎期的文字替换游戏,假诺笔者在block里的率先行代码,重新定义sagit这么些宏会如何? 

比如那样定义:

公海手机版 7

下一场这么使用:

公海手机版 8

如上所述是自个儿想多,编绎都过不去。

终极:作弄叁个IOS的另1个坑,又是机密的dealloc方法:

上一篇作品,讲到,假使对UIView增添了dealloc那措施,引发的命案是:

导航栏:二回后退就闪退。

这一篇,又被本人开采,假若对UIViewController扩大dealloc这一个方法,引发的命案:

UIAlertView:当alertViewStyle设置为带文本框时就闪退。

给大家上多个图,先把dealloc展开:

公海手机版 9

然后运营的效果:

公海手机版 10

坑吧,幸好有上一次的经历,赶紧新建了3个品种,然后用代码排除法,最后照旧排到dealloc那里来。

来看那小说的校友,你们又能够去忽悠同事了。

煎熬贰:将宏定义指向一个函数

举例那样定义:

#define sagit [Sagit share].Layout

下一场跑到Sagit这么些类里定义3个UIView*公海手机版, Layout属性,比方那样:

公海手机版 11

然后,正是在相继基类(STController或S电视iew)初叶化时,将本身的self.baseView赋值给它。

PS:baseView是对UIView和UIViewController扩张的一本质量,都指向View。

比如:

公海手机版 12

看起来有点功效,可是,要用那种艺术,还得想想的更健全:

1:架框中每个STView都是baseView。

2:STView可以无限嵌套STView。

3:因此:在STView被初时化时,设置它为baseView,加载完后,如果STView有父的STView,交还控制权,(这里就涉及到嵌套的控制流程,如果各个子View是异步加载,那就悲催了)。

4:没有继承自STView的情况呢,怎么拦截View的开始和结束呢?(Sagit已经慢慢弱化基类的功能,多数功能都是在原生的上做扩展,所以不用STView,很多功能也可以正常使用)

好吧,写那样多,正是说这些办法是足以的,但不能够不思索的更仔细很多些!!!!

还要以此方式,只是逃避了self,self照旧差别意被存在。

故而,那个格局,先暂放,看看有未有点子,打破self的轮回引用先。

末尾:吐槽3个IOS的另三个坑,又是潜在的dealloc方法:

上一篇文章,讲到,借使对UIView扩展了dealloc这格局,引发的谋杀案是:

导航栏:三回后退就闪退。

那1篇,又被作者意识,假使对UIViewController扩展dealloc这几个格局,引发的命案:

UIAlertView:当alertViewStyle设置为带文本框时就闪退。

给大伙上一个图,先把dealloc张开:

公海手机版 13

然后运转的遵守:

公海手机版 14

坑吧,幸而有上一遍的阅历,赶紧新建了一个门类,然后用代码排除法,最后依然排到dealloc那里来。

见状那小说的同窗,你们又有啥不可去忽悠同事了。

折腾2:将宏定义指向1个函数

比方说那样定义:

#define sagit [Sagit share].Layout

下一场跑到Sagit那一个类里定义三个UIView* Layout属性,举个例子这样:

公海手机版 15

下一场,便是在依次基类(STController或S电视机iew)初始化时,将自家的self.baseView赋值给它。

PS:baseView是对UIView和UIViewController扩张的二特性质,都指向View。

比如:

公海手机版 16

看起来有点成效,不过,要用那种格局,还得想想的更周到:

1:架框中每个STView都是baseView。

2:STView可以无限嵌套STView。

3:因此:在STView被初时化时,设置它为baseView,加载完后,如果STView有父的STView,交还控制权,(这里就涉及到嵌套的控制流程,如果各个子View是异步加载,那就悲催了)。

4:没有继承自STView的情况呢,怎么拦截View的开始和结束呢?(Sagit已经慢慢弱化基类的功能,多数功能都是在原生的上做扩展,所以不用STView,很多功能也可以正常使用)

可以吗,写那样多,正是说这几个法子是足以的,但不可能不思量的更周全许多些!!!!

再正是以此措施,只是逃避了self,self如故不容许被存在。

故此,这几个点子,先暂放,看看有未有点子,打破self的轮回引用先。

要是你想将四个block持久化,先copy一下,不然你会死的相当的惨。

好呢,让它们互相强引用吧,剩下的事,正是什么人来当以此第2方,以及怎么化解那层关系!!!

于是,到导航栏后退事件中,拦截,并做销毁职业:

@implementation UINavigationController (ST)

#pragma mark NavigationBar 的协议,这里触发
// fuck shouldPopItem 方法存在时,只会触发导航栏后退,界面视图却不后退。
//- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item  // same as push methods
//{
////    //重设上一个Controller的导航(不然在二次Push后再Pop会Crash)
////    NSInteger count=self.viewControllers.count;
////    if(count>0)//发现这里返回的viewControllers,已经是移掉了当前的Controller后剩下的。
////    {
////        UIViewController *preController=self.viewControllers[count-1];//获取上一个控制器
////        if([preController needNavBar])
////        {
////            [preController reSetNav:self];
////        }
////    }
////
//    return YES;
//}
//返回到当前页面
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
//    if(navigationBar!=nil && [navigationBar.lastSubView isKindOfClass:[UIButton class]])
//    {
//       // [navigationBar.lastSubView height:0];//取消自定义复盖的UIButton
//    }
    NSInteger count=self.viewControllers.count;
    if(count>0)
    {
        UIViewController *current=self.viewControllers[count-1];
        self.navigationBar.hidden=![current needNavBar];
        if(self.tabBarController!=nil)
        {
            self.tabBarController.tabBar.hidden=![current needTabBar];
        }
        //检测上一个控制器有没有释放
        UIViewController *nextController=current.nextController;
        if(nextController!=nil)
        {
            [nextController dispose];
            nextController=nil;
        }
    }
}
-(void)dealloc
{
    NSLog(@"UINavigationController relase -> %@", [self class]);
}

Sagit框架为:每种view和controller扩张了dispose方法,里面清掉键值对,等于把block置为nil,解除了关乎。

而外导航后退,还须求拦截多贰个事变,正是presentViewController的轩然大波跳转时,也急需检查评定并销毁。

抓牢那两步之后,现在就能够轻巧的在block里写self了,爱引用就引述了,反正传说的终极,都有三个旁人来终结

并且强引用有二个便宜:

1:再也用不上WeakSelf这种定义了。

2:由于是强引用,就不用去管:里面还要套个StrongSelf,去避开多线程时,self可能被移除时带来的闪退问题。

假使您想将二个block持久化,先copy一下,不然你会死的相当惨。

行吗,让它们相互强引用吧,剩下的事,就是什么人来当以此第3方,以及怎么消除那层关系!!!

于是,到导航栏后退事件中,拦截,并做销毁专门的工作:

@implementation UINavigationController (ST)

#pragma mark NavigationBar 的协议,这里触发
// fuck shouldPopItem 方法存在时,只会触发导航栏后退,界面视图却不后退。
//- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item  // same as push methods
//{
////    //重设上一个Controller的导航(不然在二次Push后再Pop会Crash)
////    NSInteger count=self.viewControllers.count;
////    if(count>0)//发现这里返回的viewControllers,已经是移掉了当前的Controller后剩下的。
////    {
////        UIViewController *preController=self.viewControllers[count-1];//获取上一个控制器
////        if([preController needNavBar])
////        {
////            [preController reSetNav:self];
////        }
////    }
////
//    return YES;
//}
//返回到当前页面
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
//    if(navigationBar!=nil && [navigationBar.lastSubView isKindOfClass:[UIButton class]])
//    {
//       // [navigationBar.lastSubView height:0];//取消自定义复盖的UIButton
//    }
    NSInteger count=self.viewControllers.count;
    if(count>0)
    {
        UIViewController *current=self.viewControllers[count-1];
        self.navigationBar.hidden=![current needNavBar];
        if(self.tabBarController!=nil)
        {
            self.tabBarController.tabBar.hidden=![current needTabBar];
        }
        //检测上一个控制器有没有释放
        UIViewController *nextController=current.nextController;
        if(nextController!=nil)
        {
            [nextController dispose];
            nextController=nil;
        }
    }
}
-(void)dealloc
{
    NSLog(@"UINavigationController relase -> %@", [self class]);
}

Sagit框架为:每一个view和controller扩大了dispose方法,里面清掉键值对,等于把block置为nil,解除了关系。

而外导航后退,还亟需拦截多三个事件,便是presentViewController的事件跳转时,也亟需检验并销毁。

盘活那两步之后,今后就能够轻便的在block里写self了,爱引用就引述了,反正轶事的末尾,都有两个别人来了却

并且强引用有二个便宜:

1:再也用不上WeakSelf这种定义了。

2:由于是强引用,就不用去管:里面还要套个StrongSelf,去避开多线程时,self可能被移除时带来的闪退问题。

如若第二方对block是弱引用呢?

为了这几个实验,小编新建了二个品类,然后在那个体系上,试了总体2四钟头:

实验进程未有赢得的想要的结果,但明白block的法则,和剖断本身的逻辑误区。

试验的收获的知识后边再享受,那里先一连:

由于这里addCell,必须始终存活,因为你不知道什么时候,可能又要UITableView的reloadData一下。

所以,addCell这个block,必须被强引用,而且生命周期得和UITableView一致。

所以,要打破这个核心,还是得有第三方行为事件来触发破除关系,故事就转变成为:由self去移除第三方。

如果一定义要由某个事件来触发解除关系,那么第三方也没存在的必要了。

因为正常A和B互相引用无解,是指他们互相无解,但只要有第三者存在,对其中一个置nil就解了。

最终的末段,框架的代码是那样的:

-(AddTableCell)addCell
{
    return [self key:@"addCell"];
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
        addCell=[addCell copy];
        [self key:@"addCell" value:addCell];
    }
    else
    {
        [self.keyValue remove:@"addCell"];
    }
}

1如既往是用强引用来存档block,那里有一个注意事项:

煎熬一:在代码中另行定义宏?

上边的代码,说白了正是选拔了self,大家看一下宏定义:

公海手机版 17

平凡的做法,蒙受block,都陪伴有WeakSelf那东东,像这么:

公海手机版 18

STWeakSelf的默料定义:

//block块中用的引用
#define STWeakSelf __weak typeof(self) selfWeak = self;__weak typeof(selfWeak) this = selfWeak;
#define STWeakObj(o) __weak typeof(o) o##Weak = o;
#define STStrongObj(o) __strong typeof(o) o = o##Weak;

轻便,宏定义正是编绎期的文字替换游戏,假设小编在block里的率先行代码,重新定义sagit那个宏会怎么样? 

举例说那样定义:

公海手机版 19

下一场这么使用:

公海手机版 20

由此看来是自己想多,编绎都短路。

总结:

完整折腾完内部存款和储蓄器释放难题后,Sagit框架也急速了众多,可能是错觉。

IT连的创业的也在持续,招待我们持续关切,多谢!

总结:

总体折腾完内部存储器释放难题后,Sagit框架也神速了不少,大概是错觉。

IT连的创业的也在持续,应接我们持续关心,多谢!

煎熬3:思考怎么着打破block和self的双向引用?

 block和self,互相的强引用,要打破它,总得有壹方要示弱。

既然block中要允许self中存,就意味着block对self必然是强引用,辣么就只可以思虑,要是让self对block只能是弱引用了,大概没有引用!

先来看框架的一段代码:

公海手机版 21

被圈起来的代码,达成的下列图中圈起来的效劳:

公海手机版 22

对此Sagit中,落成表格的代码是或不是觉的很简短,然则教程还没写,那里提前败露了。

抑或说珍视,注重为UITableView中,扩充了三个性能AddCell的Block属性,见代码如下:

@interface UITableView(ST)

#pragma mark 核心扩展
typedef void(^AddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^DelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef void(^AfterTableReloadData)(UITableView *tableView);
//!用于为Table追加每一行的Cell
@property (nonatomic,copy) AddTableCell addCell;
//!用于为Table移除行的Cell
@property (nonatomic,copy) DelTableCell delCell;
//!用于为Table reloadData 加载完数据后触发
@property (nonatomic,copy) AfterTableReloadData afterReload;
//!获取Table的数据源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!设置Table的数据源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;

固然如此定义了1个addCell属性,可是怎么具备,还得看getter和setter怎么得以落成:

@implementation UITableView(ST)

#pragma mark 核心扩展

-(AddTableCell)addCell
{
    //从第三方持有返回
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
         //第三方持有addCell
    }
    else
    {

    }
}

比如那里,把存档addCell这些block存到和UITableView非亲非故的地点去了?

用一个第1方持有block,只要这些第一方不和和self发生径直关联,那么相应就不会有标题。

引用关系就改成:

第三方:强引用=》block

block:强引用=》self

此间的放走关系,第一方活着,就不会放出block,block活着,就不会放出self。

由此结论:照旧不自由。

也正是说,一顿代码写下去,固然破除了关系,但要么没释放。

设若第3方对block是弱引用呢?

为了这么些试验,笔者新建了三个类型,然后在这几个种类上,试了整个二4刻钟:

尝试进程并未有到手的想要的结果,但领悟block的规律,和判定自个儿的逻辑误区。

试验的获得的学问后边再享受,那里先一连:

由于这里addCell,必须始终存活,因为你不知道什么时候,可能又要UITableView的reloadData一下。

所以,addCell这个block,必须被强引用,而且生命周期得和UITableView一致。

所以,要打破这个核心,还是得有第三方行为事件来触发破除关系,故事就转变成为:由self去移除第三方。

如果一定义要由某个事件来触发解除关系,那么第三方也没存在的必要了。

因为正常A和B互相引用无解,是指他们互相无解,但只要有第三者存在,对其中一个置nil就解了。

终极的末尾,框架的代码是那样的:

-(AddTableCell)addCell
{
    return [self key:@"addCell"];
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
        addCell=[addCell copy];
        [self key:@"addCell" value:addCell];
    }
    else
    {
        [self.keyValue remove:@"addCell"];
    }
}

还是是用强引用来存档block,那里有三个注意事项:

煎熬三:思索什么打破block和self的双向引用?

 block和self,相互的强引用,要打破它,总得有一方要示弱。

既然block中要允许self中存,就代表block对self必然是强引用,辣么就只可以考虑,假诺让self对block只可以是弱引用了,只怕未有引用!

先来看框架的一段代码:

公海手机版 23

被圈起来的代码,完毕的下列图中圈起来的法力:

公海手机版 24

对此Sagit中,落成表格的代码是或不是觉的很轻便,不过教程还没写,那里提前走漏了。

抑或说敬服,注重为UITableView中,扩大了一本质量AddCell的Block属性,见代码如下:

@interface UITableView(ST)

#pragma mark 核心扩展
typedef void(^AddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^DelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef void(^AfterTableReloadData)(UITableView *tableView);
//!用于为Table追加每一行的Cell
@property (nonatomic,copy) AddTableCell addCell;
//!用于为Table移除行的Cell
@property (nonatomic,copy) DelTableCell delCell;
//!用于为Table reloadData 加载完数据后触发
@property (nonatomic,copy) AfterTableReloadData afterReload;
//!获取Table的数据源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!设置Table的数据源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;

固然定义了二个addCell属性,可是怎么具有,还得看getter和setter怎么得以完成:

@implementation UITableView(ST)

#pragma mark 核心扩展

-(AddTableCell)addCell
{
    //从第三方持有返回
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
         //第三方持有addCell
    }
    else
    {

    }
}

假定那里,把存档addCell那些block存到和UITableView非亲非故的地方去了?

用叁个第3方持有block,只要这么些第三方不和和self爆发径直关乎,那么相应就不会有标题。

引用关系就改成:

第三方:强引用=》block

block:强引用=》self

那里的假释关系,第3方活着,就不会释放block,block活着,就不会释放self。

因而结论:依然不自由。

也正是说,壹顿代码写下去,就算破除了涉及,但要么没释放。

总结:

完整折腾完内部存款和储蓄器释放难题后,Sagit框架也快捷了广大,只怕是错觉。

IT连的创业的也在持续,应接我们持续关切,多谢!

http://www.bkjia.com/IOSjc/1270679.htmlwww.bkjia.comtruehttp://www.bkjia.com/IOSjc/1270679.htmlTechArticle讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)-
block中任意用self,sagit.frameworkios 前言:
在管理完框架内部存储器泄漏的题材后,见上篇…

煎熬三:考虑怎么着打破block和self的双向引用?

 block和self,相互的强引用,要打破它,总得有一方要示弱。

既然block中要允许self中存,就表示block对self必然是强引用,辣么就只可以考虑,若是让self对block只好是弱引用了,可能没有引用!

先来看框架的一段代码:

公海手机版 25

被圈起来的代码,完毕的下列图中圈起来的功效:

公海手机版 26

对此Sagit中,达成表格的代码是还是不是觉的很轻巧,可是教程还没写,那里提前败露了。

或许说着重,珍视为UITableView中,扩大了一个个性AddCell的Block属性,见代码如下:

@interface UITableView(ST)

#pragma mark 核心扩展
typedef void(^AddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^DelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef void(^AfterTableReloadData)(UITableView *tableView);
//!用于为Table追加每一行的Cell
@property (nonatomic,copy) AddTableCell addCell;
//!用于为Table移除行的Cell
@property (nonatomic,copy) DelTableCell delCell;
//!用于为Table reloadData 加载完数据后触发
@property (nonatomic,copy) AfterTableReloadData afterReload;
//!获取Table的数据源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!设置Table的数据源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;

虽说定义了多个addCell属性,然而怎么具有,还得看getter和setter怎么得以达成:

@implementation UITableView(ST)

#pragma mark 核心扩展

-(AddTableCell)addCell
{
    //从第三方持有返回
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
         //第三方持有addCell
    }
    else
    {

    }
}

假设那里,把存档addCell那么些block存到和UITableView毫不相关的地点去了?

用3个第叁方持有block,只要那一个第二方不和和self发生直接关系,那么应该就不会反常。

引用关系就变成:

第三方:强引用=》block

block:强引用=》self

此地的放出关系,第一方活着,就不会自由block,block活着,就不会自由self。

由此结论:依旧不自由。

也便是说,1顿代码写下来,尽管免去了关联,但要么没释放。

煎熬1:在代码中重新定义宏?

上边的代码,说白了就是使用了self,我们看一下宏定义:

公海手机版 27

一般说来的做法,碰到block,都陪伴有WeakSelf那东东,像这么:

公海手机版 28

STWeakSelf的默料定义:

//block块中用的引用
#define STWeakSelf __weak typeof(self) selfWeak = self;__weak typeof(selfWeak) this = selfWeak;
#define STWeakObj(o) __weak typeof(o) o##Weak = o;
#define STStrongObj(o) __strong typeof(o) o = o##Weak;

回顾,宏定义正是编绎期的文字替换游戏,如若小编在block里的第二行代码,重新定义sagit那些宏会怎么样? 

譬如那样定义:

公海手机版 29

接下来这么使用:

公海手机版 30

因而看来是自身想多,编绎都打断。

末尾:嗤笑二个IOS的另2个坑,又是私人住房的dealloc方法:

上壹篇小说,讲到,假诺对UIView扩展了dealloc这措施,引发的谋杀案是:

导航栏:二遍后退就闪退。

那一篇,又被自个儿开采,即使对UIViewController扩张dealloc这一个格局,引发的命案:

UIAlertView:当alertViewStyle设置为带文本框时就闪退。

给大伙儿上1个图,先把dealloc打开:

公海手机版 31

下一场运营的机能:

公海手机版 32

坑吧,幸亏有上三回的经验,赶紧新建了二个类型,然后用代码排除法,最后照旧排到dealloc那里来。

见到那小说的同室,你们又可以去忽悠同事了。

前言:

在拍卖完框架内部存款和储蓄器泄漏的主题材料后,见上篇:讲述Sagit.Framework消除:双向引用导致的IOS内存泄漏(中)-
IOS无人问津的Bug

发觉专门的工作代码有叁个地点的内部存款和储蓄器没释放,原因很也大约:

公海手机版 33

在block里用到了self,产生双向引用,然后就从头怀恋怎么处理那一个主题材料。

平常则合计,正是改代码,block不要用到self,或只用self的弱引用。

只是框架那里特别,有2个特好用的俯十地芥,STLastXXX体系,是用宏定义的,而且该宏指向了self。

如此好用的STLastXXXX宏定义体系,作者期待它能够不受限制的四处使用。

于是乎初叶折腾之路:

假定你想将1个block持久化,先copy一下,不然你会死的相当惨。

可以吗,让它们相互强引用吧,剩下的事,正是何人来当这几个第一方,以及怎么消除那层关系!!!

于是乎,到导航栏后退事件中,拦截,并做销毁职业:

@implementation UINavigationController (ST)

#pragma mark NavigationBar 的协议,这里触发
// fuck shouldPopItem 方法存在时,只会触发导航栏后退,界面视图却不后退。
//- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item  // same as push methods
//{
////    //重设上一个Controller的导航(不然在二次Push后再Pop会Crash)
////    NSInteger count=self.viewControllers.count;
////    if(count>0)//发现这里返回的viewControllers,已经是移掉了当前的Controller后剩下的。
////    {
////        UIViewController *preController=self.viewControllers[count-1];//获取上一个控制器
////        if([preController needNavBar])
////        {
////            [preController reSetNav:self];
////        }
////    }
////
//    return YES;
//}
//返回到当前页面
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
//    if(navigationBar!=nil && [navigationBar.lastSubView isKindOfClass:[UIButton class]])
//    {
//       // [navigationBar.lastSubView height:0];//取消自定义复盖的UIButton
//    }
    NSInteger count=self.viewControllers.count;
    if(count>0)
    {
        UIViewController *current=self.viewControllers[count-1];
        self.navigationBar.hidden=![current needNavBar];
        if(self.tabBarController!=nil)
        {
            self.tabBarController.tabBar.hidden=![current needTabBar];
        }
        //检测上一个控制器有没有释放
        UIViewController *nextController=current.nextController;
        if(nextController!=nil)
        {
            [nextController dispose];
            nextController=nil;
        }
    }
}
-(void)dealloc
{
    NSLog(@"UINavigationController relase -> %@", [self class]);
}

Sagit框架为:每个view和controller扩大了dispose方法,里面清掉键值对,等于把block置为nil,解除了事关。

除了导航后退,还亟需拦截多二个轩然大波,正是presentViewController的事件跳转时,也须要检查实验并销毁。

办好那两步之后,以往就足以轻易的在block里写self了,爱引用就引述了,反正传说的尾声,都有1个目生人来终结

再正是强引用有三个功利:

1:再也用不上WeakSelf这种定义了。

2:由于是强引用,就不用去管:里面还要套个StrongSelf,去避开多线程时,self可能被移除时带来的闪退问题。

假诺第二方对block是弱引用呢?

为了那些实验,小编新建了三个门类,然后在这一个项目上,试了全副二四钟头:

推行进度并未有博得的想要的结果,但精晓block的原理,和剖断本人的逻辑误区。

实验的拿走的学问后边再享受,那里先一连:

由于这里addCell,必须始终存活,因为你不知道什么时候,可能又要UITableView的reloadData一下。

所以,addCell这个block,必须被强引用,而且生命周期得和UITableView一致。

所以,要打破这个核心,还是得有第三方行为事件来触发破除关系,故事就转变成为:由self去移除第三方。

如果一定义要由某个事件来触发解除关系,那么第三方也没存在的必要了。

因为正常A和B互相引用无解,是指他们互相无解,但只要有第三者存在,对其中一个置nil就解了。

最终的末尾,框架的代码是这么的:

-(AddTableCell)addCell
{
    return [self key:@"addCell"];
}
-(void)setAddCell:(AddTableCell)addCell
{
    if(addCell!=nil)
    {
        addCell=[addCell copy];
        [self key:@"addCell" value:addCell];
    }
    else
    {
        [self.keyValue remove:@"addCell"];
    }
}

一如既往是用强引用来存档block,那里有一个注意事项:

叙述Sagit.Framework搞定:双向引用导致的IOS内部存款和储蓄器泄漏(下)- block中放4用self,sagit.frameworkios

相关文章