iOS内存优化

1、运行MemoryProblems后,运行崩溃出现EXC_BAD_ACCESS,启动NSZombieEnabled,选中Edit Scheme并点击,Run -> Diagnostics -> Enable Zombie Objects(悬挂指针的检测),设置完之后,再次运行和点击页面,虽然会再次crash,但这次控制台打印了有用信息,点击Continue program execution按钮继续运行,对比找到相同地址并修改(启动MallocStackLogging

常见原因:某变量被assign修饰,对变量值后,它的对象就马上释放,而变量也不是strong而是weak,此时仍然使用就会导致程序crash


2、手动静态分析:应用Product—>Analyze或捷键shift + command + b进行内存泄漏的初步检测

    自动静态分析:在Build Settings启用Analyze During 'Build',每次编译时都会自动静态分析


3、可以在xcode的build setting中打开implicit retain of ‘self’ within blocks,xcode编译器会给出警告,逐个排查警告


4、应用Leak Instrument进行内存泄露查找:点击Xcode的菜单栏的 Product -> Profile 启动Instruments,出现Instruments的工具集,选中Leaks子工具点击,点击红色圆点按钮启动Leaks工具,在Leaks工具启动同时,模拟器或真机也跟着启动,启动Leaks工具后,它会在程序运行时记录内存分配信息和检查是否发生内存泄露

首先点击Leak Checks时间条那个红色叉,点击红色叉后,下面显示Leaks By Backtrace,双击某行内存泄露调用栈,会直接跳到内存泄露代码位置

Leak Instrument有Cycles & Roots界面:Persistent Bytes和#Persistent。#Persistent是object的数量,也就是allocation的次数,而Persistent Bytes是具体的内存大小。#Persistent是我们需要关注的,内存有没有泄露也是看这个值是不是只增不减。

Allocations:启动Allocations,勾选列表最上边的,右边设置勾选:Discard unrecorded data upon stop、Identify virtual C++ objects、* isContain…Record 

列表勾选VM

Generation Analysis

这个功能是非常有用的,一般是这样用的:进入一个页面前mark一下,在退出这个页面的时候再mark一下可以比较哪些内容增加了,就可以具体分析哪些内存没有被释放


Call Tree:需要我们把列表展示类型切换成Call Trees,能够非常清晰的看到调用树

Separate by Category:按照类别隔开,我们钩上看看效果

Separate by Thread:按照线程划分,我个人不是很喜欢这种划分,因为我不是很关心线程

Invert Call Tree:反转调用,我们给一张对比图就不需要解释了

Hide System Libraries:这个似乎是必钩的,因为我们目前只关心自己的方法,不关心系统的

Flatten Recursion:扁平化递归


Data Mining:数据挖掘,这是一个很具有噱头的功能

点击Symbol、Library会自动把你选中的行的符号、库加到小框中

符号和库有两个选项,就是是否过滤改行;点击Restore会去掉小框中的选中行



5、通过查看dealloc是否调用查看某个class是否泄漏问题

- (void)dealloc

{

    NSLog(@"release XXXXViewController");

}

方法: __weak XXXXViewController *weakSelf = self;在Block里用weakSelf


常见问题:

1、UITextField在iOS 11内存泄漏问题:UITextField没释放原因使用secureTextEntry属性,解决方案

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {

    if (textField == self.passWordTextField) {

        textField.secureTextEntry = YES;

    }else {

        textField.secureTextEntry = NO;

    }

    return YES;

}


2、使用CGMutablePathRef path = CGPathCreateMutable();时出现Potential leak of an object stored into 'path’解决方案

CGPathRelease(path);

creat,copy作为关键字的函数都是需要释放内存的,注意配对使用。比如:CGColorCreate<-->CGColorRelease


3、The 'viewWillDisappear:' instance method in UIViewController subclass 

XXX is missing a [super viewWillDisappear:] callm,解决方案

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

}


4、调用

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

方法之后在不需要NSTimer时及时调用[self.timer invalidate];千万不要在dealloc方法中调用,因为NSTimer强引用self,所以不会执行dealloc方法。


5、对象之间的循环引用:例子:两个ViewController都需要使用对方,这个时候可以用@class ; 

说明:在 .h 中引入某个类, @class 指的是 当前文件 只是引入类名, 并没有使用类里面的东西. 想要在 .m 里面使用 类的内容的话, 还是要 #import <>, 这种情况跟 上面的对象之间的防止循环引 有点不一样


6、如果是C申请的内存,注意new delete, malloc free的配对处理。


7、图片相关:

缓存:imageNamed:

只需传入文件名.扩展名即可。

可以加载bundle中任意位置的图片,包括main bundle中其他bundle的。

imageNamed方法创建对象的步骤如下:

7.1根据图片文件名在缓存池中查找图片数据,如存在,则创建对象并返回;

7.2如果不存在,则从bundle中加载图片数据,创建对象并返回;

7.3如果相应的图片数据不存在,返回nil。

不缓存:imageWithContentsOfFile:

必须传入图片文件的全名(全路径+文件名)

无法加载Images.xcassets中的图片。

对于大的图片且偶尔需要显示的应放到工程目录下,不要放到Assets.xcassets中;并使用imageWithContentsOfFile加载不让系统缓存

background.image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/*.png"]];

对于经常需要展示的小图片放到Assets.xcassets中让系统缓存,使用imageNamed加载

background.image = [UIImage imageNamed:@"*.png"];


不常用大图:将imageView.image = [UIImage imageNamed:nameArr[index]];

改为imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:nameArr[index] ofType:@"png"]];


8、出现VM:CG raster data,SDWebImage的问题

需要在Appdelegate中设置一下

[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];

[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];

[[SDImageCache sharedImageCache] setShouldCacheImagesInMemory:NO];


9、VM:CoreAnimation

Found out that animation caused by the inner pages.

Inside the pageViewController(viewController that added to the scrollView as a page) on viewWillDisappear:(BOOL)animated method I added this

for (CALayer* layer in [self.view.layer sublayers]) {

        [layer removeAllAnimations];

}

it resolved the problem.


10、@property (readwrite, nonatomic, copy) NSMutableURLRequest *request;出现Property of mutable type 'NSMutableURLRequest' has 'copy' attribute; an immutable object will be stored instead,解决方案

@property (readwrite, nonatomic, strong) NSMutableURLRequest *request;


猜你喜欢

转载自blog.csdn.net/u013069892/article/details/80495272