一:访客界面效果如图

二:xib封装访客视图的view

1:业务逻辑分析:1:由于用户未登录时要显示访客视图,要先进行判断用户是否登录,未登录则显示访客视图,登录则显示正常的登陆界面,由于要在四个子控制器界面的控制器中都要判断是否显示访客视图,同样的逻辑,所以考虑抽成父类,把判断是否显示访客视图的逻辑封装在父类中,让子类去继承。2:访客视图的界面如图:将访客视图封装在一个view中,view的界面相对固定,所以用xib搭建,首先将尽可能显示的控件全部封装在view的内部,再根据外界传入的model或是在封装类中定义方法来控制控件显示的内容或是相应控件的显示和隐藏,3:通过在父类控制器中重写loadView方法判断用户是否登陆来设置是否加载访客视图

2:访客视图的搭建:新建文件继承UIView,新建xib与新建的UIview类同名,首先来到xib中,将类与xib进行关联,可以不设置freeform

1:1:先拖入UIimageView来设置旋转图片:先在如图处设置xib约束,设置控件相对于父视图水平居中竖直居中,在如图所示位置水平竖直居中(此处1设置的是相对于父视图的水平竖直居中,图2水平竖直居中对齐,一般都是任意选中两个控件,设置控件A相对于控件B的中心点水平竖直居中)。

2:先设置旋转图片相对于父视图水平竖直居中,在上图1中去设置,再来到右侧调整其竖直中心点向上偏移,按住command + =调整旋转图片的UIimageView的大小等于图片的大小,就不用再去设置宽高的约束了。

3:再拖入一个UIImageView背景图片来盖住旋转图片的底部,在如图所示的位置设置背景图片的顶部左右和高约束,(图中小箭头的部分可以设置相对于哪个控件的约束)

4:再设置房子的约束,拖入一个UIimageView,command + = 来设置imageView的大小和图片的大小相等,所以就不用设置宽高约束了,再来到如图所示的位置处设置,同时选中房子和旋转图片,拉线,按住shift键可同时设置多个约束,设置房子相对于旋转view的中心点水平居中,竖直居中(在右侧又可以调整位置的相对偏移)

5:提示lable的约束设置:拖入lable,换行,设置numberoflines为0,设置文字的居中效果,Aliment对齐方式为居中,就会显示出如图所示的效果:在左侧同时选中lable和房子,设置lable相对于房子中心点水平居中对齐,y方向的约束就设置lable距离房子底部的约束,拉线设置竖直距离。给lable设置一个最大宽度的约束,为了适配登陆注册按钮,高度约束不去设置

10:登陆注册按钮的设置:拖入注册按钮,调整样式为custom,否则不能显示出按钮的高亮状态,设置按钮的背景图片,此时背景图片会拉伸,可以在如图处设置,防止注册按钮的背景拉伸:在如图出sliciing处设置水平竖直为保护区域,不产生拉伸

宽高约束不设置,让按钮根据内容大小来自定义宽高,在设置按钮相对lable左对齐,y方向约束,设置lable相对于房子(固定不变)的底部约束,为了避免因提示文字内容的多少,而导致四个界面的登陆注册按钮不再同一个y值方向上。再拷贝粘贴出登陆按钮,拷贝粘贴的控件保留了宽高约束,所以还需要设置其右对齐和y方向上的约束。设置两个控件的对齐方式如图:1:同时选中两个控件,来到如图处位置设置两个控件的对齐方式

三:控制器代码

1:封装访客view的代码

import UIKit
/* 总结:1:设置好xib后,拉线到相应的view中成为RHVisitorView的属性(对于注释:一般代码的模块化用 //MARK:-1来注释,非模块化只是可用//来表示),@IBOutlet weak var loginBtn: UIButton!,用weak修饰因为xib控件已经在该view上了,所以该view对该控件已经有了一个强引用,在swift中一般变量基本都为可选类型,要是确定其一定有值,则可以用!来进行强制解包,as?可以将左边的类型转换为右边的可选类型,as!当确定要转的变量一定有值的时候,可以将左边的可选类型转换为右边确定的类型,as,将左边的类型转换为右边的类型,例如:利用as将swift字符串转为oc字符串来实现字符串的截取 2:1:在封装的view中提供类方法快速返回xib中加载的对象:在swift中类方法以class开头:class + func + 函数名(参数裂变)-> 返回值类型{
业务逻辑代码
return 返回值类型
} 2:代码
class func visitorView()-> RHVisitorView{ //1:加载xib的view
let visitor = Bundle.main.loadNibNamed("RHVisitorView", owner: nil, options: nil)!.last as! RHVisitorView
visitor.backgroundColor = UIColor(red: 238/255.0, green: 238/255.0, blue: 238/255.0, alpha: 1) return visitor
}
1:Bundle.main.loadNibNamed("RHVisitorView", owner: nil, options: nil),从xib中获得加载的数组,此获得数组的类型为可选类型[Any]?,Any表示数组中存放的元素,此时可以保证数组一定有值,所以可以!强制解包, Bundle.main.loadNibNamed("RHVisitorView", owner: nil, options: nil)!
2:Bundle.main.loadNibNamed("RHVisitorView", owner: nil, options: nil)!.last,从数组或是字典取出的元素都是Any?的可选类型,能保证其一定有值,可以用as!转换为RHVisitorView类型 3:封装view提供方法接口来控制封装view具体显示的内容和需要隐藏的内容:1:传入参数imageName和title来设置图片和文字的显示内容,其中苹果默认函数中第一个参数为内部参数,用_+空格+参数名来表示,默认从第二个参数开始即为内部参数又为外部参数,要想让其他参数,也为默认参数则可以用_+空格+参数名来表示,还可以传入默认参数。 4:首页需要旋转图片:旋转图片绕着z轴旋转一圈2π,从0到2π,两个value值,所以用CABasicAnimation func rotationImage() { //1:创建基础动画对象
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z") //2:设置动画效果
rotationAnimation.fromValue = 0
rotationAnimation.toValue = M_PI * 2
rotationAnimation.repeatCount = MAXFLOAT
rotationAnimation.isRemovedOnCompletion = false
rotationAnimation.duration = 3 //3:将动画添加到layear上
rotationImageView.layer.add(rotationAnimation, forKey: nil)
}
注意:1:核心动画,都会在切换界面或是程序进入后台的时候停止动画,所以rotationAnimation.isRemovedOnCompletion = false
2:要将核心动画添加到view的layer上
**/
class RHVisitorView: UIView {
//MARK:-1:定义xib属性
@IBOutlet weak var loginBtn: UIButton!
@IBOutlet weak var infoLable: UILabel!
@IBOutlet weak var registerBtn: UIButton!
@IBOutlet weak var rotationImageView: UIImageView!
@IBOutlet weak var iconImageView: UIImageView! //MARK:-2:类方法加载xib并设置背景色
class func visitorView()-> RHVisitorView{ //1:加载xib的view
let visitor = Bundle.main.loadNibNamed("RHVisitorView", owner: nil, options: nil)!.last as! RHVisitorView
visitor.backgroundColor = UIColor(red: /255.0, green: /255.0, blue: /255.0, alpha: ) return visitor
} //MARK:-3:提供接口,供子类调用
func setupVisitorView(_ imageName:String,title:String) { iconImageView.image = UIImage(named: imageName)
infoLable.text = title
rotationImageView.isHidden = true
} //MARK:-4:旋转图片 func rotationImage() { //1:创建基础动画对象
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z") //2:设置动画效果
rotationAnimation.fromValue =
rotationAnimation.toValue = M_PI *
rotationAnimation.repeatCount = MAXFLOAT
rotationAnimation.isRemovedOnCompletion = false
rotationAnimation.duration = //3:将动画添加到layear上
rotationImageView.layer.add(rotationAnimation, forKey: nil)
} }

2:父类控制器代码

import UIKit
/*
总结:
1:为什么要抽父类RHBaseTableViewController?因为要显示访客视图就要判断用户是否登陆,四个控制器界面都需要判断,所以可以将四个界面相同的业务逻辑抽到父类,让子类去继承(若是将业务逻辑封装在工具类中,四个界面依然需要写相同的代码,所以考虑抽到父类,让子类去继承)四个界面的访客视图界面又是类似,所以可以将访客视图的界面也封装在父类中,访客视图封装时把尽可能显示的控件全部添加到视图中,然后父类提供访客视图的接口,让子类去继承,访客视图中再去封装方法来控制不同界面访客视图的显示和隐藏 2:在父类中定义属性标识来判断用户是否登陆:1:在类中定义属性的时候,必须给属性一个初始值,或是定义为可选类型,在之后初始化或是其他地方再给该属性赋值,Bool属性只有两个关键字true和false 2:懒加载:1:闭包懒加载 2:直接进行初始化 注意:1:懒加载用关键字lazy并且必须是var来修饰 2:在定义类属性或是懒加载或是定义类中方法的时候,要考虑是否需要用private或是filePrivate来修饰来保证私有不让外界访问,private,只在当前的class类中可以访问,在同一个文件中不同class类中不可以访问,filePrivate在当前文件任何地方都可以访问,二者都不能在外界被访问 3: 设置访客视图需要重写控制器的方法loadView,在此方法中可以设置控制器当前的view,当我们需要重写系统的方法的时候,需要加上override重写标识,用三目运算,根据是否登陆的表示,来选择加载不同的控制器的view,setupView()方法是创建访客视图的方法,一般将此方法都封装在当前类的扩展中extension override func loadView() { //1:根据标识判断是加载访客视图还是登陆后界面 isLogin ? super.loadView() : setupView() } 4: //MARK:-4:设置访客视图的view
extension RHBaseTableViewController { fileprivate func setupView() { view = visitorView
}
},fileprivate设置该方法为私有,外界不可以访问 5:在viewDidLoad中设置左右导航栏按钮:将设置导航栏左右按钮也封装在当前类中的extension中,在当前类中调用当前类的方法可以省去self:
//注册按钮
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "注册", style: .plain, target: self, action: #selector(RHBaseTableViewController.clickRegisterBtn))
事件监听:#selector(RHBaseTableViewController.clickRegisterBtn),一般也将事件的监听封装在当前类的extension中, 当监听点击事件的时候,才用 @objc,当swift中定义的方法用private或是fileprivate修饰的时候,则不会将该方法加载进类的方法列表,用@objc则会将该方法依然加入到方法列表中 extension RHBaseTableViewController { @objc fileprivate func clickRegisterBtn() { DLog(message: "点击了左侧的注册按钮")
} 6:访客视图中的登陆注册按钮的监听:1:若是将监听方法放在访客视图的view中则需要协议代理,通知,闭包来进行反向监听,还可以在访客视图中提供两个btn的属性接口,在父类控制器中来设置监听,在父类的控制器中来实现跳转 **/ class RHBaseTableViewController: UITableViewController { //MARK:-1:定义属性标识:用来判断是显示访客视图还是登陆界面,默认是没有登陆
let isLogin = false
lazy var visitorView = RHVisitorView.visitorView() //MARK:-2:设置访客视图:重写loadView方法,从而更改当前控制器的view
override func loadView() { //1:根据标识判断是加载访客视图还是登陆后界面 isLogin ? super.loadView() : setupView() } override func viewDidLoad() {
super.viewDidLoad() //MARK:-3:设置左右按钮的导航栏 setupNavgationItem() //MARK:-4:添加登录注册按钮监听
//注册按钮
visitorView.registerBtn.addTarget(self, action: #selector(registBtnClick), for: .touchUpInside)
//登录按钮
visitorView.loginBtn.addTarget(self, action: #selector(loginBtnClic), for: .touchUpInside) }
} //MARK:-4:设置访客视图的view
extension RHBaseTableViewController { fileprivate func setupView() { view = visitorView
}
} //MARK:-5:设置导航栏左右item
extension RHBaseTableViewController { fileprivate func setupNavgationItem() { //注册按钮
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "注册", style: .plain, target: self, action: #selector(RHBaseTableViewController.clickRegisterBtn)) //登录按钮
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "登录", style: .plain, target: self, action: #selector(RHBaseTableViewController.clickLoginBtn))
} }
//MARK:-6:监听按钮的点击
extension RHBaseTableViewController { @objc fileprivate func clickRegisterBtn() { DLog(message: "点击了左侧的注册按钮")
} @objc fileprivate func clickLoginBtn() { DLog(message: "点击了右侧的登录按钮")
} @objc fileprivate func registBtnClick() { DLog(message: "点击了注册按钮") } @objc fileprivate func loginBtnClic() { DLog(message: "点击了登录按钮") }
}

3:Appdelegate中设置Navbar的渲染

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { //MARK:-1:设置全局tab渲染颜色
UITabBar.appearance().tintColor = UIColor.orange //MARK:-2:设置全局导航栏渲染颜色
UINavigationBar.appearance().tintColor = UIColor.orange return true
}
} //MARK:-1:定义全局打印 func DLog<T> (fileName:String = #file,function:String = #function,lineNum:Int = #line, message:T) { #if DEBUG let fileNameComponse = (fileName as NSString).lastPathComponent
print("\(fileNameComponse):\(function):\(lineNum):\("打印内容"):\(message)") #endif
}

4:子类控制器中调用

import UIKit

class HomeViewController: RHBaseTableViewController {

    override func viewDidLoad() {
super.viewDidLoad() //MARK:-1:让iconImageView旋转
visitorView.rotationImage()
} }
import UIKit

class MessageViewController: RHBaseTableViewController {

    override func viewDidLoad() {
super.viewDidLoad() //MARK:-1:更换图片和title,取消动画
visitorView.setupVisitorView("visitordiscover_image_message", title: "支持MJExtension,没毛病,关注MJExtension,有惊喜") } }

swift项目第七天:构建访客界面以及监听按钮点击的更多相关文章

  1. 第2节 网站点击流项目(下):6、访客visit分析

    0: jdbc:hive2://node03:10000> select * from ods_click_stream_visit limit 2;+--------------------- ...

  2. swift项目-模仿团购(主界面的搭建,以及首页的一些细节)

    以前学习oc的时候写的一个团购的项目,现在学习swift,拿来用swift写一遍,也是连猜带蒙的,一点一点的往上凑. 今天主要是把主要的架子搭起来了. 主要有:UITabBarController,U ...

  3. swift项目第八天:自定义转场动画以及设置titleView的状态

    如图效果: 一:Home控制器 /* 总结:1:设置登陆状态下的导航栏的左右按钮:1:在viewDidLoad里用三目运算根据从父类继承的islogin的登陆标识来判断用户是否登陆来显示不同的界面.未 ...

  4. swift项目初体验--教你打造一款个性化图片浏览器(篇幅过大,慎入)

    项目需求:做一个图片浏览器,点击图片查看大图,大图模式下,左右滚动能查看不同的图片. 项目的主要核心技术:图片的弹出和消失动画     项目源代码: Photo-Browser   一.对代码进行重构 ...

  5. [技术博客]react native事件监听、与原生通信——实现对通知消息的响应

    在react native中会涉及到很多页面之间的参数传递问题.静态的参数传递通常利用组件的Props属性,在初始化组件时即可从父组件中将参数传递到子组件中.对于非父子关系的组件来说,无法直接传递参数 ...

  6. 7.Flink实时项目之独立访客开发

    1.架构说明 在上6节当中,我们已经完成了从ods层到dwd层的转换,包括日志数据和业务数据,下面我们开始做dwm层的任务. DWM 层主要服务 DWS,因为部分需求直接从 DWD 层到DWS 层中间 ...

  7. 8.Flink实时项目之CEP计算访客跳出

    1.访客跳出明细介绍 首先要识别哪些是跳出行为,要把这些跳出的访客最后一个访问的页面识别出来.那么就要抓住几个特征: 该页面是用户近期访问的第一个页面,这个可以通过该页面是否有上一个页面(last_p ...

  8. Swift项目兼容Objective-C问题汇总

    Swift项目兼容Objective-C问题汇总 转载自 http://www.cocoachina.com/swift/20150608/12025.html 本文是投稿文章,作者:一叶(博客)欢迎 ...

  9. 《点石成金-访客至上的web和移动可用性设计秘籍》读书笔记

      简介 作者Steve Krug,惯例先去了解一下本书的作者,发现书中介绍的并不多,百度一下后发现这本书比作者出名.好吧,百度就是这样子,作者自称web可用性咨询师,手上这本书是第三版再版,第一版2 ...

随机推荐

  1. 给iOS项目中添加图片,并通过UIImageView引用和显示该UIImage图片

    [问题] 关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件 过程中,问题转换为,需要给当前iOS项目中,添加一个图片. 类似于Windows开发中的资源文件,其中图片文件属于资源的 ...

  2. 51Nod 圆与三角形

    给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是否相交.相交输出"Yes",否则输出"No".(三角形的面积大于0).   Input 第1行:一个数T ...

  3. dig---域名查询

    dig命令是常用的域名查询工具,可以用来测试域名系统工作是否正常. QUESTION SECTION 这部分是提问,显示你要查询的域名 ANSWER SECTION 即答案,显示查询到的域名对应的IP ...

  4. dp之多重背包(未用二进制优化)

    hdu 2191: #include <iostream>#include <stdio.h>#include <string.h>using namespace ...

  5. iOS 创建静态库文件时去掉当中的Symbols

    在project中创建静态库文件时.默认会将一些Symbols加到静态库文件里.这样做有两个缺点: 1.假设引用静态库文件的project中发生了bug.就会直接跳转到静态库的源代码. 也许有人问:静 ...

  6. 一些VPS

    https://www.perfectip.net                                        5美元/1C/4G/20G/10Thttps://www.hetzne ...

  7. js08--函数1

    函数当成类看当成匿名对象看,都是跟java吻合的,只有当成函数看(函数自己可以执行)跟java区别在这里. function fact(){} var F = fact ; 函数名是函数对象的地址,是 ...

  8. C#操作SQLite方法实例详解

    用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox  用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...

  9. ViewPager (下)-- 利用 Fragment 实现美丽的 页面切换

    之前用的ViewPager适用于简单的广告切换,但实现页面间的切换最好是用官方推荐的Fragment来处理. 本人力争做到最简单.最有用,是想以后用到的时候能够方便的拿过来复制就能够了. 效果图: w ...

  10. 1.1 Introduction中 Topics and Logs官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Topics and Logs 话题和日志 (Topic和Log) Let's fi ...