https://blog.csdn.net/a184251289/article/details/82589128
一、为什么需要内存优化
The easy answer is users have a better experience.
Not only will your app launch faster.
The system will perform better.
Your app will stay in memory longer.
Other apps will stay in memory longer.
Pretty much everything’s better.
二、内存管理
Objective-C语言本身是支持垃圾回收机制的,但有平台局限性,仅限于Mac桌面系统开发中,而在iPhone和iPad等苹果移动终端设备中是不支持垃圾回收机制的。在移动设备开发中的内存管理是采用MRC(Manual Reference Counting)以及iOS5以后的ARC(Automatic Reference Counting),本质都是RC引用计数,通过引用计数的方式来管理内存的分配与释放,从而防止内存泄漏。
内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
三、常见问题
内存问题主要包括两个部分,一个是iOS中常见循环引用导致的内存泄露 ,另外就是大量数据加载及使用导致的内存警告。
1、mmap
虽然苹果并没有明确每个App在运行期间可以使用的内存最大值,但是有开发者进行了实验和统计,一般在占用系统内存超过20%的时候会有内存警告,而超过50%的时候,就很容易Crash了,所以内存使用率还是尽量要少,对于数据量比较大的应用,可以采用分步加载数据的方式,或者采用mmap方式。mmap 是使用逻辑内存对磁盘文件进行映射,中间只是进行映射没有任何拷贝操作,避免了写文件的数据拷贝。 操作内存就相当于在操作文件,避免了内核空间和用户空间的频繁切换。之前在开发输入法的时候 ,词库的加载也是使用mmap方式,可以有效降低App的内存占用率。
1>Cell的重用机制,包括UITableView、UICollectionView。
2、循环引用
循环引用是iOS开发中经常遇到的问题,尤其对于新手来说是个头疼的问题。循环引用对App有潜在的危害,会使内存消耗过高,性能变差和Crash等,iOS常见的内存主要以下三种情况:
1>Delegate
代理声明为weak是一个即好又安全的做法 @property (nonatomic, weak) id <MyCustomDelegate> delegate;
2>NSTimer
使用类方法
使用weakProxy
使用GCD timer
3>Block
3、其他
1>NSNotification addObserver之后,在dealloc里面添加remove。
2>动画的repeat count无限大,而且也不主动停止动画,基本就等于无限循环。
3>forwardingTargetForSelector不能返回self。
4>UIGraphicsBeginImageContext之后调用UIGraphicsEndImageContext。
5>C语法,malloc之后调用free。
6>CoreFoundation
7>明确标注需要release的函数。
SecPKCS12Import、protocol_copyMethodDescriptionList等
四、内存占用
五、检测工具
1、Xcode Memory Debugger
2、Instruments
3、FBRetainCycleDetector
FBAlloca1onTracker
FBMemoryProfiler
4、MLeaksFinder
摘要
https://developer.apple.com/videos/play/wwdc2018/416/
https://juejin.im/post/5b23dafee51d4558e03cbf4f
https://blog.csdn.net/cordova/article/details/60958978
https://juejin.im/post/58ca0832a22b9d006418fe43
iOS最全图片内存优化
https://blog.csdn.net/weixin_33674437/article/details/88181214
2018年07月30日 14:04:00 weixin_33674437 阅读数:25
在加载大量图片的时候,尤其是一些高清大图的时候如果不做什么处理,很容易导致APP内存溢出,软件闪退的问题。
在加载图片的时候,我们一般使用SDWebimage框架,所以,下面的处理方法,我们也是以SDWebimage框架来处理。
清理缓存
最简单的一个操作就是监听tableView的滚动事件,当进行了滚动的时候进行缓存的清理来减少内存。
[[SDWebImageManager sharedManager].imageCache clearMemory];
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];//建议使用这句话,效果更好
更改图片加载方式
我们一般加载本地图片的时候都是使用图片的名称来加载图片,但是这种加载方式会先把图片加载到内存中,所以如果图片很大的话,就会影响到内存,所以,建议使用NSData的方法来加载图片。
[UIImage imageNamed:ImageName];
//更换为
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
NSData *image = [NSData dataWithContentsOfFile:filePath];
[UIImage imageWithData:image];
进行缓存清理
监听scrollView的滚动事件,一旦滚动就清理缓存
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
}
监听内存警告,一旦收到内存警告就清理缓存
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
[[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
}
减少图片体积
内存溢出的主要原因是因为图片体积过大,所以,我们可以减少图片的体积来达到减少内存的溢出
方法一:
把图片转为jpg格式,并且压缩图片像素,会导致图片模糊,CPU使用上升,但是内存会下降。
NSData *imageData = UIImageJPEGRepresentation(image, 0.5);//取值范围0~1
UIImage *ipgImage = [UIImage imageWithData:imageData];
方法二:
在SDWebimage中修改下载的图片体积,SDWebimageManager.m文件中添加如下代码,会导致图片模糊,CPU使用上升,但是内存会下降。
-(UIImage *)compressImageWith:(UIImage *)image
{
float imageWidth = image.size.width;
float imageHeight = image.size.height;
CGSize croppedSize;
CGFloat offsetX = 0.0;
CGFloat offsetY = 0.0;
if (imageWidth > imageHeight) {
offsetX = (imageWidth -imageHeight) / 2;
croppedSize = CGSizeMake(imageHeight, imageHeight);
} else {
offsetY = (imageHeight-imageWidth) / 2;
croppedSize = CGSizeMake(imageWidth, imageWidth);
}
CGRect clippedRect = CGRectMake(offsetX, offsetY, croppedSize.width, croppedSize.height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
float ratio = croppedSize.width>120?120:croppedSize.width;
CGRect rect = CGRectMake(0.0, 0.0, ratio, ratio);
UIGraphicsBeginImageContext(rect.size);
[[UIImage imageWithCGImage:imageRef] drawInRect:rect];
UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRelease(imageRef);
return thumbnail;
}
然后我们要让图片来进行这个减少提交操作
//在获取到内存中的图片进行体积减少操作
else if (cachedImage) {
cachedImage = [self compressImageWith:cachedImage];//修改图片大小
[self callCompletionBlockForOperation:strongOperation completion:completedBlock image:cachedImage data:cachedData error:nil cacheType:cacheType finished:YES url:url];
[self safelyRemoveOperationFromRunning:strongOperation];
} else {
//在下载完成后对图片进行体积减少操作
if (downloadedImage && finished) {//修改图片大小
[self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil];
downloadedImage = [self compressImageWith:downloadedImage];
downloadedData = [NSMutableData dataWithData:UIImageJPEGRepresentation(downloadedImage, 1)];
// if (self.cacheSerializer) {
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// NSData *cacheData = self.cacheSerializer(downloadedImage, downloadedData, url);
// [self.imageCache storeImage:downloadedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
// });
// } else {
// [self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil];
// }
}
[self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:downloadedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
---------------------
作者:weixin_33674437
来源:CSDN
版权声明:本文为博主原创文章,转载请附上博文链接!
原文:https://www.cnblogs.com/sundaysgarden/p/10846993.html