首页投稿(暂停使用,暂停投稿)iOS 开发 iOS Developer

第二天--框架的搭建和未登陆界面的实现

2016-08-20  本文已影响246人  改变自己_now

前言

第一天我们把项目如何托管到github中,今天主要记录基本框架的搭建,和简单的UI实现。碰到的问题如下

1、swift中如何动态加载控制
2、swift中本地文件的序列化和容错处理
3、swift按钮事件的监听写法
4、swift中cocopods使用SnapKit
5、如何自定义View和xib定义view以及swift中类方法的写法
6、swift中协议的写法
7、swift中如何用闭包来代替协议

最后简单的实现效果如下图

QQ20160820-0@2x.png

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

有可能会碰到安装出错,如下

0DA1D724-CEC7-4851-9D96-4C0FC10CDB4A.png

则用下面的安装命令

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

等待安装完成


5754B61B-3058-4ED3-897B-C50B25A3F84D.png

就可以通过上图那个打开我们的工程,这样我们就能使用第三方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我用的不多,不是很熟,谢谢!!!

上一篇下一篇

猜你喜欢

热点阅读