公海赌船网站每当公的类别蒙投入这一行代码就不过并。只是自我自己不过过头信任人了。这里主要以iOS和OSX讲出口crash闪退怎么防御。

LYEmptyView

其一框架是我于5,6独月前,公司启动新路之早晚,一起开始着手编写的,经过这类型之证实和考验,不断的开展到,在此特将马上卖框架分享出来供大家参考和习。
github地址:https://github.com/yangli-dev/LYEmptyView

勿欲依照协议,不欲安装代理,不待贯彻代理方,只需要立即同一句代码,就只是也一个UITableViwe/UICollectionView集成空白页面占各类图。self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];

今天没什么事做的光阴里,跟着室友看了一阵子演员的生,我大体看了季单小品,能记得的《风声》、《团圆》、《滚蛋吧,肿瘤君》、《激情燃烧的辰》,除了激情燃烧的辰,我若每一个且哭了。
啊聚会四十年的光阴的等待与追寻,知道后新在的扑,以及总会有人伤心之交融选择;
呢风声里比较急,然后造化呢是比苛折,人物关系复杂;
也肿瘤君里也许有时候该相信命运,当患了绝症后的悲惨和思念在下来的私心之矛盾感吧。

timg.jpeg

目录

  • 一致 效果亮
  • 其次 使用参考示例
    • 1 一行代码集成空内容视图
    • 2 自由选择空内容元素
    • 3 自定义空内容元素
    • 4 自定义元素的UI样式
    • 5 二糟糕封装
    • 6 缓显示emptyView
    • 7 异常要求,手动控制emptyView的亮隐藏

新兴之生活里,我弗知底我怎么了,泪点儿越来越低,似乎对于被自己触动的业务,我哭的蝇头大少是盖想到自己的组成部分涉或者什么。大多的时刻都是我无比入戏。不克仅仅就的说自家看的凡不错的食指当上演了对的角色关系以及纠纷。只是我自己最过分信任人了,是自身要好之良心极度过头柔软了,太过头去支持于为其表现的内容去接近了。

前言

这边要因为iOS和OSX讲出口crash闪退怎么防御。
内最新的OSX应用本身就是生得闪退防御,但稍事类似@try @catch于极端外层包了瞬间一般性的越界调用空方法还见面搁浅在操作位置不向下实行,如果没有更复杂逻辑不会见闪退,只是影响延续之操作。

假定iOS则没有这么好谈了,二话不说直接闪退给你看没上面的那种机制。

为此才有矣统筹一个安保系统的意思,来担保最好深程度之健壮性,理想的状态就是免crash且能继续健康运转后的逻辑。

参考了诸多网上的资料有了下的稍成果分享出去,这实际上只是是安保网最终的一个环节的守护

https://github.com/heroims/SafeObjectProxy

平等 效果亮

show.gif

ImitateOtherApp.png

受自己流泪,让自家之泪腺发挥作用的再度多的凡盖自己之柔软。

安保体系规划

此间自己所认为的安保体系应该于代码和业内两个范畴看,毕竟想拘捕到所有的crash情况是必定非容许的,现实中尽管处处try
catch都没法保证办案及具备crash!

其次 使用参考示例

既看罢同样段话说,当一个丁回想过去的时候表明它们开一直矣。很明朗,我不属这个规模,只是回忆里呢生太多的作业,似乎在自家记起她,缅怀和认知一下顿时它带动为自家挺心情下之自家之拍以及震撼的时刻,在我操感受手指的律动,把它们形容下来的天天,它便实在在开始去我多去矣~
像她从未过来了千篇一律。无声无息的来,同样云淡风轻的错过!

代码

  • swizzing切面
  • 方防御选型
  • 守卫成功申报

先后外需要之是代码,这个模块是一旦没有外侵入性的,所以切面是必的,其次就是尽量的细化切面颗粒度保证意外状况绝小化!

其余一些就是切面以后咱们针对原方法应该运用哪些的防守,这里虽好try catch的形式吗可以进行逻辑判断形式。
要己之代码里之所以逻辑判断,更多的勘查是针对性的函数都偏下层都易用时外部恰巧又发各种循环逻辑,那样相较之下try catch每当未间断的调用性能会发出一定影响,所以临时失效try catch作防守之伎俩。
从今任何一样角度看其实try catch的采用状况有些措施还是比合适的,首先我们于戍守时办法颗粒度已经老细所以抓住异常都见面开对诺处理不会见产生内存泄漏或逻辑遗漏,另外无论try还是catch内之艺术吧非会见极其多,满足了`try
catch的顶尖场景,只是分别方法循环使用多少过高或性能没法到极致仅此而已。

看守了了crash就是上报,我们维护了先后的又为便表示有地方写的生问题,由于没crash所以没crash
log,这时候就需要在安保模块里投入报告机制,这时候我之做法尽管是加大起一个协商等人去贯彻,安保模块就专心处理防御的事体,上报及劳动端的政工交给专门处理当下从的模块,我们特待以戍守成功时告知协议来诸如此类个工作即可。剩下的虽是私家看状态只要得详细情况直接[NSThread callStackSymbols]把仓库信息输出一下!

//安保模块上报协议
@protocol SafeObjectReportProtocol

@required
/**
 上报防御的crash log

 @param log log无法抓到Notification的遗漏注销情况
 */
-(void)reportDefendCrashLog:(NSString*)log;

@end

假定落实此协议的只需要针对SafeObjectProxy做个Category实现转即可。

再有就是是守卫的分类开启,这时候枚举就要用各项运算的花样,这样才能够匹配多种模式共存如下只被Array和String的守护

[SafeObjectProxy startSafeObjectProxyWithType: SafeObjectProxyType_Array| SafeObjectProxyType_String]

1 一行代码集成空内容视图

//框架方法
self.tableView.ly_emptyView = [LYEmptyView emptyViewWithImageStr:@"noData"
                                                        titleStr:@"暂无数据,点击重新加载"
                                                       detailStr:@""];

PS:可针对框架进行第二不良封装,调用更简单(二不行封装方法在底下的言传身教5丁会摆到)

//二次封装方法,调用简洁
self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];

净没有耦合,在您的花色被加入这一行代码就可并
不论项目面临凡reloadData方法刷UI还是insert、delete等办法刷UI,不欲召开其他任何操作,只待及时一行代码就不过实现以下功能

example1.gif

偶觉得甚盲目,似乎生命里发出极端多值得咀嚼的事情,有时候在无声的构思,会意识,似乎整个吧都非会见是定点,它只有是每个当下底生之一个缩影。没有遗憾,也没特意的惊喜,我只好说自家看出了美丽的瞬间,也享受过局部美好的时刻,有些美好真实的起在自身上了,我感觉得到它于自家活,它于那一刻的我感知到了甜美。虽然本人还无顶说得清幸福是呀,但是有些时刻我真感到这样好与神奇,它带来为自家了惊喜之感觉到,就比如在你前面铺开一帧描绘了是您所好的样子的点染,一帧一帧的播放着,你生想一直还扣留不结,看不尽,但她一闪而过了,没有了,空留你于当年思考和惋惜。一些天天的本身大体如此吧。没有好记得过去底哟,也不曾感念极力忘记的呀,因为实在记得的若莫用失去记,真正想忘记的该忘的为决不你努力。

规范

任何一个安保模块的构成则该是本着代码规范之制订及校验,这便得clang来开了,不是此最主要讲的,相当给多了同等种Build OptionsCompiler for C/C++/Objective-C特性的选料,用我们开发之Xcode校验插件,检查代码语法上的题目直接报错,这样于源头来规范化编码。

2 自由选择空内容元素

交互事件可选择SEL或block方式
SEL交互事件:
self.tableView.ly_emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData"
                                                              titleStr:@"无数据"
                                                             detailStr:@"请稍后再试!"
                                                           btnTitleStr:@"重新加载"
                                                                target:target
                                                                action:action];
block交互事件:
self.tableView.ly_emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData"
                                                              titleStr:@""
                                                             detailStr:@""
                                                           btnTitleStr:@""
                                                         btnClickBlock:^{}];
//    imageStr    : 占位图片
//    titleStr    : 标题
//    detailStr   : 详细描述
//    btnTitleStr : 按钮标题                                                         

框架提供四独元素,传入相应元素的字符串即可显示对应元素(按钮的示前提是流传target,action或btnClickBlock)
唯独根据项目要求,自由进行重组,如下只展示了片构成功能

example2.png

命里即使再来同样普,我依然选择如此,我仍会是这的面目。

Crash分类与防御实现

  • Unrecognized Selector(找不交艺术)
  • UI Refresh Not In Main Thread(UI刷新不以主线程)
  • Input Parm Abnormal(入参异常)
  • Dangling Pointer(野指针)
  • Abnormal Matching(异常配对)
  • Thread Conflict(线程冲突)

纪念要守护crash,首先使召开的便是摸底都起哪些状态会生crash,上边就是作者总结的几乎种植最广大的景况,不净的语句想有人留言补足,毕竟crash的防卫真正有发言权开发这种模块的估算只有充分商店开发app的,不然用户量不敷没样本采集,没法了解坑爹的景象!

若是者列的6种植常见crash,真正能够广域控制得矣之或者也就发生一半请勿交!下面就相继讲解一下,Hook切面就是重要的一手!

3 自定义空内容元素

异常情况下,如果空内容状态布局不满足要求时,可开展打定义
经艺术+ (instancetype)emptyViewWithCustomView:(UIView *)customView;
传一个View 即可创建一个自定义的emptyView

self.tableView.ly_emptyView = [LYEmptyView emptyViewWithCustomView:customView];

example3.png

奇迹热忱,有时候沉默~
有时候随和如明媚,有时候偏执而拧巴~

Unrecognized Selector(找不顶方式)

斯找不顶点子算比较好惩治的。。。也算是比较普遍的好查的,另外处理ok了null对象调用的题目为会见跟着缓解
只是卜的方法发生个别种植
Hook这片个法子
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
抑或Hook这一个计
-(id)forwardingTargetForSelector:(SEL)aSelector

核心思想就是当查找不顶艺术之前创建方法确保继续执行不挂,为了尽量不多余的缔造方法,集中之将创建于至联的地方。

前端需要以methodSignatureForSelector实行前在新的target里创建没有底措施,然后据此其调用methodSignatureForSelector返回,而这边的target当然如果单例弄出来省的事后来回创建。然后在forwardInvocation里之所以外来调用invokeWithTarget拄到我们新的target上。

后来人为就算是自个儿用底法门,之所以用它们根本是一个法
就ok!而我们还要兼任静态方法和实例方法去分别hook才能够防住这点儿种植,而前者也要是hook的计重复多。。。。
假设此仅待切forwardingTargetForSelector艺术,静态方法返回class,动态方法返回target,当然返回之前我们如果补偿加上未在的法子,值得注意的凡OSX上一个神奇的题材,我以认清是否系来这个艺术的当儿第一不良还是respondsToSelector返回false而methodSignatureForSelector发数据,第二不善校验是methodSignatureForSelector才为空,而iOS上则无这题目首先涂鸦校验就是本着之!

4 自定义元素的UI样式

这里从定义UI样式需要多代码,别担心,在演示5遇见面讲课二差封装的方式,封装后调用时就单纯需要一行代码了
^ _ ^

  //初始化一个emptyView
  LYEmptyView *emptyView = [LYEmptyView emptyActionViewWithImageStr:@"noData"
                                                           titleStr:@"无数据"
                                                          detailStr:@"请稍后再试!"
                                                        btnTitleStr:@"重新加载"
                                                      btnClickBlock:^{}];
  //元素竖直方向的间距
  emptyView.subViewMargin = 20.f;
  //标题颜色
  emptyView.titleLabTextColor = MainColor(90, 180, 160);
  //描述颜色
  emptyView.detailLabTextColor = MainColor(180, 120, 90);
  //按钮背景色
  emptyView.actionBtnBackGroundColor = MainColor(90, 180, 160);

  //设置空内容占位图
  self.tableView.ly_emptyView = emptyView;

此只有列举了部分常用的性质,更多属性请到LYEmptyView.h查看

example4.png

瞻前顾后写不写的天天,关了微机又瞬间还打开敲了一会儿字的自家,似乎写之前我吧无知底我要是写啊,只是当手指开始敲起键盘的下,忍不住的永不去思的,就可形容下几什么。

UI Refresh Not In Main Thread(UI刷新不以主线程)

刷新UI不以主线程的情况这里仅仅是针对性UIView和NSView的3独章程做切面线程判断。分别是setNeedsLayout,setNeedsDisplay,setNeedsDisplayInRect,执行前看是匪是在主线程,不在的言语虽断到主线程执行,但生明确这3独点子肯定覆盖不净,而且就覆盖全了每次都认清一下也是性浪费,所以这里分别斟酌处理吧,这类状况小无悟出其他好的处理方式!但好于算有这般个可控方案!

5 二次于封装

第4小节的示范代码,修改emptyView的样式需要一个个性能单独去改变,如果项目受到每个界面都这么形容就显示十分烦,而且不易维护
解决办法是本着库房进行第二赖封装,二赖封装后,对UI样式单独管理,方便维护

旋即一刻,那无异秒,你当事关啊,又有啊轻轻的激动了若的衷心?

Input Parm Abnormal(入参异常)

入参异常这是一致怪类,防御之方吧相对较通俗易懂,也是无比易查最易并发的。

1)新建一个像样继承自LYEmptyView,例如demo中之MyDIYEmpty

常用色入参异常

常见类包括String,Array,Dictionary,URL,FileManager等这些近似空值初始化,越界取值,空赋值等,基本看crash
log统计依次切面对应措施以实践前判断一下哪怕ok。如objectAtIndex,objectAtIndexedSubscript,removeObjectAtIndex,fileURLWithPath,initWithAttributedString,substringFromIndex,substringToIndex等等。唯一用注意的就算是这些使切面的类名可是五花八门同时更iOS版本有充分可怜关系,所以是就算是赖crash
log积累了解有哪坑。当然代码写的好就是就此无交了!__NSSingleObjectArrayI这就是是近日在iOS11高达新意识的报错数组类,当然也恐怕是最近我司有人写起了这相关的bug……
常见的得注意的hook的类似产生以下
objc_getClass("__NSPlaceholderArray")
objc_getClass("__NSSingleObjectArrayI")
objc_getClass("__NSArrayI")
objc_getClass("__NSArrayM")
objc_getClass("__NSPlaceholderDictionary")
objc_getClass("__NSDictionaryI")
objc_getClass("__NSDictionaryM")
objc_getClass("NSConcreteAttributedString")
objc_getClass("NSConcreteMutableAttributedString")
objc_getClass("__NSCFConstantString")
objc_getClass("NSTaggedPointerString")
objc_getClass("__NSCFString")
objc_getClass("NSPlaceholderMutableString")
切切实实产生怎样措施要切面还是看源码吧,这部分凡是没什么难点的。

此外自之看守中没针对NSCache做,可能以后会管加点,因为缓存相关的模块我的建议是友善包裹缓存模块或用第三正,那样对上层使用者来说已是平安之了!各种非常处理在缓存模块里就是该来包。

2)重写- (void)prepare 方法,并修改想如果改变的要素的UI样式
- (void)prepare{
    [super prepare];

    self.titleLabFont = [UIFont systemFontOfSize:25];
    self.titleLabTextColor = MainColor(90, 180, 160);

    self.detailLabFont = [UIFont systemFontOfSize:17];
    self.detailLabTextColor = MainColor(180, 120, 90);
    self.detailLabMaxLines = 5;

    self.actionBtnBackGroundColor = MainColor(90, 180, 160);
    self.actionBtnTitleColor = [UIColor whiteColor];
}

操作上面的点滴步就是可实现对体制的独保管
调用方法无转移,只是调用的好像成为了MYDiyEmpty

self.tableView.ly_emptyView = [MYDiyEmpty emptyActionViewWithImageStr:@"noData"
                                                             titleStr:@"暂无数据"
                                                            detailStr:@"请稍后再试!"
                                                          btnTitleStr:@"重新加载"
                                                        btnClickBlock:^{}];

KVC Crash

KVC归根结底也好不容易这仿佛入参异常,一共切面3单地方就是足够防御了!
-(void)setValue:(id)value forKey:(NSString *)key,
-(void)setValue:(id)value forKeyPath:(NSString *)keyPath
空值防御上面2独艺术
-(void)setValue:(id)value forUndefinedKey:(NSString *)key
点是就从未底性做赋值操作时走的回调,如果用到我之SafeObjectProxy假若由定义各个类不同之处理是好无上马起来UndefinedKey防御的!

3)进一步封装显示的元素内容,比如无多少状态图、无网状态图

当MYDiyEmpty.h定义方法+ (instancetype)diyNoDataEmpty;
以MYDiyEmpty.m实现方式

+ (instancetype)diyNoDataEmpty{
    return [MyDIYEmpty emptyViewWithImageStr:@"noData"
                                    titleStr:@"暂无数据"
                                   detailStr:@"请稍后再试!"];
}

由此3步包,自定义了UI样式,使管理还利于,使调用更简洁
self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];


Dangling Pointer(野指针)

这种Crash堪称经典!就是挺最难以排查的,而此我们能够做的守卫工作吗深星星!
切实定位看看腾讯这几篇大有帮衬!
何以定位Obj-C野指针随机Crash(一)
争稳定Obj-C野指针随机Crash(二)
安定位Obj-C野指针随机Crash(三)
咱俩只好去对已经了解之起野指针的近乎进行防卫,找到crash的野指针开启Zombie
Objects,加上Zombies工具,然后想艺术不断增高复现率还是可以的稳到的。
咱俩的守护则是hook系统dealloc,判断用开处理的近乎非活动系统delloc而是走objc_desctructInstance放实例之中所负有属性的援和涉对象,保证对象极其小化。紧接着便需来波isa swizzling了,因为一般而言野指针伴随在的还有即使是调用没有底措施,或者由调用的这个时机是勿正常的,各种数据的安全性都尚未了保证,所以dealloc后去掉所有有,再把原先的isa指为一个旁的类,而以此类能把装有的调用方法对一个空方法这么即使于及了守之图。

能够干就事之也罢惟有NSProxy了,利用协议落实methodSignatureForSelectorforwardInvocation计,统一于到前面处理找不至艺术自动创建的近乎中,也即是在NSProxy内实现地方Unrecognized Selector的守卫,这样具有对野指针的调用就都是拖欠了!
巧因地方的来由使被了此防御,真正自由的火候就是还是片,如果当野指针出现前点了真自由的逻辑,crash就还是会有些!
我在SafeObjectProxy里只是用野指针个数控制做实在释放,回头可能会见卷入个block方便复杂气象的判断。

脚的有数栽示例,属于特殊需要,需要四行代码搞定,调用和MJRefrsh类似,需要事先安装样式,然后显示和潜伏

Abnormal Matching(异常配对)

当时无异于好像算是不建议做防守的!成对的点子处理好像KVO,NSTimer,NSNotification都算,需要报及撤销。
这种状态我之提议是统一封闭装独立模块调用统一之计,让人非需关爱注册及取消,主要描写逻辑处理。从效果实现达标做严格限制,这样被人设想的虽是何许将一个场景融入到包的方法吃,而非是即兴的描绘!
下面说下由,由于挂号及撤销是分手写的
,所以使用状况,解决问题之方都见面具备非常灵活的操作,这实际上十分可怕,先用KVO做一个比方顺便说一下随即仿佛防御如果确若召开一般的做法是怎开。

6 推迟显示emptyView

如示例1图,框架自动根据DataSource计算是否显示emptyView,在空页面发起网络要时,DataSource肯定也空,会自行显示emptyView,有的产品需要或不愿意这样,希望提倡呼吁时临时隐藏emptyView。
准框架提供了零星单办法可实现此需要,两只点子都是scrollView的分类,调用非常便利

 /**
   一般用于开始请求网络时调用,ly_startLoading调用时会暂时隐藏emptyView
   当调用ly_endLoading方法时,ly_endLoading方法内部会根据当前的tableView/collectionView的
   DataSource来自动判断是否显示emptyView
 */
- (void)ly_startLoading;

 /**
   在想要刷新emptyView状态时调用
   注意:ly_endLoading 的调用时机,有刷新UI的地方一定要等到刷新UI的方法之后调用,
   因为只有刷新了UI,view的DataSource才会更新,故调用此方法才能正确判断是否有内容。
 */
- (void)ly_endLoading;

*注意点:使用就片单道,请预以emptyView的autoShowEmptyView属性置为NO,关闭自动显隐

以下是调用示例(具体细节而参考demo中之demo2)

//1.先设置样式
self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];
//2.关闭自动显隐(此步可封装进自定义类中,相关调用就可省去这步)
self.tableView.ly_emptyView.autoShowEmptyView = NO;
//3.网络请求时调用
[self.tableView ly_startLoading];
//4.刷新UI时调用(保证在刷新UI后调用)
[self.tableView ly_endLoading];

example6.gif

KVO

KVO这种crash如果要守其实只能防御下面3种情形:
1.观察者或让观察者已经休存了
2.注销同增长的次数不般配
3.未曾写监听回调observeValueForKeyPath:ofObject:change:context:

若果当时3栽状态咱来认真考虑下开发的等是匪是形似都见面第一时间就让发现!而且若是未曾经历的程序员写KVO我们是勿是都非敢用,会反复审查,而有更的同时不会见发上面的摩。。。。
要是对端的景防御也要命复杂,而且自己尝试以因此了无数老三着,都当我司稍微有硌复杂的花色落得挂了,不仅没能够守crash还去了crash,这种成对逻辑的灵活性非常大,你没法理解系统里人家怎么用正在戏的!
说一下守上面的情状首先切面add、removeObserve是早晚的,还要当装有的类里再加一个靶,这个目标要负责管理KVO下面就是被KVOController吧,让有的观察者都成了给观察者的一个性能,用map记录原来的观察者和keyPath等信息,这样加加要移除观察者就能够判断是勿是成对出现的,另外KVOController在dealloc时为可以经map依次移除监听,而出于有着的监听回调其实还是出于KVOController的observeValueForKeyPath:ofObject:change:context:通过[originObserver observeValueForKeyPath:keyPath ofObject:object change:change context:context]传递出的本来没有写监听回调的图景吧可看清了,但为是能够解决那3只状态!

真正KVO产生的恐怖之crash是移除时机未跟观察者或给观察者销毁有提到,而是和咱们的逻辑有关,一旦没有当宜会移除导致的crash排查起来超级讨厌!还有你于监听回调里处理逻辑来没有有线程安全题材,这些才是咱们以上线前容易透,排查以坏排查的!

安保网则是如果保护上线后能够正常运行,然而就如自己这边说之KVO,如果非以编码期间就开严格规范,上线后产生之题目呢是有史以来不许防御的!

下一场再度来说说怎么界定我们的自由发挥,KVOController刚才说及的此用之是将她变形,把回调用block放出来,另外即使是受它们发生单例模式以及常见的实例模式,只有创建对象、关联监听与逻辑处理,一个KVOController可以是全局或属于一个目标,相当给可视化了KVO的见效周期,一目了然,这里被特殊逻辑适应我们的标准才是不利的安保思路。包括NSTimer在内也为是如此可以为个TimerController不过封装最好呢变化用NSTimer精度不赛,反正要卷入不如直接gcd,与该只要手动保持成对不如我们就是管逻辑封装好,让使用者忘掉成对的概念!但当放的今日了可以GitHub搜一波找来封装好之友好又简单包装下,然后给团队按规范开发即可。。。

KVO:KVOController比较推荐的一个KVO管理

7 例外要求,手动控制emptyView的来得隐藏

在某些特殊界面下,有的tableView/collectionView有固定的组成部分充分多少,其它的多少根据网加载,这时根据以上之演示方法恐怕上不顶立刻需要。
仍框架提供另外的鲜只道来化解之题目。

/**
 手动调用显示emptyView
 */
- (void)ly_showEmptyView;

/**
 手动调用隐藏emptyView
 */
- (void)ly_hideEmptyView;

*注意点:使用这简单单艺术,请预以emptyView的autoShowEmptyView属性置为NO,关闭自动显隐

以下是调用示例(具体细节而参看demo中之demo4)

//1.先设置样式
self.tableView.ly_emptyView = [MyDIYEmpty diyNoDataEmpty];
//2.关闭自动显隐(此步可封装进自定义类中,相关调用就可省去这步)
self.tableView.ly_emptyView.autoShowEmptyView = NO;
//3.显示emptyView
[self.tableView ly_showEmptyView];
//4.隐藏emptyView
[self.tableView ly_hideEmptyView];

example7.gif

欢迎star
github地址:https://github.com/yangli-dev/LYEmptyView

NSTimer

NSTimer比较突出,有些时候偏偏不该变成对下,它的成对的逻辑其实是和自己的生命周期有关,毕竟生命周期结束时如果错过成对的停掉timer才能够自由,另一些就是是NSTimer精确度并无高!但它包裹出来给人就此底法门是ok的正是有单例模式及实例模式简单种植下。所以我之提议当然是投机把gcd的timer封装一下,另外将target这个概念变为weak持有,这样咱们和好包裹的timer就可以dealloc的时节停掉timer释放了,按照系统NSTimer封装方法即可。这样至少能够保证timer指定的target释放时timer能住少不会见因跑了任何未安全的逻辑挂掉。其他可能挂掉的情状应该比较少。。。

Timer:MSWeakTimer较推荐的一个计时器封装方法就是是自身点讲的那种

NSNotification

夫虽然为是成为对应用,单比地方的几乎独比方安全有,因为以它们产生[[NSNotificationCenter defaultCenter] removeObserver:self]屡次调用或尚未addObserver还非会见挂,所以可以全局作一下,我当SafeObjectProxy里就是只是对具有NSObject目标上加了只特性做标识,然后hook一下NSNotificationCenter-(void)addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject方法,只要observer是NSObject对象自我就是标识一下,然后切所有NSObjectdealloc倘标识了之合实施[[NSNotificationCenter defaultCenter] removeObserver:self],反正多行了邪未尝问题用之放心!

但是如若是成对的,就发出另外一个问题,万一真正需要注销的地方是暨逻辑有关,那你对象销毁时注销就晚矣,就像面KVO中关系的我们开的当下层crash防御其实犯错率并无高能及时发现,而及时发现不了底只能是由此编码规范或者人员分别禁用来化解。

Thread Conflict(线程冲突)

基本无解的题目,出现之后瞬间懵逼,典型例证就是是死锁,异步调用同一对象造成未安全,基本没防守手段,排查也只能凭借多加log不断复现,然后猜。。。。
唯独一般如果代码按照正规的业内写啊无会见那么爱碰到这问题,但线程冲突理论及如果保证UI操作都于主线程,其他都gcd不以主线程上,然后有要线程安全的gcd信号量做锁就好,但未会见有人这么勾画代码,性能与频率那么折腾是都要抛开的,现在犹期盼你顿时出活那有空那样,这类就得完全不考虑防御的从了!

相关文章