启动白屏
在 iOS 13 以下的版本中,如果你在 App 中替换了 window.rootViewController 那么会有一个 UITransitionView 的界面遗留在 window 上无法释放,苹果并不推荐我们在 App 运行时替换 window.rootViewController 。但是有时业务确实需要我们怎么做,比如只有登录后可以使用 App ,我们可以在登录后替换 window.rootViewController 。但是到了 iOS 13 情况变得不一样了,iOS 13 可能调整了流程,如果移除了 UITransitionView 应用就会白屏,所以需要调整下代码逻辑,添加判断是否为 iOS 13。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func setRootViewController(_ newRootViewController: UIViewController,
withTransition transition: CATransition? = nil) {
rootViewController?.dismiss(animated: false, completion: { [weak self] in
self?.rootViewController?.view.removeFromSuperview()
})
if let transition = transition {
layer.add(transition, forKey: kCATransition)
}
rootViewController = newRootViewController
if UIView.areAnimationsEnabled {
UIView.animate(withDuration: CATransaction.animationDuration()) {
newRootViewController.setNeedsStatusBarAppearanceUpdate()
}
} else {
newRootViewController.setNeedsStatusBarAppearanceUpdate()
}
if #available(iOS 13.0, *) {
} else {
if let transitionViewClass = NSClassFromString("UITransitionView") {
for subview in subviews where subview.isKind(of: transitionViewClass) {
subview.removeFromSuperview()
}
}
}
}
}
UIModalPresentationStyle
在 iOS 13 上,使用 presentViewController 弹出 ViewController 时,默认样式如下:

大部分情况下我们需要的还是原来的样式,需要将 viewController 的 modalPresentationStyle 改为 overFullScreen ,但是一个个手动去改,工作量也比较大,此时就需要用到 method swizzle 了,Referencing the Objective-C selector of property getters and setters 这份提案有说到 Swift 是支持获取 getter 和 setter 对应的 selector ,然后我们需要替换 modalPresentationStyle 的默认值,改为 overFullScreen ,这样可以在需要的时候设置为 autoMatic 。首先,需要在 UIViewController 的 extension 中新增 swizzledModalPresentationStyle 属性,默认值为 .overFullScreen :
// MARK: - ModalPresentationStyle
private var modalPresentationStyleKey: UInt8 = 0
extension UIViewController {
var swizzledModalPresentationStyle: UIModalPresentationStyle {
set {
objc_setAssociatedObject(self,
&modalPresentationStyleKey,
newValue,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
get {
if let presentationStyle =
(objc_getAssociatedObject(self,
&modalPresentationStyleKey)) as? UIModalPresentationStyle {
return presentationStyle
} else {
return .overFullScreen
}
}
}
}
然后再对 modalPresentationStyle 的 setter 和 getter 方法进行 swizzle:
private static var hasSwizzled = false
static func swizzleMethods() {
guard !hasSwizzled else { return }
hasSwizzled = true
[
(#selector(self.viewDidLoad), #selector(cbViewDidLoad)),
(#selector(self.viewDidAppear(_:)), #selector(cbViewDidAppear(_:))),
(#selector(self.viewWillAppear(_:)), #selector(cbViewWillAppear(_:))),
(#selector(getter: self.preferredStatusBarStyle), #selector(getter: cbPreferredStatusBarStyle)),
(#selector(getter: self.modalPresentationStyle), #selector(getter: swizzledModalPresentationStyle)),
(#selector(setter: self.modalPresentationStyle), #selector(setter: swizzledModalPresentationStyle))
].forEach { (original, swizzled) in
guard let originalMethod = class_getInstanceMethod(self, original),
let swizzledMethod = class_getInstanceMethod(self, swizzled) else { return }
if class_addMethod(self,
original,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)) {
class_replaceMethod(self,
swizzled,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
Cocoapods 与 Xcode New Build System
如果你有至少一个 Pods 包含 Assets.xcassets ,那么在打包的时候就会生成重复的图片到 App 的根路径下的 Assets.car 中,在使用 Xcode 11 build 时,那么就会报错,显示你有 duplicate output file 。 如果你的 Pods 包含 Assets.xcassets ,那么应该在 Input File 列表中,具体讨论可以看这里 Xcode 10 new build system makes asset catalog invalid specified by podspec’sresource(s) ,里面也有说到具体的解决方案。
Comments powered by Disqus.