- DB的block如果捕获到比较大的数据量(假设是数组A),且DB的block这样的操作比较繁密的情况底下,会造成block的堆积,进而造成block捕获到的数组A的内存堆积,最终有可能会导致内存涨到被系统杀掉。
实际上是通式:会被延迟执行的block中捕获的数据量不小(_a),且有可能这个操作后面会频繁调用(_b)的话会导致内存的堆积。
所以我们要么:不让他捕获那么大的数据量,改成单例(_a处下手),要么不要频繁调用这样的延迟带block的操作(_b处下手)。
- Swift的设计模式书中第4章提到,对象模版模式。暂时的理解,思想类似于工厂模式。作者举的例子是:
用swift的元组作为数据结构进行存储,修改,然后在传参的时候直接传一整个元组过去的时候,当数据结构发生修改,其对应的接口,都要进行相应的修改。
// 假设对应表示着:名字,数量,价格
//[(String,Int,Double)] 改成[String,Double]//假设这个数据结构我们这里称他为组件b
func oldFunc1(sth:(String,Int,Double))->String {
return sth.0 + "\(1 + sth.2 * sth.2)";
}
func oldFunc1_ver2(sth:(String,Double))->String {// 发生改变
return sth.0 + "\(1 + sth.1 * sth.1)";// 发生改变
}
上面这个例子中的oldFun1(组件a)就紧耦合于组件b(这个元组),b发生任何改变,oldFun1等一系列和组件b有紧耦合的部分都要修改。
后续给出的作为对象模版模式的例子是将这个元组,封装成对象。
func oldFunc1_verCorrect(data:SomeData)->String {
return data.name + "\(1 + data.price * data.price)";
}
- 另外描述下之前比较纠结的一个点:请求B是最终获取数据进行展示的请求(会带有参数b,有默认值:$$$,但有可能会是上次请求的值),请求A是用于校验参数b本身正确与否的,如果不正常,应当用b默认参数$$$发起一个新的请求B(B2)。当时想到的解决方案是:同时发起AB,存在的问题是:B2和一开始的B1有可能有覆盖的问题,所以就用了标志位来解决这个问题,写得代码写得有点复杂。想到的最完美的是,服务端做b的校验,在返回的结果中,带上正确的b。
// 要在跟随列表reloadData之后才能更新layout.不然layout使用的为缓存的值
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UICollectionView received layout attributes for a cell with an index path that does not exist: <NSIndexPath: 0xabc64847c85f5fd9> {length = 2, path = 0 - 0}'
- 没懂..UIViewContentModeScaleAspectFill和另外自己做离屏渲染裁剪好的照片再来设置,两者效率,之类有什么差别吗?((按照引用部分的解释,一个是在解码的时候占了资源,另外一个是生成中间位图bitmap大量内存)以下引用涵盖一个大图片的内存优化的指引)
图片内存使用优化
1.使用适当尺寸的图片
我们知道,解压后的图片是由一个个像素点组成的。每个像素点一般有R、G、B、A(红绿蓝透明度)四个通道,每个通道是8位,因此一个像素通常占用4字节。对于一张图片,如果同样是300*300分辨率的jpeg和png两张图,文件大小可能差几倍,但是渲染后的内存开销是完全一样的。
而由于机型的不同,下载的图片经常与最终展示在界面上的尺寸不同。如果我们将一张矩形图片展示在很小的view里,原图解压会消耗大量内存,但最终大部分像素最终都被丢掉浪费了。或者将图片手动缩放成合适大小,处理过程中仍然可能会多占用一部分内存。因此,我们与服务端共同制定了一套方案,在服务端将图片裁剪成控件的精确尺寸(记得乘上屏幕缩放比例[UIScreen mainScreen].scale)下发到不同机型,从根本上将内存使用降低。
出自《你真的了解OOM吗?——京东iOS APP内存优化实录》
但是,文章中同时也指出,图片的缩放方案采用ImageIO的写法能比普通的缩放写法更节省内存
3.注意图片缩放方式
参考Apple的 WWDC18 Session 416 —— iOS Memory Deep Dive,处理图片缩放时,直接使用UIImage会在解码时读取文件占用一部分内存,还会生成中间位图bitmap消耗大量内存,而ImageIO不存在上述两种内存消耗,只会占用最终图片大小的内存。(此处可以参考Linux的mmap内存映射)
/// 常见的UIimage缩放写法:
- (UIImage *)scaleImage:(UIImage *)image newSize:(CGSize)newSize{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
/// 节约内存的ImageIO缩放写法:
+ (UIImage *)scaledImageWithData:(NSData *)data withSize:(CGSize)size scale:(CGFloat)scale orientation:(UIImageOrientation)orientation{
CGFloat maxPixelSize = MAX(size.width, size.height);
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)data, nil);
NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways : (__bridge id)kCFBooleanTrue,
(__bridge id)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithFloat:maxPixelSize]};
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (__bridge CFDictionaryRef)options);
UIImage *resultImage = [UIImage imageWithCGImage:imageRef scale:scale orientation:orientation];
CGImageRelease(imageRef);
CFRelease(sourceRef);
return resultImage;
}
同样出自《你真的了解OOM吗?——京东iOS APP内存优化实录》
网友评论