对于一款App来说,内存管理一直是iOS开发的一个重点。APP占用太大内存,会导致内存泄漏、内存消耗太大。所以内存优化可以说是性能优化中较为重要的一部分内容了。如果应用占用内存过大,轻则应用卡顿降低用户体验,重则内存溢出(OOM),程序崩溃。所以选择合适的算法和数据结构永远是开发人员最先应该考虑的事情,可以借用友盟+u-apm这款工具,作为助手针对App的内存分析问题进行检测。
内存分析方式:
静态内存分析
动态内存分析
1.静态分析(Analyze)
不运行程序,直接检测代码中是否有潜在的内存问题(不一定百分百准确,仅仅是提供建议)
结合实际情况来分析,是否真的有内存问题
2.动态分析(友盟U-APM)
运行APP,打开友盟后台查看App在所选时间中发生OOM异常的整体趋势、异常分布和异常列表
运行APP,利用友盟查看内存占用情况
二、内存方面常见问题:1、UIGraphicsEndImageContextUIGraphicsBeginImageContext和UIGraphicsEndImageContext必须成双出现,不然会造成context泄漏。另外XCode的Analyze也能扫出这类问题。2、无论是打开网页,还是执行一段简单的js代码,UIWebView都会占用APP大量内存。而WKWebView不仅有出色的渲染性能,而且它有自己独立进程,一些网页相关的内存消耗移到自身进程里,最适合取替UIWebView。不过目前苹果已经强制iOS开发者使用WKWebView3、autoreleasepool通常autoreleased对象是在runloop结束时才释放。如果在循环里产生大量autoreleased对象,内存峰值会猛涨,甚至出现OOM。适当的添加autoreleasepool能及时释放内存,降低峰值。4、互相引用比较容易出现互相引用的地方是block里使用了self,而self又持有这个block,只能通过代码规范来避免。另外NSTimer的target、CAAnimation的delegate,是对Obj强引用。使用的时候要注意。5、大图片处理举个例子一般图片缩放接口是这样写的:
(UIImage)scaleImage:(UIImage)imagenewSize:(CGSize)newSize{UIGraphicsBeginImageContextWithOptions(newSize,NO,0);[imagedrawInRect:CGRectMake(0,0,newSize.width,newSize.height)];UIImage*newImage=UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();returnnewImage;}但处理大分辨率图片时,往往容易出现,原因是-[UIImagedrawInRect:]在绘制时,先解码图片,再生成原始分辨率大小的bitmap,这是很耗内存的。解决方法是使用更低层的ImageIO接口,避免中间bitmap产生:
(UIImage)scaleImageWithData:(NSData)datawithSize:(CGSize)sizescale:(CGFloat)scaleorientation:(UIImageOrientation)orientation{CGFloatmaxPixelSize=MAX(size.width,size.height);CGImageSourceRefref=CGImageSourceCreateWithData((__bridgeCFDataRef)data,nil);NSDictionary*options=
{(__bridgeid)kCGImageSourceCreateThumbnailFromImageAlways:(__bridgeid)kCFBooleanTrue,(__bridgeid)kCGImageSourceThumbnailMaxPixelSize:[NSNumbernumberWithFloat:maxPixelSize]};CGImageRefimageRef=CGImageSourceCreateThumbnailAtIndex(ref,0,(__bridgeCFDictionaryRef)options);UIImage*resultImage=[UIImageimageWithCGImage:imageRefscale:scaleorientation:orientation];CGImageRelease(imageRef);CFRelease(ref);returnresultImage;}6、大视图大视图是指View的size过大,自身包含要渲染的内容。比如