2019-10-16
在现在的许多 APP 中可以看到在启动页上加载广告,实际上这里是由两部分组成,一张与启动页完全相同的图片以及广告视图。
在 iOS13 以前我们可以通过启动页加载完成之后读取 LaunchImage
资源里所对应的不同尺寸的启动图来达到这一目的,但是在 iOS 13 之后苹果不再推荐使用 LaunchImage
来设置启动图,而是应该通过 LaunchScreen.StoryBoard
来设置,所以之前所使用的方法就失效了。
最初我想可以通过读取 LaunchScreen.StoryBoard
里的视图,再将其转为一张图片就可以达到目的了,然而事实是如果去除了安全区域那么读取出来的视图的尺寸是不全的。
默认创建的 LaunchScreen.StoryBoard
的大小是 iPhone11
的大小,也就是 414 * 896
, 如果你采取直接读取 LaunchScreen.StoryBoard
里 Controller
对应的 View
的方式运行在一个 iPhoneX
的设备上,那么这里的视图将以 414 * 896
切成 375 * 812
后得到的视图显示在屏幕上。看到的效果如下所示:
let controller = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()!
从示图中可以明显看到相比正常的启动图快照,有问题的少了 Copyright 部分以及 logo 发生了偏移。
下面部分我们就来解决这个问题
- 在
LaunchScreen.StoryBoard
里设置 Copyright 对应的文本底部约束的 identifier, 这是为了后面调整在iPhoneX
等设备上这段文本距离底部的距离偏差问题
2.创建一个 Controller
,其中的代码图所示。这里我们将加载出来的 LaunchScreen.Storyboard
里的 Controller
作为当前控制器的子控制器,同时设置了对应 View
的尺寸,注意正是由于这一层的包装才使得最后取得的快照是正确的。
- 在前面我们设置了
Copyright
文本底部约束所对应的 identifier,这是为了处理iPhoneX
等设备上 34 像素的间距问题,你可以注释掉下面的代码查看效果。处理代码如下:
/// 针对 iPhoneX 设备处理安全区域34间距问题
if #available(iOS 11.0, *) {
let isPhoneX = (UIApplication.shared.delegate as! AppDelegate).window!.safeAreaInsets.bottom > 0.0
if isPhoneX {
for constraint in controller.view.constraints {
if constraint.identifier == "bottomConstraint" {
constraint.constant += 34.0
}
}
}
}
- 在
UIImage+LaunchScreen.swift
中创建获取启动图快照的方法,这里将LaunchScreenViewController
的view
做成了一张快照,最终这里得到的快照与启动图一模一样。
extension UIImage {
static func launchImage() -> UIImage? {
let controller = LaunchScreenViewController()
// 打开下面的注释就可以看到有问题的快照
// let controller = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()!
let launchImage = UIImage.snapshot(from: controller.view)
return launchImage
}
static func snapshot(from view: UIView) -> UIImage? {
let size = view.bounds.size
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(size, true, scale)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
- 最后我们可在
AdViewController
里加载启动图快照与广告视图
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let launchImage = UIImage.launchImage()
let imageView = UIImageView(frame: view.bounds)
imageView.image = launchImage
view.addSubview(imageView)
}
AppDelegate.swift
看到演示的加载代码如下:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let adVC = AdViewController()
let mainVC = ViewController()
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = adVC;
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 4.0) {
self.window?.rootViewController = mainVC
}
return true
}