前言
这里使用 launchScreen
、.storyboard
文件创建启动图和引导页。首次打开项目或者更新后第一次打开时展示引导页,保存有用户信息时进入首页,否则进入登录注册页面。
正文
1. 动态启动图
将 LaunchScreen.storyboard
文件上放入一个图片。并添加约束,铺满整个页面。为 LaunchScreen.storyboard
文件设置 Storyboard ID
。注意到文件的 Class
是 UIViewController
。
在 AppDelegate
文件中设置启动动画。
extension AppDelegate {
/// 动态启动图
fileprivate func setupLaunchImage() {
let launchSB = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateViewController(withIdentifier: "launchScreen")
let launchView = launchSB.view
window?.addSubview(launchView!)
// 动画效果
UIView.animate(withDuration: 1.5, animations: {
launchView?.alpha = 0.0
launchView?.layer.transform = CATransform3DScale(CATransform3DIdentity, 1.5, 1.5, 1.0)
}) { (success) in
launchView?.removeFromSuperview()
}
}
}
在启动时调用方法。必须要先设置 window?.makeKeyAndVisible()
,使 window
可用。否则后面使用 window
时,始终为 nil
。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window?.makeKeyAndVisible()
setupLaunchImage()
return true
}
查看效果:
如果想要在启动图上做些什么,譬如添加链接、倒计时等,创建 LaunchScreen
文件对应的 controller
代码文件,然后设计开发。
2. 引导页
暂时不考虑是否展示引导页的问题,目前始终展示引导页。创建引导页 .storyboard
文件。关联相关文件。关于 storyboard
文件中 UIScrollView
文件的使用,参考 Storyboard中的UIScrollView使用自动布局,使其能够滚动 ,或者 史上最简单的UIScrollView+Autolayout出坑指南。
关于具体的引导页内部实现参考代码,这里解释下 AppDelegate
文件中的引导操作。首先暂时设置引导页为 rootViewController
,否则动画过渡期间会展示 Main.storyboard
下的页面。其次, 延时加载动画的目的是让过渡更加自然些。
fileprivate let guideVC = UIStoryboard(name: "GuidePage", bundle: nil).instantiateViewController(withIdentifier: "GuideViewController") as? GuideViewController
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window?.rootViewController = guideVC
window?.makeKeyAndVisible()
setupLaunchImage()
return true
}
```
`AppDelegate` 扩展代码:
extension AppDelegate {
/// 动态启动图
fileprivate func setupLaunchImage() {
let launchSB = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateViewController(withIdentifier: "launchScreen")
let launchView = launchSB.view
window?.addSubview(launchView!)
showGuidePage(0.5)
// 动画效果
UIView.animate(withDuration: 1.5, animations: {
launchView?.alpha = 0.0
launchView?.layer.transform = CATransform3DScale(CATransform3DIdentity, 1.5, 1.5, 1.0)
}) { (success) in
launchView?.removeFromSuperview()
}
}
/// 展示引导页
///
/// - Parameter animationAfter: 延时动画时间
private func showGuidePage(_ animationAfter: TimeInterval) {
// 将引导页设置为主页面
let guideView = guideVC?.view
window?.addSubview(guideView!)
guideView?.alpha = 0.5
// 延时加载动画
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + animationAfter) {
UIView.animate(withDuration: 1.0) {
guideView?.alpha = 1.0
}
}
}
}
效果:
![引导页](http://upload-images.jianshu.io/upload_images/1910830-cdf01fa91a9ce728.gif?imageMogr2/auto-orient/strip)
###### 3. 程序首次启动或者更新后首次启动才展示引导页
首先设置一些全局变量:
// 本地保存版本号
public let kAppVersion = "appVersion"
// 本地账号
public let kUserName = "userName"
// 本地密码
public let kPassword = "password"
/// 从 Storyboard 中读取 ViewController
///
/// - Parameters:
/// - name: SB name
/// - identifier: VC identifier
/// - Returns: need VC
public func mViewControllerByStoryboard(sb name: String, vc identifier: String) -> UIViewController {
return UIStoryboard(name: name, bundle: nil).instantiateViewController(withIdentifier: identifier)
}
/// 设置 UserDefaults 值的存取
public func mUserDefaultsSetValue(_ value: Any, _ key: String) {
UserDefaults.standard.set(value, forKey: key)
}
public func mUserDefaultsObject(_ key: String) -> Any? {
return UserDefaults.standard.object(forKey: key)
}
判断是否是第一次启动或者版本更新:
/// 是否是首次登陆或者版本更新
///
/// - Returns: 判断是否要展示引导页
fileprivate func isFirstLaunchOrUpdated() -> Bool {
// 获取应用上次启动时保存的版本号
let lastVersion = UserDefaults.standard.object(forKey: kAppVersion) as? String
let currentVersion = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
if lastVersion == nil || lastVersion != currentVersion {
// 未保存版本号或者已更新
UserDefaults.standard.set(currentVersion, forKey: kAppVersion)
UserDefaults.standard.synchronize()
return true
} else {
return false
}
}
上面方法中 `Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String` 是从 `info.plist` 文件中读取版本号。
通过这个方法,设置引导页的展示。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if isFirstLaunchOrUpdated() {
// 首次打开或者更新后打开
window?.rootViewController = guideVC
} else {
// 已经打开过,然后判断是否已经登录过
if mUserDefaultsObject(kUserName) != nil && mUserDefaultsObject(kPassword) != nil {
let mainVC = mViewControllerByStoryboard(sb: "Main", vc: "ViewController")
window?.rootViewController = mainVC
} else {
let loginVC = mViewControllerByStoryboard(sb: "LoginAndRegister", vc: "LoginViewController") as! LoginViewController
window?.rootViewController = loginVC
}
}
window?.makeKeyAndVisible()
setupLaunchImage()
return true
}
并在展示引导页的方法中加入判断:
/// 展示引导页
///
/// - Parameter animationAfter: 延时动画时间
private func showGuidePage(_ animationAfter: TimeInterval) {
// 判断是否是首次启动或者更新后启动
guard isFirstLaunchOrUpdated() == true else {
return
}
// 将引导页设置为主页面
let guideView = guideVC?.view
window?.addSubview(guideView!)
guideView?.alpha = 0.5
// 延时加载动画
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + animationAfter) {
UIView.animate(withDuration: 1.0) {
guideView?.alpha = 1.0
}
}
}
#### 结束
更多细节参考源码: [Demo 下载](https://github.com/Bruce-Hsu/GuidePageDemo)