1,defer的理解不到位,这个崩溃0.7%,总共300个崩溃,它一个崩溃就占了70多个。
var imageData: UnsafeMutableRawPointer!
if needRedraw {
imageData = UnsafeMutableRawPointer.allocate(byteCount: length, alignment: 4)
guard let context = imageContext else {
throw AnyError("failed to init CGContext")
}
defer {
imageData.deallocate()
}
}
return imageData
大家来看看上述代码有什么问题?
问题1:defer写在了throw后边,当项目有Error throw时,这里就产生了内存泄露,因为throw后边的代码根本不会执行。
解决1:那怎么解决呢?首选大家想到defer最好紧跟在UnsafeMutableRawPointer.allocate下面写就好了嘛,对不对?那上述代码就变成了:
var imageData: UnsafeMutableRawPointer!
if needRedraw {
imageData = UnsafeMutableRawPointer.allocate(byteCount: length, alignment: 4)
defer {
imageData.deallocate()
}
guard let context = imageContext else {
throw AnyError("failed to init CGContext")
}
}
return imageData
大家再看上述代码有什么问题呢?
这里考验大家对defer的理解了,那我问一下,这里的defer在哪行代码执行完后释放呢?大家可能会说return后执行,这是错的,实际defer在if的作用域走完后就释放了,导致return的imageData变成了空的,直接崩溃了。
最后大家再来看看firebase这个堆栈:
swift_slowAlloc你能看明白这是个什么鬼吗?没解决过这种崩溃的绝对一头雾水,心里一万个草泥马汹涌而过,这咋解,然而细节决定成本,答案就隐藏在细节中,不停的细扣,写demo测试,网上搜索,你才能把这个堆栈跟上述问题及解决方案联系到一块去,最终把这个问题解决掉。
2,RTRootNavigationController引起的崩溃:
引入这个三方库呢是为了解决系统导航条显示隐藏push、pop、侧滑的动画不平滑问题,加了这个库之后外层会有一个大的RootNavigationController,然后每一个viewController会有一个自己的ContainerNavigationController,这样显示隐藏只要设置内部的导航条即可,动画无比的流畅。
但是现在这个库有27个崩溃,崩溃率在当时占0.27%,但看这个堆栈死活看不出问题来,最后带着尝试的态度把containerNavigationController的tabBarController方法给注掉了,因为看了一下里边代码,没有系统会自动处理这个方法,注掉后这个问题没有了。
3,AVMutableAudioMixInputParameters传入的timeRange invalid的问题
parameters.setVolumeRamp(fromStartVolume: volume, toEndVolume: volume, timeRange: data.timeRange)
我同事写的音视频编辑器传入的这个data.timeRange传入的值存在invalid的问题,将这行代码修改为:
var timeRange = CMTIMERANGE_IS_VALID(data.timeRange) ? data.timeRange : .zero
parameters.setVolumeRamp(fromStartVolume: volume, toEndVolume: volume, timeRange: timeRange)
4,优化智能生成图片的压缩,在55张素材的情况下iphone8从高峰1.2G内存崩溃一直降到高峰600M
实际使用发现在智能生成里图片没有进行压缩,直接使用的相册选择的超高清分辨率的素材,增加了根据设备型号进行分级返回压缩尺寸,然后进行压缩,从而降低内存使用,降低OOM引起的崩溃。
5,优化智能生成根据素材数量进行的压缩操作,在iPad下素材数量很多时优化前占用1.9G内存,优化后占用778M
实际使用发现智能生成中没有根据素材数量来实现不同等级的尺寸压缩,新增代码实现素材数量越多压缩比率越大,尺寸越小,使这种情况下内存占用大幅降低。降低OOM崩溃
6,导出时即时释放导出完成的素材、特效、转场、滤镜资源,iPad下从导出最高2.75G优化到800M
智能生成导出时之前不会进行导出完毕素材等资源的释放,导致资源在导出过程中一直占用,当素材很多的时候,内存占用非常庞大,即时释放后内存大幅降低。降低了OOM崩溃。
7,解决强解包引起的崩溃,例如以下写法:
(1)全局变量 public var text: AnimatedText!,全靠自己在指定位置初始化,万一哪里没走初始化代码直接访问了,就强解包崩溃了。所以这种代码就不要写,写?,用的地方也加?或者guard 一下。
(2)return一个强解包
private static var _document: URL?
public static var document: URL {
if _document == nil {
let manager = FileManager.default
if let url = try? manager.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: false
) {
_document = url
}
}
return _document!
}
将最后一行修改为
return _document ?? temporary
8,lowerBound > upperBound,例如
var a = 10
var b = 8
for _ in a...b {}
在for前面加一个guard a > b else { return }
9,static URL._unconditionallyBridgeFromObjectiveC
FBSDKShareKit的videoURL方法没有写nullable,但实际返回了nil,swift桥接时崩溃了。
- (nullable NSURL *)fbVideoURL {
return [self videoURL];
}
加了一个OC包装方法声明为nullable,在swift中guard一下
guard let videoURL = asset.fbVideoURL else {
completion?(ShareError.resourceConvertDataFailed)
return
}