内存泄漏:https://my.oschina.net/llfk/blog/1031291

内存泄漏监测自动化:http://www.cocoachina.com/articles/18490

facebook三件套内存检测:https://www.jianshu.com/p/bf43f2a7290c、https://www.jianshu.com/p/4730d90e6008、https://www.jianshu.com/p/bf43f2a7290c

******iOS几种常见内存泄漏:https://blog.csdn.net/heqiang2015/article/details/84575047

**【view  removeFromSuperview】后,view的内存并不一定释放,最好在合适的时候设置view=nil;

**UITextfield获得焦点后会内存高涨,因为弹出了键盘,不用的时候要取消焦点。

AFN内存泄漏问题:https://juejin.im/post/5a20ec24f265da432240feb8

// AFURLSessionManager.m
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {// ... 初始化代码,省略// 导致循环引用的方法self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];// ... 其它初始化代码,省略return self;
}
大致原因就是AFURLSessionManager引用NSURLSession,同时设置NSURLSession的delegate为自己,NSURLSession会强引用delegate,于是产生了循环引用。
Leaked memory 和 Abandoned memory 都属于应该释放而没释放的内存,
都是内存泄露,而 Leaks 工具只负责检测 Leaked memory,
而不管 Abandoned memory。
对于 Abandoned memory,可以用 Instrument 的 Allocations 检测出来。

__weak和__strog配合使用原因:https://www.jianshu.com/p/ae4f84e289b9

__weak对象释放后自动变为nil解释:https://blog.csdn.net/weixin_30352645/article/details/98951975

引用计数原理:https://www.cnblogs.com/azuo/p/6066868.html

打印引用计数:

方法一:使用KVC
[obj valueForKey:@"retainCount"]
方法二:使用CFGetRetainCount
CFGetRetainCount((__bridge CFTypeRef)(obj))
方法三:使用私有API
OBJC_EXTERN int _objc_rootRetainCount(id);
_objc_rootRetainCount(obj)

引用计数会增加的情况:alloc,new,strong,copy,set方法或者点语法,block内的对象,storyboard拖拽出来的控件,addsubview添加子控件。当对象的引用计数减为0时候,会出发dealloc的调用;当前对象销毁,属性所持有的对象也跟着销毁。

******引用计数举例:

#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;

1.****
@property(nonatomic,strong)TestTwovc *twovc;self.twovc=[TestTwovc new];NSLog(@"jishu---%ld",CFGetRetainCount((__bridge CFTypeRef)(self.twovc)));//self.twovc引用计数2.
2*****TestTwovc*twovc=[TestTwovc new];self.twovc=twovc;NSLog(@"jishu---%ld",CFGetRetainCount((__bridge CFTypeRef)(twovc)));//twovc的引用计数是2
@property(nonatomic,weak)TestTwovc *twovc;TestTwovc*twovc=[TestTwovc new];self.twovc=twovc;NSLog(@"jishu---%ld",CFGetRetainCount((__bridge CFTypeRef)(twovc)));//twovc的引用计数是1
 3.*****
TestTwovc*twovc=[TestTwovc new];self.twovc=twovc;NSLog(@"jishu---%ld",CFGetRetainCount((__bridge CFTypeRef)(self.twovc)));//self.twovc的引用计数是3
4.****
@property(nonatomic,strong)Testoneview *oneview;Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];self.oneview =oneview;//计数+1[self.view addSubview:oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));//one view的引用计数+3
 6。*****
testob *testobs=[testob sharedCommonManager];//testob是单利NSLog(@"单利---%ld",CFGetRetainCount((__bridge CFTypeRef)(testobs)));//testobs的引用计数是2,在单利内部有一次实例话的过程。
7.*****NSLog(@"self---%ld",CFGetRetainCount((__bridge CFTypeRef)(self)));
//在控制器vc中什么才做不做,self本身就会有6个引用计数。

****UIVIew animation动画、AFN、dispatch_async(dispatch_after中使用self会循环引用,必须用weakSelf或者StrongSelf)中等block中使用self不会造成循环引用(block中没有其他的block嵌套)。

***** QMWNSTRONG在block不会造成循环引用
@property(nonatomic,copy)void (^blc)(void);QMWNWEAKSELF;self.blc = ^{QMWNSTRONG;在里面Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];strongS.oneview =oneview;//计数+1[strongS.view addSubview:strongS.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));};*********** QMWNSTRONG在block外面会造成循环引用,strongSelf是防止block中weakself提前释放造成崩溃,一般简单的操作用weakSelf也可以。
@property(nonatomic,copy)void (^blc)(void);QMWNWEAKSELF;QMWNSTRONG;在外面self.blc = ^{Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];strongS.oneview =oneview;//计数+1[strongS.view addSubview:strongS.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));};******直接用weakSelf不会造成循环引用QMWNWEAKSELF;self.blc = ^{Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];weakSelf.oneview =oneview;//计数+1[weakSelf.view addSubview:weakSelf.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));};********方法体中用self不会造成循环引用QMWNWEAKSELF;self.blc = ^{QMWNSTRONG;[strongS testfun];//在这里使用了weakSelf或者strongSelf方法体中就不需要在使用weakSelf或者strongSelf了。};}
-(void)testfun{Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];self.oneview =oneview;//计数+1[self.view addSubview:self.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));}**********UIView的block 方法不会造成循环引用[UIView animateWithDuration:0.2 animations:^{[self testfun];//用self 不会造成循环引用} completion:^(BOOL finished) {}];-(void)testfun{Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];self.oneview =oneview;//计数+1[self.view addSubview:self.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));}*****UIVIew的block外还有一层不blockQMWNWEAKSELF;self.blc = ^{QMWNSTRONG;[UIView animateWithDuration:0.2 animations:^{
//             [self testfun];//这里如果self会循环引用,如果UIView  animate方法外层没有block,用self 不会造成循环引用[strongS testfun];//不会造成循环引用} completion:^(BOOL finished) {}];};}
-(void)testfun{Testoneview *oneview=[[Testoneview alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];//计数+1oneview.backgroundColor=[UIColor redColor];self.oneview =oneview;//计数+1[self.view addSubview:self.oneview];//计数+1NSLog(@"oneview---%ld",CFGetRetainCount((__bridge CFTypeRef)(oneview)));}

ARC内存管理(mj):https://www.cnblogs.com/huanying2000/p/6165440.html

weak避免强引用objc对象:https://www.jianshu.com/p/14f494b1f566

内存管理:https://www.jianshu.com/p/ac86dc80cca5

ARC内存管理/strong weak copy assign 的用法与区别:https://blog.csdn.net/u011146511/article/details/51344070


a). 将控件声明成strong
@property(nonatomic,strong) UIButton *btn;
那么你在实现这个控件时只需这样:
_btn = [[UIButton alloc]init];
[self.view addSubview:_btn]b). 将控件声明成weak
@property(nonatomic,weak) UIButton *btn;
那么你在实现这个控件时需要这样:
UIButton *button = [[UIButton alloc]init];
_btn = button;
[self.view addSubview:_btn];assign:适用于基本数据类型,其set方法只会进行简单的赋值操作NSInteger,CGFloat...
/** 基本数据类型*/
@property (assign, nonatomic) NSInteger age;strong:强引用类型,被定义了该类型的属性会被其所指对象持有,为这种属性设置新值的时候,set方法先保留新值,并释放掉旧值,然后再把新值赋值上去
/** 适用于对象类型,并且被持有*/
@property (strong, nonatomic) UIView *view;weak:爱恨交织的weak!弱引用类型,被定义了该类型的属性不会被持有,在set的时候,
既不保留新值也不会释放旧值,和assign类似,不同的是在该属性所指对象被销毁之后,
属性值也会被置为nil
/** 弱引用类型,对象释放后置为nil*/
@property (weak, nonatomic) id<SSDelegate> delegate;
unsafe_unretained:这个跟assign就更像了,但不同的是它适用于对象类型.同样的不会被持有,但与weak不同是,所指对象被销毁之后不会把属性置为nil/** 弱引用类型,对象释放后不会置为nil*/
@property (unsafe_unretained, nonatomic) UIView *view;
copy:它与所指对象是持有关系,与strong类似,然而set方法并不会保留新值,而是将其拷贝一份.
所以,当你声明一个非可变集合类型(collection type)的时候应该使用这个修饰符,不单单是NSString,
同样的NSArray,NSDictionary,NSSet也应当使用它来修饰,
copy可以保护非可变集合类型(collection type)的封装性,
因为在其传递过程中有可能会指向一个可变类型(mutable type),
此时如果不是copy,那么设置完属性之后,其值可能会在对象不知情的情况下被更改了.
所以使用copy修饰符,保证set的时候copy一份不可变(immutable)类型的值,确保前后的一致性./** 适用于集合类型(collection type)*/
@property (copy, nonatomic) NSString *name;

***代码静态分析:OCLint

***僵尸对象分析:在Xcode的scheme页面中设置NSZombieEnabled环境变量。点击Product——>Edit Scheme打开该页面,然后勾选Enable Zombie Objects 复选框。

内存泄漏参考:https://www.cnblogs.com/mukekeheart/p/8144742.html

内存泄漏检测工具MLeaksFinder:https://github.com/Tencent/MLeaksFinder

instrument 使用:https://blog.csdn.net/u011146511/article/details/51500628

*****Analyze (shift+command+b)检测内存泄露product----Analyze

Analyze 分析内存 检测出现 User-facing text should use localized string macro 警告问题

Analyze也可以逻辑错误监测:

Analyze是一个编译和分析工具,可以发现编译中的warning,内存泄露隐患,有时还可以查处逻辑上的问题。

内存泄露隐患提示:

Potential Leak of an object allocated on line ……

数据赋值隐患提示:

The left operand of …… is a garbage value;

对象引用隐患提示:

Reference-Counted object is used after it is released;

Analyze发现的问题值得我们注意,但它只是提出隐患,并不一定就存在问题。

MLeaksFinder原理:

MLeaksFinder 一开始从 UIViewController 入手。我们知道,当一个 UIViewController 被 pop 或 dismiss 后,该 UIViewController 包括它的 view,view 的 subviews 等等将很快被释放(除非你把它设计成单例,或者持有它的强引用,但一般很少这样做)。于是,我们只需在一个 ViewController 被 pop 或 dismiss 一小段时间后,看看该 UIViewController,它的 view,view 的 subviews 等等是否还存在。
具体的方法是,为基类 NSObject 添加一个方法 -willDealloc 方法,该方法的作用是,先用一个弱指针指向 self,并在一小段时间(3秒)后,通过这个弱指针调用 -assertNotDealloc,而 -assertNotDealloc 主要作用是直接中断言。这样,当我们认为某个对象应该要被释放了,在释放前调用这个方法,如果3秒后它被释放成功,weakSelf 就指向 nil,不会调用到 -assertNotDealloc 方法,也就不会中断言,如果它没被释放(泄露了),-assertNotDealloc 就会被调用中断言。这样,当一个 UIViewController 被 pop 或 dismiss 时(我们认为它应该要被释放了),我们遍历该 UIViewController 上的所有 view,依次调 -willDealloc,若3秒后没被释放,就会中断言。
总结起来一句话就是,当一个对象3秒之后还没释放,那么指向它的 weak 指针还是存在的,所以可以调用其 runtime 绑定的方法 willDealloc 从而提示内存泄漏。

**内存泄漏检测框架:FBRetainCycleDetector

NStimer循环引用解决:https://www.jianshu.com/p/bb691938fb2f

循环引用会导致内存泄露,对象释放不掉,会占用内存,如果循环引用多的话,占用内存太大,会导致程序崩溃.

参考:http://blog.csdn.net/lvxiangan/article/details/50202673

****检测循环引用:

Leaks 工具只负责检测 Leaked memory,而不管 Abandoned memory。
在 MRC 时代 Leaked memory 很常见,因为很容易忘了调用 release,但在 ARC 时代更常见的内存泄露是循环引用导致的 Abandoned memory,

对于 Abandoned memory,可以用 Instrument 的 Allocations 检测出来。

检测方法:每次点击 Mark Generation 时,Allocations 会生成当前 App 的内存快照,而且 Allocations 会记录从上回内存快照到这次内存快照这个时间段内,新分配的内存信息。重复操作看内存有没有增长;

二.选择Product----->Profile------->工程的模拟器instrument会开始运行,

三,在弹出的对话框中选择Leaks---->Choose.

四,选择Choose后,会弹出如下界面。默认是选择Allocations的。

五,选择Leaks.

六,选择左上角的红色的圆圈,红色的圆圈变成黒色的方型。此时,开始运行工程,检测循环引用。

七,会出现如下的界面。

八,点击黑色的圆圈,此时又变为红色圆圈,暂时停止循环引用的检测。

九,此时循环检测完成。在Leaks中出现了一条红色的线条,此线条表示一次内存泄漏的产生。

=============================================

block中多次调用self的问题解决:在block中使用__strong:https://www.jianshu.com/p/d2f551370890

__weak:https://blog.csdn.net/lixuezhi86/article/details/81839906

objc_autorelease:将对象注册到autoreleasepool中,因为对象为弱引用在访问的过程中随时都有可能释放,如果那它加入到autoreleasepool中,那么在autoreleasepool未释放之前对象可以放心使用了。

block中的循环引用是这样的:某个对象有一个copy或者strong的block成员变量或者属性,这时block内部直接引用了成员变量或者self,这样就产生了self持有block成员,block成员持有self,就会导致循环引用。因为self本身就是一个strong类型的变量。苹果官方的建议是:传进block之前,把self转换成weak automatic的变量,这样在block中就不会出现对self的强引用。如果在block执行完成之前,self被释放,weakSelf也会置为nil。weak类型相对比较安全,因为可以在释放后自动置为nil,不会引起野指针。那么如何来声明呢?

1.IOS5.0推出的weak

__weak typeof(self) weakSelf = self;

这句话的意思是声明了一个self类型的weak指针,名字叫做weakSelf.  typeof是用来求参数类型的,这里也就是来求self的类型。这样定义出的weakSelf就是和self是一个类型,并且是原self的一个弱引用。

以下几种写法同一个意思:

 

__weak typeof(&*self)weakSelf = self;// 我之前一直这么写的
__weak typeof(self) weakSelf = self;
// 或者这么写
__weak XxxViewController *weakSelf = self;
// 或者这么写
__weak id weakSelf = self;

2. iOS4.0推出的

    __unsafe_unretained typeof(self) weakSelf = self;

==================

NSTImer的循环引用问题

使用NSTimer可能会碰到循环引用的问题。特别是当类具有NSTimer类型的成员变量,并且需要反复执行计时任务时。例如

_timer = [NSTimer scheduledTimerWithTimeInterval:5.0target:selfselector:@selector(startCounting) userInfo:nilrepeats:YES];

类有一个成员变量_timer,给_timer设置的target为这个类本身。这样类保留_timer_timer又保留了这个类,就会出现循环引用的问题,最后导致类无法正确释放。

解决这个问题的方式也很简单,当类的使用者能够确定不需要使用这个计时器时,就调用

[_timer invalidate];
_timer = nil;

这样就打破了保留环,类也可以正确释放。但是,这种依赖于开发者手动调用方法,才能让内存正确释放的方式不是一个非常好的处理方式。所以需要另外一种解决方案。如下所示:

@interface NSTimer (JQUsingBlock)
+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)tiblock:(void(^)())blockrepeats:(BOOL)repeats;
@end@implementation NSTimer (JQUsingBlock)+ (NSTimer *)jq_scheduledTimerWithTimeInterval:(NSTimeInterval)tiblock:(void(^)())blockrepeats:(BOOL)repeats{return [self scheduledTimerWithTimeInterval:titarget:selfselector:@selector(jq_blockInvoke:)userInfo:[block copy]repeats:repeats];
}+ (void)jq_blockInvoke:(NSTimer *)timer{void(^block)() = timer.userInfo;if (block) {block();}
}@end

定义一个NSTimer的类别,在类别中定义一个类方法。类方法有一个类型为块的参数(定义的块位于栈上,为了防止块被释放,需要调用copy方法,将块移到堆上)。使用这个类别的方式如下:

__weak ViewController *weakSelf = self;
_timer = [NSTimer jq_scheduledTimerWithTimeInterval:5.0block:^{__strong ViewController *strongSelf = weakSelf;[strongSelf startCounting];}repeats:YES];

使用这种方案就可以防止NSTimer对类的保留,从而打破了循环引用的产生。__strong ViewController *strongSelf = weakSelf主要是为了防止执行块的代码时,类被释放了。在类的dealloc方法中,记得调用[_timer invalidate]

===================

使用Delegate也可能遇到循环引用问题,要用weak修饰Delegate

=======================

使用__block 时的循环应用,只要调用以下block就可以解除循环应用;

利用__block解决循环的做法。例子4:

#import "ViewController.h"
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];__block Student *stu = student;student.name = @"Hello World";student.study = ^{NSLog(@"my name is = %@",stu.name);stu = nil;};
}
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];__block Student *stu = student;student.name = @"Hello World";student.study = ^{NSLog(@"my name is = %@",stu.name);stu = nil;};
}

这样写会循环么?看上去应该不会。但是实际上却是会的。

由于没有执行study这个block,现在student持有该block,block持有__block变量,__block变量又持有student对象。3者形成了环,导致了循环引用了。 想打破环就需要破坏掉其中一个引用。__block不持有student即可。

只需要执行一下block即可。例子5:

#import "ViewController.h"
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];student.name = @"Hello World";__block Student *stu = student;student.study = ^{NSLog(@"my name is = %@",stu.name);stu = nil;}; student.study();
} student.study();
}

这样就不会循环引用了。

=====================以下会出现循环应用

#import <Foundation/Foundation.h>
typedef void(^Study)();
@interface Student : NSObject
@property (copy , nonatomic) NSString *name;
@property (copy , nonatomic) Study study;
@end
typedef void(^Study)();
@interface Student : NSObject
@property (copy , nonatomic) NSString *name;
@property (copy , nonatomic) Study study;
@end
#import "ViewController.h"
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];student.name = @"Hello World";student.study = ^{NSLog(@"my name is = %@",student.name);};
}
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];student.name = @"Hello World";student.study = ^{NSLog(@"my name is = %@",student.name);};
}

到这里,大家应该看出来了,这里肯定出现了循环引用了。student的study的Block里面强引用了student自身。根据上篇文章的分析,可以知道,_NSConcreteMallocBlock捕获了外部的对象,会在内部持有它。retainCount值会加一。

这里形成环的原因block里面持有student本身,student本身又持有block;

block内部使用了外面强引用的student对象,block代码块的内部会自动产生一个强引用,引用着student对象!所以上面的student对象不会被销毁,造成循环引用!

//===========以下这种情况不会出现循环应用

#import "ViewController.h"
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];student.name = @"Hello World";student.study = ^(NSString * name){NSLog(@"my name is = %@",name);};student.study(student.name);
}
#import "Student.h"@interface ViewController ()
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];student.name = @"Hello World";student.study = ^(NSString * name){NSLog(@"my name is = %@",name);};student.study(student.name);
}

我把block新传入一个参数,传入的是student.name。这个时候会引起循环引用么?

答案肯定是不会。

并不会出现内存泄露。原因是因为,student是作为形参传递进block的,block并不会捕获形参到block内部进行持有。所以肯定不会造成循环引用

=====================以下不会出现循环应用

#import "ViewController.h"
#import "Student.h"@interface ViewController ()
@property (copy,nonatomic) NSString *name;
@property (strong, nonatomic) Student *stu;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];self.name = @"halfrost";self.stu = student;student.study = ^{NSLog(@"my name is = %@",self.name);};student.study();
}
#import "Student.h"@interface ViewController ()
@property (copy,nonatomic) NSString *name;
@property (strong, nonatomic) Student *stu;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Student *student = [[Student alloc]init];self.name = @"halfrost";self.stu = student;student.study = ^{NSLog(@"my name is = %@",self.name);};student.study();
}

ViewController虽然强引用着student,但是student里面的blcok强引用的是viewController的name属性,并没有形成环。如果把上述的self.name改成self,也依旧不会产生循环引用。因为他们都没有强引用这个block。

===================

Apple 官方的建议是,传进 Block 之前,把 ‘self’ 转换成 weak automatic 的变量,这样在 Block 中就不会出现对 self 的强引用。如果在 Block 执行完成之前,self 被释放了,weakSelf 也会变为 nil。

示例代码:

__weak __typeof__(self) weakSelf = self;    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

[weakSelf doSomething];

});

clang 的文档表示,在 doSomething 内,weakSelf 不会被释放。但,下面的情况除外:

__weak __typeof__(self) weakSelf = self;  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

[weakSelf doSomething];

[weakSelf doOtherThing];

});

在 doSomething 中,weakSelf 不会变成 nil,不过在 doSomething 执行完成,调用第二个方法 doOtherThing 的时候,weakSelf 有可能被释放,于是,strongSelf 就派上用场了:

__weak __typeof__(self) weakSelf = self;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

__strong __typeof(self) strongSelf = weakSelf;

[strongSelf doSomething];

[strongSelf doOtherThing];

});

__strong 确保在 Block 内,strongSelf 不会被释放。

总结

1 在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。

2 如果在 Block 内需要多次 访问 self,则需要使用 strongSelf。

AFN框架中的例子:

__weak __typeof(self)weakSelf = self;

AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {

__strong __typeof(weakSelf)strongSelf = weakSelf;

strongSelf.networkReachabilityStatus = status;

if (strongSelf.networkReachabilityStatusBlock) {

strongSelf.networkReachabilityStatusBlock(status);

}

};

***********僵尸对象:

参考:https://www.jianshu.com/p/f6e6b4f21ca2

程序崩在了一个方法里,并且报错 “Thread 1:EXC_BAD_ACCESS(code=1,address=0x4000)”,这种错误通常是内存管理的问题,一般是访问了已经释放的对象导致的,可以开启僵尸对象(Zombie Objects)来定位问题。

第一步:还是打开Xcode 选择屏幕左上角Xcode-> PReferencese,不过我们这次是要设置一下输出信息,调试的时候输出更多的信息;

第二步:再对环境变量进行设置:菜单Product > Scheme > Edit Scheme;Guard malloc、zombie object、malloc stack前打勾

************成员变量在block中循环引用解决:

strongSelf修饰的self 必须为 __weak 修饰过以后的self。

__weak typeof(self) weakSelf = self;

__strong typeof(weakSelf) strongSelf = weakSelf;

BlockView *view = [BlockView new];
    __weak typeof (self)weak = self;
    view.myBlock = ^{
        // 会循环引用
        _money = @"10元";
        // @property修饰的用下面的不会循环引用
        weak.name = @"xiaobing";

// 私有成员变量避免循环引用方法
        __strong typeof(weak) sself = weak;
        sself->_text = @"循环引用";
    };

[self.view addSubview:view];

iOS循环引用问题集合、内存泄漏、僵尸对象、代码静态分析相关推荐

  1. iOS 循环引用 委托 (实例说明)

    如何避免循环引用造成的内存泄漏呢: 以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时 ...

  2. iOS 自动引用计数和内存泄露

    自动引用计数与解决内存泄露 自动引用计数主要用于管理和释放内存. 引用计数 我们在创建一个对象的时候,系统会为其分配内存,而什么时候和谁来释放对象内存成了问题,如果不释放,就会导致内存不足.所以苹果公 ...

  3. iPhone开发资料之内存管理 ,循环引用导致的内存问题

    iPhone开发资料之内存管理 ,循环引用导致的内存问题 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual ...

  4. Lua弱引用表处理普通的内存泄漏

    Lua中有垃圾回收机制(GC)的,支持GC的对象有五种string,table,function,full userdata,thread,理论上不会有内存泄漏,但是进行GC时,如果这个对象还有引用, ...

  5. 防止网络请求(或其他回调)引用,从而造成内存泄漏

    本文的解决方案用来解决类似如:Activity请求网络,而回调传的是自身,造成Activity执行finish()后并没有被销毁,而是被网络请求持有.和其相类似的问题 正文 1.网络请求使用Activ ...

  6. [iOS] 使用 blockable NSTimer 避免内存泄漏

    背景 此知识点,从阅读<Effective Objective-C>中学习到,现扩展到 Swift 并兼容 iOS 10+ NSTimer 提供定时执行任务的功能,可用于延时或者重复处理事 ...

  7. iOS中需要避免的内存泄漏总结

    一.从AFNetWorking说起 对于AFNetWorking的使用我们通常会对通用参数.网址环境切换.网络状态监测.请求错误信息等进行封装.在封装网络请求类时需注意的是需要将请求队列管理者AFHT ...

  8. android 集合 内存泄漏,Android内存泄漏第二课--------(集合中对象没清理造成的内存泄漏 )...

    一.我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大.如果这个集合是static的话,那情况就更严重 ...

  9. 你不必使用弱引用以避免内存泄漏

    本文翻译自https://medium.com/google-developer-experts/weakreference-in-android-dd1e66b9be9d#.7gyh5qy6l 我的 ...

最新文章

  1. 选择一线一张床还是小城一套房?
  2. 修改 cmd 控制台默认代码页编码的几种方法【GBK、UTF-8】
  3. nginx alias
  4. nodejs request module里的json参数的一个坑
  5. php数据库postgresql,PHP 操作 PostgreSQL数据库
  6. java主流微服务框架_Spring Boot作为当下最流行的微服务开发框架,一名合格的Java开发者一定有所了解,...
  7. 一行代码引来的安全漏洞,就让我们丢失了整个服务器的控制权
  8. [有限元] Ansys Workbench Mechanical 中的应力应变显示类型的文档翻译
  9. wifi两种工作模式
  10. (70)Verilog HDL测试激励:复位激励2
  11. Netty工作笔记0020---Selectionkey在NIO体系
  12. Linux kernel中网络设备的管理
  13. 计算机最大化快捷键,最大化窗口快捷键,mac窗口最大化快捷键
  14. AD19导出bom表的方法(按照元件不同数值分类,重点信息突出)
  15. 报告总监,他...在代码里面 “下毒” 了
  16. 数据结构(八)——后缀表达式
  17. python 生成pdf 文字和图片_Python系列—PDF文本与图片抽取
  18. 计算机毕业设计ssm基于web的社团管理系统r848z系统+程序+源码+lw+远程部署
  19. 计算机策略组 网络,组策略
  20. 安卓手机远程控制DIY智能家居设备(ESP8266)

热门文章

  1. 政府行政管理思维与互联网思维
  2. 通过扫码下载安卓和ios安装包
  3. larval-admin
  4. nand2tetris 布尔函数和和门逻辑路线图
  5. 零界之痕30号服务器维护,零界之痕12月9日更新了什么 12月9日更新维护公告介绍...
  6. Apex英雄手游国服何时上线 Apex英雄手游和端游互通吗
  7. Blurring the Lines between Blockchains andDatabase Systems: the Case of Hyperledger Fabric(翻译)
  8. 对populate()方法的理解
  9. 管理员同志,回收站博文希望得到恢复,万分感谢
  10. 没经验能做seo专员吗