仿制新浪微博iOS客户端之四-未登录页面处理

  写在最前:非常抱歉,前期因为个人原因有二十多天的时间没有再继续更新这个专题,期间仅仅是完成了苹果官方的UIStackView的文档的翻译。在这里我们将继续未完成的任务,继续做下去!现在继续!

  一、前期总结

  在完成第三篇的任务后,我们实际上完成的效果如下:

  

  目前我们已经能保证界面的顺利切换,并且给微博的撰写按钮预留了点击事件接口,再下一步,我们将要完成在用户登录前的所有准备工作。

  

  二、抽取基类

  目前我们在首页、消息、发现、我这四个界面中使用的都是UITableViewController来加载和显示内容,虽然在实际显示时是有区别的,但是在本质上我们可以认为一样,因此这四个我们可以抽出一个共同的基类,供四个TableViewController来继承,来实现我们想要的功能。

  1.创建继承自UITableViewController的类:BaseTVC;

  2.修改四个页面对应控制器类的父类;

  3.在BaseTVC中写入登录判断代码并测试。

  在BaseTVC中写入的代码如下:

    // 用户登录标记
    var userLogon: Bool = false

    override func loadView() {
        // 用户已登录,则执行默认情况
        if userLogon {
            super.loadView()
            return
        }
        // 用户未登录,修改控制器view为空白view
        view = UIView()
    }

  在用户已登录的情况下,执行的效果与不写这段代码的效果是一样的,因此我们这里只测试未登录的效果,即 userLogon = false。测试结果如下:

  

  在这里我们可以看到,在用户未登录情况下,确实创建了一个空白的view取代了原有的tableView,而这个空白view将是我们实现 用户登录视图 效果的位置。

  

  三、用户登录视图

  微博的登录界面基本上如上图所示,中间是一个与页面相关的大图标,界面变化时大图标会进行切换,一圈小图标围绕着大图标转动,并且视图有透明度渐变效果,大图标底部的小图标是有若隐若现的效果的,其他内容则与图片所示的基本一致。

  1.首先拖入素材

  2.创建xib

  由于我们的view是使用代码创建的,因此在storyboard上我们是无法进行操作的,如果要进行处理,我们只有两种方式选择:纯代码操作/xib加载。纯代码开发有一定的可行性,但是考虑到可视化操作对于效率上的优势,我们在这里使用的是xib。

  创建xib文件VisitorLoginView,拖入控件并对应设置布局如下:

  

  拖入顺序:小图标图片->遮罩图片->大图标图片->Label->注册按钮、登录按钮

  约束顺序:

    遮罩与xib左、右、上三边对齐,与下方间距110;

    大图标居中,宽高均90;

    小图标参照大图标中心对齐,宽高均180;

    label参照小图标水平中心对齐,垂直间距8,宽224,高34,字号14,行数2

    按钮参照Label分别左右对齐,垂直间距15,宽106,高34,字号18,文字颜色分别为橙色和黑色

  备注:默认拖入顺序反映了各个图片之间的遮挡关系,越后拖入的控件,会遮挡住在它之前拖入的图片,因此按照这个顺序,可以保证遮罩是可以遮挡住小图标的,在加上遮罩图片是渐变效果,因此可以显示出一个渐变的小图标图片。

  同时,除遮罩外的所有控件的约束都参照了大图标,因此如果大图标移动,则所有控件都会保持当前的相对位置同向移动,这也是方便开发的一种方式。

  以上步骤完成后,修改以下代码,再次测试,测试结果如下图:

        //        view = UIView()
        view = NSBundle.mainBundle().loadNibNamed("VisitorLoginView", owner: nil, options: nil).last as! UIView    

  UI设置的部分基本上宣告完成,后续我们只需要根据页面的不同来切换图标和文字内容就可以了。

  3.创建自定义view类,对xib文件进行代码补充

  创建VisitorLoginView.swift文件,写入以下代码:

    @IBOutlet weak var smallIcon: UIImageView!
    @IBOutlet weak var bigIcon: UIImageView!
    @IBOutlet weak var msgLabel: UILabel!

    // 点击注册按钮事件方法
    @IBAction func visitorRegister(sender: UIButton) {
        println(__FUNCTION__)
    }
    // 点击登录按钮事件方法
    @IBAction func visitorLogin(sender: UIButton) {
        println(__FUNCTION__)
    }

    /**
    设置访客界面信息

    :param: iconName 显示图标名称
    :param: message  信息label内容
    :param: isHome   是否首页
    */
    func setupVisitorInfo(iconName: String, message: String, isHome: Bool = false) {
        // 非首页情况下:隐藏大图标,将图片显示到小图标
        // 首页情况下:大图标显示,并呈现默认图片
        bigIcon.hidden = !isHome
        if isHome {
            smallIcon.image = UIImage(named: "visitordiscover_feed_image_smallicon")
            bigIcon.image = UIImage(named: iconName)
        } else {
            smallIcon.image = UIImage(named: iconName)
        }
        msgLabel.text = message
    }

  在此类中,我们预留了一个接口方法setupVisitorInfo,来设置对应的图片和label的内容。

  完成上述内容后,我们需要在各个控制器中调用这个接口,来给不同界面下显示的view进行赋值。

  这时就体现出抽取基类的好处了:我们只需要给基类赋予一个属性,那么所有继承基类的类都会自动获得基类所拥有的属性,方法也是如此,因此这里我们先添加一个属性:

   // 登录视图属性
    var visitorLoginView: VisitorLoginView?

  然后将控制器基类的loadView方法进行再次部分修改:

    // 用户未登录,修改控制器view为指定xib加载的view
    visitorLoginView = NSBundle.mainBundle().loadNibNamed("VisitorLoginView", owner: nil, options: nil).last as? VisitorLoginView
    view = visitorLoginView

  最后在四个子控制器的viewDidLoad方法中加入以下代码:

  HomePageTableViewController

    visitorLoginView?.setupVisitorInfo("visitordiscover_feed_image_house", message: "关注一些人,回这里看看有什么惊喜", isHome: true)

  MessageTableViewController

    visitorLoginView?.setupVisitorInfo("visitordiscover_image_message", message: "登录后,别人评论你的微博,发给你的消息,都会在这里收到通知")

  DiscoverTableViewController

    visitorLoginView?.setupVisitorInfo("visitordiscover_image_message", message: "登录后,最新、最热微博尽在掌握,不再会与实事潮流擦肩而过")

  ProfileTableViewController

    visitorLoginView?.setupVisitorInfo("visitordiscover_image_profile", message: "登录后,你的微博、相册、个人资料会显示在这里,展示给别人")

  注意:这里用到了swift语法的一个特性:当一个方法的某个参数被赋予了默认值的情况下,这个参数是可以省略的,省略此参数代表将传入默认值。在这里,我们的三次调用接口就省略了isHome这个参数。

  完成以上设置之后,再次运行测试,我们看到的测试结果如下:

  下一步,我们将实现首页的小图标转动效果。

  4.首页动画效果

  在原版的微博中,围绕着大图标的小图标图片是在不停的旋转的,我们在这里也可以做出这样的效果。具体步骤如下:

  在自定义xib类中创建动画方法:

    // 开始动画
    private func startAnimation() {
        let anim = CABasicAnimation(keyPath: "transform.rotation")
        anim.repeatCount = MAXFLOAT
        anim.duration = 20
        anim.toValue = M_PI * 2
        smallIcon.layer.addAnimation(anim, forKey: "smallIconRotationAnim")
    }

  改写setupVisitorInfo:

    func setupVisitorInfo(iconName: String, message: String, isHome: Bool = false) {
        // 非首页情况下:隐藏大图标,将图片显示到小图标
        // 首页情况下:大图标显示,并呈现默认图片
        bigIcon.hidden = !isHome
        if isHome {
            bigIcon.image = UIImage(named: iconName)
            if (smallIcon.layer.animationForKey("smallIconRotationAnim") == nil) {
                startAnimation()
            }
        } else {
            smallIcon.image = UIImage(named: iconName)
        }
        msgLabel.text = message
    }

  这里需要提示的几点是:

  核心动画中 anim.removedOnCompletion 默认为 true
  当视图消失时,动画会被自动从图层删除,因此不需要停止动画方法
  在添加动画时,如果指定了 key,图层会对动画强引用,并且不会释放,避免界面切换之后动画停止,不会再启动的情况

   因此在以上的代码中,需要对加入的动画设置key,避免界面切换时动画被释放掉。

  同时由于一个控制器的viewDidLoad方法只会在视图加载时调用,因此界面切换时是不会调用这个方法的。基于上述原因,HomePageTableViewController中的设置图片类型和文字的方法setupVisitorInfo调整到viewWillAppear方法中。

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        visitorLoginView?.setupVisitorInfo("visitordiscover_feed_image_house", message: "关注一些人,回这里看看有什么惊喜", isHome: true)
    }

  完成上述步骤后,实现的效果如下:

  

  至此,首页动画效果完成。

  5.注册、登陆按钮点击代理

  登陆界面中另外要处理的就是注册和登陆按钮的点击了。在这里我们使用代理方式来处理事件的点击。

  首先要说明的是,代理的使用是分两部分的:代理的声明以及代理的实现

  代理的声明分为三部分:定义代理属性->定义代理协议和方法->在合适时机调用代理方法;

  代理的实现同样有三部分:注册代理对象->遵守代理协议->实现代理方法。

  5.1 代理声明

  不多说,上代码  

/**
*  定义代理协议及方法
*/
protocol VisitorLoginViewDelegate: NSObjectProtocol {
    func didRegisterButtonClicked()
    func didLoginButtonClicked()
}

class VisitorLoginView: UIView {
    // 定义代理属性
    weak var delegate: VisitorLoginViewDelegate?

    // 点击注册按钮事件方法
    @IBAction func visitorRegister(sender: UIButton) {
        // 在合适时机调用代理方法
        delegate?.didRegisterButtonClicked()
    }
    // 点击登录按钮事件方法
    @IBAction func visitorLogin(sender: UIButton) {
        // 在合适时机调用代理方法
        delegate?.didLoginButtonClicked()
    }

  在这里,我们首先定义的是代理协议及方法,根据代理属性类型定义代理属性,由于代理方法是点击按钮时调用,因此调用代理方法也是在按钮点击事件方法中调用。

  5.2 代理实现

  在BaseTVC中注册代理对象

    // 注册代理对象
    visitorLoginView?.delegate = self

  遵守代理协议并实现代理方法

extension BaseTVC: VisitorLoginViewDelegate {
    func didRegisterButtonClicked() {
        println(__FUNCTION__);
    }

    func didLoginButtonClicked() {
        println(__FUNCTION__);
    }
}

  给导航栏添加两侧的按钮,并注册点击事件:

    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "注册", style: UIBarButtonItemStyle.Done, target: self, action: "didRegisterButtonClicked")
    navigationItem.rightBarButtonItem = UIBarButtonItem(title: "登录", style: UIBarButtonItemStyle.Done, target: self, action: "didLoginButtonClicked")

  完成以上代码后,测试结果如下:

  6.设置导航栏全局外观

  我们代码手动添加的按钮为系统默认样式,是蓝色的按钮,其样式与整个应用的橙、灰配色并不协调,在加上其他页面也可能需要设置外观,因此我们可以设置全局外观,来一次性确定合适的样式。

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        setupAppearance()

        return true
    }

    // 设置全局外观样式
    private func setupAppearance() {
        UINavigationBar.appearance().tintColor = UIColor.orangeColor()
    }

  完成上述设置后,导航栏按钮也变为了与app色调一致的橙色。

  至此,实现用户登录前的所有准备工作便已经完成了。

  杂谈:

  1.接口

  在开发过程中,我们往往会为了一些还未开发的功能和代码预留接口,这是非常必要的手段和方法,也可以理解成这是一个Todo事项,需要我们去完成它。从本项目开始到现在,我们的项目中已经留下了不少的接口(或者说是“坑”),接下来我们会一个个的填上。

  2.Swift中的代理

  Swift中的代理与OC是基本一致的,实现思路可以说是完全一样,只是有一些细节需要着重说明。

  定义协议时,需要继承自:NSObjectProtocol。这是与OC比较大的一个区别。

  定义代理属性时,我们使用了weak字段来对属性进行修饰,这样做是为了避免出现循环引用。如果是默认的strong,则控制器会强引用view,当注册代理属性时会强引用view的代理,而view如果再强引用它自身的代理,则一定会出现循环引用。

时间: 2024-08-05 14:34:22

仿制新浪微博iOS客户端之四-未登录页面处理的相关文章

仿制新浪微博iOS客户端之二-项目基础搭建及相关设置

上一次的文章主要提到了仿制新浪微博所用到的一些技术和知识点,那本文就开始进入正式的项目实施阶段了.首先要做的自然是项目的创建和相关的设置,以及基础框架的搭建了. 一.项目创建及相关设置 1.项目创建 现在越来越多的的公司开始使用Swift开发iOS和AppleWatch的项目,因此此次我们的开发也使用Swift语言来进行,新建项目,设置如下: 既然是仿制,自然可以当成是一个练习,项目名称:“WeiboTest”,编程语言选择“Swift”.然后“下一步”直到创建完成. 2.应用图标设置 将应用图

仿制新浪微博iOS客户端之一-序言

新浪微博是现在各个互联网平台上都使用得非常频繁的app之一,在其上拥有大量的用户,同时,其app的设计也反映了当前移动应用的主流开发趋势.因此在此基础上,对其app的仿制也有利于对当今app的开发技术的掌握.下面就开始仿制自己的新浪微博项目吧! 在本项目中,我们会使用到主流开发架构.OAuth认证授权登录.自动布局.二维码扫描.Emoji表情文字.自定义图片查看器.数据库SQLite等功能和技术,敬请期待! 一.架构方式 目前主流的多界面的移动app开发中,普遍的使用 TabBarControl

仿制新浪微博iOS客户端之三-自定义TabBar

继续上一篇文章的进度,我们实际完成了微博基本框架的搭建,具体实现的效果如下左图,但我们实际需要实现的效果为右图,除去主要的页面内容不谈,仅仅下面的TabBar距离我们的需求就有相当的差距.因此本文着重于实现需要的效果.                           再简要汇总一下我们的需求: 1.我们要在TabBar原有四个按钮的基础上,再增加一个按钮,作为撰写微博的入口: 2.新加入的按钮必须和原有按钮一起,均匀分布在TabBar上: 3.新加入的按钮只有图片,没有文字. 需求汇总如上,

仿新浪微博IOS客户端(v5.2.8)——自定义UITabBar替换系统默认的(添加“+”号按钮)

转载请标明出处:http://blog.csdn.net/android_ls/article/details/45896395 声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片. 自定义UITabBar替换系统默认的,目的是为了在UITabBar中间位置添加一个"+号按钮",下面我们来聊聊具体的实现. 1.自定义WBTabBar,让其继承自UITabBar,代码如下: // // WBT

仿新浪微博IOS客户端(v5.2.8)——下拉菜单栏的实现

转载请标明出处:http://blog.csdn.net/android_ls/article/details/45877983 声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片. 接着上一篇博文,这篇我们来聊聊新浪微博导航栏上,点击中间部分的标题(titleView)弹出的下拉菜单是如何实现. 1.自定义导航栏中间的titleView,代码如下: // 设置导航栏中间的titleView _tit

仿新浪微博IOS客户端(v5.2.8)——设置导航栏外观

转载请标明出处:http://blog.csdn.net/android_ls/article/details/45849447 声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片. 一. 在Xcode6下添加.pch文件 对于使用惯了之前版本Xcode的朋友来说,在系统提醒之下升级到Xcode 6之后,发现新建项目后Xcode不再帮我们创建.pch文件了.可是我们已经习惯了,把一些在很多地方都用的宏

仿新浪微博IOS客户端(v5.2.8)——搭建项目基本框架

转载请标明出处:http://blog.csdn.net/android_ls/article/details/45827719 声明:仿新浪微博项目,所用所有图片资源都来源于官方新浪微博IOS客户端,编写本应用的目的在于学习交流,如涉及侵权请告知,我会及时换掉用到的相关图片. 最近我打算利用业余时间,仿下新浪微博IOS客户端,至于能写到哪里我也不确定,能写多少就写多少吧,下面我们开始项目的基本搭建: 1.打开Xcode选择创建新项目,并创建各个模块的目录结构,完成后项目的目录结构如下图: 2.

IOS客户端UIwebview下web页面闪屏问题

基于ios客户端uiwebview下的web页面,在其内容高度大于视窗高度时,如果点击超过视窗下文档的底部按钮,收缩内容高度,会发生闪屏问题. 外因是由文档的高度大于视窗的高度所致,本质原因未知. 解决办法: 为最外层的元素设置height:100%(要保证100%的高度等于视窗高度),overflow:scroll,如果想避免出现滚动条的话,还可以在最外层元素加上伪类::-webkit-scrollbar{display:none},即可完美解决闪屏问题.

新浪微博iOS客户端架构与优化之路

随着Facebook.Twitter.微博的崛起,向UGC.PGC.OGC,自媒体提供平台的内 容消费型App逐渐形成了独特的客户端架构模式.与电商和通讯工具类App不同,微博客户端具有多信息流.内容丰富多样.对数据量和延迟敏感等特点.微博的信息流承载着文字.网页.照片.视频.直播等多样的内容形式,所以复杂信息流对团队的开发效率.App的性能都带来了极大的挑战. 2016年6月24-25日,GMTC全球移动技术大会将在北京举行.本届大会,我们邀请到了新浪微博移动端资深研发专家邱晨老师.曾就职于F