前言
第一天我们把项目如何托管到github中,今天主要记录基本框架的搭建,和简单的UI实现。碰到的问题如下
1、swift中如何动态加载控制
2、swift中本地文件的序列化和容错处理
3、swift按钮事件的监听写法
4、swift中cocopods使用SnapKit
5、如何自定义View和xib定义view以及swift中类方法的写法
6、swift中协议的写法
7、swift中如何用闭包来代替协议
最后简单的实现效果如下图
1、动态加载控制
首先继承一个UITabBarController的子类
class YJBaseTabBarViewController: UITabBarController
在该控制中添加我们需要添加的子控制器,子控制需要包装一层导航控制器。一般我不直接使用系统的控制器,所以还写了下面两个类
class YJBaseNaviViewController: UINavigationController
class YJBaseTableViewController: UITableViewController
我们的控制器都继承于 YJBaseTableViewController
在YJBaseTabBarViewController中viewDidLoad中添加子控制,定义一个方法,用来添加子控制器
// MARK: 添加子控器
private func addChildViewController(childController: UIViewController ,title:String, imageName:String) {
let main = childController
main.title = title;
main.tabBarItem.image = UIImage(named: imageName)
main.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted")
//创建一个nav
let navi = YJBaseNaviViewController()
navi.addChildViewController(main)
addChildViewController(navi)
}
我们还可以根据服务器返回的类名来动态加载我们的子控制器,于是我又定义了下面的方法
// MARK: 通过字符串动态加载控制
private func addChildViewController(childControllerName: String,title:String, imageName:String) {
//在swift中有动态命名空间的概念,默认未工程名字
let prodouctName = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as! String
//获取类名
let className:AnyClass? = NSClassFromString(prodouctName + "." + childControllerName)
// 将类名转化为指定的类型
let vcCls = className as! UIViewController.Type
// 调用初始化方法
let childVC = vcCls.init()
addChildViewController(childVC, title: title, imageName: imageName)
}
这里主要碰到的问题swift中如何通过字符串来获取类名,然后再通过类来创建需要的控制器。上面的代码我想已经写的够详细了。
2、本地文件的序列化处理,使用do和catch来处理序列化容错
由于我们没有网络返回的数据,我们就直接模拟动态加载,在本地添加一个json文件,然后我们解析json文件,然后加载我们的控制器
方法如下:
// 解析本地json
let jsonPath = NSBundle.mainBundle().pathForResource("localSettings.json", ofType: nil)
if let resultPath = jsonPath {
print(resultPath)
//转为data
let fileData = NSData.init(contentsOfFile: resultPath)
if let realData = fileData {
//在这里序列化,序列化可能会出现,抛异常
do {
// 这里正常解析
let jsonArr = try NSJSONSerialization.JSONObjectWithData(realData, options: .MutableContainers)
//遍历数组,这里需要注意因为json返回的是Anyobject对象,需要将其转为数组
for dict in jsonArr as![[String:String]] {
addChildViewController(dict["vcName"]!, title: dict["title"]!, imageName: dict["imageName"]!)
}
print("解析成功")
}
catch {
print(error)
// 异常处理,如果解析json失败,就自己创建
//创建首页
addChildViewController("YJMainViewController", title: "首页", imageName:"tabbar_home")
//消息
addChildViewController("YJMessageViewController", title: "消息", imageName:"tabbar_message_center")
//发现
addChildViewController("YJAttentionViewController", title: "发现", imageName:"tabbar_discover")
//我的
addChildViewController("YJMineViewController", title: "我的", imageName:"tabbar_profile")
}
}
}
3、按钮点击事件的写法。
上图中间的按钮是我们自己添加一个的按钮,添加点击写法真心蛋筒,需要注意的是响应事件方法也不能用private来修饰
以前添加点击事件的可以这样写:
btn.addTarget(self, action: "composeClick", forControlEvents: .TouchUpInside)
现在上面的写法已经弃用改用下面的写法,但是蛋痛是写的时候根本没有提示。
btn.addTarget(self, action: #selector(YJBaseTabBarViewController.composeClick), forControlEvents: .TouchUpInside)
4、cocopods的使用
上面我们基本就能搭建好整体的框架,接下就需要实现未登陆界面,这里有UI布局,我们如果用代码的话,为了适配我们需要用autolayout来布局,我使用第三方库SnapKit,为了方便管理使用Cocopods来安装
a、首先需要安装cocopods,如果没有安装的话。
安装命令:sudo gem install cocoa pod
有可能会碰到安装出错,如下
则用下面的安装命令
sudo gem install -n /usr/local/bin cocoa pods
b、cd 到你工程目录
pod init
然后用Xcode打开编辑
open -a Xcode Podfile
写入下面内容
use_frameworks!
platform :ios, '9.0'
pod 'SnapKit'
关闭在终端中执行
pod install
等待安装完成
就可以通过上图那个打开我们的工程,这样我们就能使用第三方SnapKit
5、6、7、自定义view和xib自定义view类方法、协议、闭包
首页的未登陆界面,用来代码来自定义view,用Snapkit来布局UI。
代码自定义view必须写下面的方法
// 主页的访客视图、
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(rorationView)
addSubview(hourseView)
addSubview(introduceLabel)
addSubview(attentionButton)
}
// 如果是自定义xib view必须实现这个方法,不是的就不需要实现
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
下面是使用SnapKit布局的部分代码如下
// 在这里写布局相关的代码
weak var weakSelf = self
//旋转视图
rorationView.snp_makeConstraints { (make) in
make.size.equalTo(CGSizeMake(200, 200))
make.center.equalTo(weakSelf!)
}
其中有个关注按钮的点击事件需要传递给控制器,OC最容易想到的使用代理。swift中代理协议的写法必须继承:NSObjectProtocol协议,首先是声明协议。
//申明协议
protocol YJMainVisitorViewDelegate:NSObjectProtocol {
// 关注按钮点击
func attentioButtonClick()
}
在该view申明一个代理,主要需要使用weak关键字来修饰
// 申明代理
weak var delegate:YJMainVisitorViewDelegate?
在按钮响应事件中实现
//MARK: 按钮点击事件
func attentionClick() {
// 感觉这个写法要比OC简单
delegate?.attentioButtonClick()
}
这样想要监听关注点击事件只要成为它代理,遵守协议就能监听点击事件了。使用如下
首先,遵守协议
class YJMainViewController: YJBaseTableViewController,YJMainVisitorViewDelegate
然后成为visitorView的代理
let visitorView = YJMainVisitorView()
visitorView.delegate = self
最后实现代理方法
//MARK:YJMainVisitorViewDelegate
func attentioButtonClick() {
print("我点击关注按钮了")
}
上面的代理协议实现过程,走了六个步骤,实在让人蛋痛,于是想到了闭包和OC 的block有点类似,于是就尝试了下。
写法如下
首先在view中申明一个闭包属性
// 定义一个闭包
var attentClickBlock:(()->())?
然后在响应事件中
//MARK: 按钮点击事件
func attentionClick() {
//
attentClickBlock?()
}
最后在控制器中的使用如下
let visitorView = YJMainVisitorView()
visitorView.attentClickBlock = {
print("我闭过包来的")
}
我还是习惯用闭包,因为简单啊,我是个怕麻烦的人。
消息的未登陆页面,我们采用xib关联的方式来实现,必须重写下面的方法
// 自定义xib重写这个方法
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
其他实现和OC基本一样我就不描述了,另外就是swift中类方法的写法,使用 internal和 class两个关键字来声明
//MARK: 获取messageVisitorView,声明类方法 internal
internal class func messageVisitorView() ->(YJMessageVisitorView){
return NSBundle.mainBundle().loadNibNamed("YJMessageVisitorView", owner: nil, options: nil).first as! YJMessageVisitorView
}
今天的内容到此结束,如果有什么错误的地方,希望指正,毕竟swift我用的不多,不是很熟,谢谢!!!