iOS引导页、启动页

前言

这里使用 launchScreen.storyboard 文件创建启动图和引导页。首次打开项目或者更新后第一次打开时展示引导页,保存有用户信息时进入首页,否则进入登录注册页面。

正文

1. 动态启动图

LaunchScreen.storyboard 文件上放入一个图片。并添加约束,铺满整个页面。为 LaunchScreen.storyboard 文件设置 Storyboard ID 。注意到文件的 ClassUIViewController

  • LunchScreen基本设置

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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 说明:开发环境为XCode7 beta5 引导页和广告栏的制作都是基于UIScrollView,因此它们有许多相似...
    EgeTart阅读 6,104评论 13 29
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,943评论 4 60
  • 老公去延安出差带回来一本路遥的《人生》,说是让孩子看看。我随意翻了一下,发现作者是榆林清涧县人,里面的内容是以陕北...
    一笑而过2023阅读 320评论 0 0
  • 我是个既深情又薄情的人 深情在我和谁在一起的时候就算出现更好的也没有见异思迁的念头 薄情在无论谁离开了我 只要我接...
    鸣桐阅读 168评论 0 1
  • 春天的湖面铺满晶莹的阳光 当微风拂过平静的湖面 总会泛起波光粼粼的耀眼光芒 那场红尘缘在波光中泛起 就像有些人怀抱...
    风情公子阅读 164评论 0 0