No2 项目框架搭建

一 自定义log

  • 部署项目
    No2 项目框架搭建_第1张图片

  • 设置启动图片
    No2 项目框架搭建_第2张图片

  • 更改项目名称
    No2 项目框架搭建_第3张图片

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

    // 1.创建window
    window = UIWindow(frame: UIScreen.mainScreen().bounds)
    window?.backgroundColor = UIColor.whiteColor()
    // 2.创建根控制器
    window?.rootViewController = ViewController()
    // 3.显示界面
    window?.makeKeyAndVisible()
    return true
  }
  • 项目分为开发阶段和发布阶段, 开发阶段自动显示LOG, 发布阶段自己屏蔽LOG
文件名称-方法名称[行号]: 输出内容
print(__FILE__) // 拿到当前文件路径
print(__LINE__) // 拿到当前的行号
print(__FUNCTION__) // 拿到当前的方法名称
// T的含义: 外界传入什么就是什么
func NJLog(message: T, file: NSString = __FILE__, method: String = __FUNCTION__, line: Int = __LINE__)
{
    #if DEBUG
    print("\(method)[\(line)]: \(message)")
    #endif
}

二 搭建基本框架

  • 设置MainViewController
  // MARK: - 内部控制方法
    func addChildViewController(childController: UIViewController, title: String, imageName: String) {
        // 1.添加子控制器
       // 如果是在iOS8以前, 只有文字有效果, 而图片没有效果
       // 设置tinColor是ios8之后做法,渲染设置是之前常用方法
        tabBar.tintColor = UIColor.orangeColor()

        // 1.1创建一个子控制器
        let homeVC = HomeTableViewController()
        // 1.2设置子控制器的相关属性
        homeVC.tabBarItem.image = UIImage(named: imageName)
        homeVC.tabBarItem.selectedImage = UIImage(named: imageName  + "_highlighted")

        // 1.3给子控制器包装一个导航控制器
        let nav = UINavigationController(rootViewController: homeVC)  
        // 1.4添加
        addChildViewController(nav)
    }
  • 设置导航栏标题(最下面代码替代注释代码)
//   homeVC.tabBarItem.title = title
//   homeVC.navigationItem.title = title
     // 系统会由内向外的设置标题
     homeVC.title = title

三 应用空间

  • 应用场景:公司App活动样式定时边换
  • 老版本的代码中包括新活动代码,用户启动程序发送请求到服务器,服务器返回JOSN数据,判断JOSN数据
  // 0.动态获取命名空间
    let nameSpace = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"]
    if let ns = nameSpace as? String
    {
   // 注意: 1.在Swift中, 如果想通过字符串创建一个类, 那么必须加上命名空间
  //        2.动态获取的命名空间是不包含.的, 所以需要我们自己手动拼接
  let cls: AnyClass? = NSClassFromString(ns + "." + childControllerName)
         // 1.将AnyClass类型转换为UIViewController类型
         // AnyClass本质: AnyObject.Type
         // UIViewController本质: UIViewController.Type
         if let clsType = cls as? UIViewController.Type
         {
             // 2.根据控制器类类型创建一个控制器对象
             let homeVC = clsType.init()
             print(homeVC)

             // 1.添加子控制器
             tabBar.tintColor = UIColor.orangeColor()

            // 1.2设置子控制器的相关属性
            homeVC.tabBarItem.image = UIImage(named: imageName)
            homeVC.tabBarItem.selectedImage = UIImage(named: imageName  + "_highlighted")  
           // 系统会由内向外的设置标题
           homeVC.title = title

           // 1.3给子控制器包装一个导航控制器
        let nav = UINavigationController(rootViewController: homeVC)      
           // 1.4添加
           addChildViewController(nav)
     }

四 guard判断语句

  • 格式:
guard 条件表达式 else {
            需要执行的语句
            return
        }
  • 特点: 只要条件为假才会执行else中的代码
  • 作用: 用于过滤数据
    • 对比if else 这哥们只有else{}没有if{}
// 1.将AnyClass类型转换为UIViewController类型
   guard let clsType = cls as? UIViewController.Type else{
     print("传入的字符串不能当做UIViewController来使用")
    return
  }

五 动态创建类

  • 动态加载控制器
// 1.获取文件路径
   let path = NSBundle.mainBundle().pathForResource("MainVCSettings.json", ofType: nil)!
// 2.根据文件创建
   let data = NSData(contentsOfFile: path)!
// 在OC中处理异常是通过传入一个NSError的指针来保存错误
// Swfit中提供了专门处理异常机制 throws -> AnyObject
// Swift中提供 try catch, 将有可能发生错误的代码放到do中, 如果真的发生了异常就会执行catch
// try作用: 如果抛出(throws)异常, 那么就会执行catch
// try!作用: 告诉一定一定没有错误, 不需要处理, 但是如果使用try!发生了错误, 那么程序就会崩溃, 开发中不推荐使用
// try?作用: 告诉系统可能有错也可能没有错, 如果发生错误会返回一个nil, 如果没有发生错误, 会将数据包装成可选类型
    do{
        let dictArr = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)
        for dict in dictArr as! [[String: AnyObject]]
            {
        addChildViewController(dict["vcName"] as? String, title: dict["title"] as? String,imageName: dict["imageName"] as? String)
            }
        }catch
        {
        addChildViewController("HomeTableViewController", title: "首页", imageName: "tabbar_home")
                    ……
    }

六 加号发布按钮

// MARK: - 懒加载
 lazy var composeButton: UIButton = {
      let btn = UIButton()
      // 1.设置背景图片
      btn.setBackgroundImage(UIImage(named: "tabbar_compose_button"), forState: UIControlState.Normal)
      btn.setBackgroundImage(UIImage(named: "tabbar_compose_button_highlighted"), forState: UIControlState.Highlighted)
      // 2.设置普通图片
      btn.setImage(UIImage(named: "tabbar_compose_icon_add"), forState: UIControlState.Normal)
      btn.setImage(UIImage(named: "tabbar_compose_icon_add_highlighted"), forState: UIControlState.Highlighted) 
      // 3.监听按钮点击
      btn.addTarget(self, action: Selector("composeBtnClick"), forControlEvents: UIControlEvents.TouchUpInside)       
      btn.sizeToFit()
      return btn;
    }()
override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        // 1.初始化加号按钮
        setupComposeButton()
    }
  • 添加加号按钮
// MARK: - 内部控制方法
    // 如果在方法前面加上private, 代表这个方法只能在当前文件中访问
    // 如果在属性前面加上private, 代表这个属性只能在当前文件中访问
    // 如果在类前面加上private,  代表这个类只能在当前文件中访问
    private func setupComposeButton()
    {
        // 0.将加号按钮添加到tabbar上
        tabBar.addSubview(composeButton)

        // 1.计算宽度
        let width = UIScreen.mainScreen().bounds.width / CGFloat(childViewControllers.count)
        // 2.计算高度
        let height = tabBar.bounds.height
        // 3.修改frame
        let rect = CGRect(origin: CGPointZero, size: CGSize(width: width, height: height))
        /*
        CGRectOffset
        第一个参数:控件的frame
        第二个参数:控件x方向偏移的值
        第三个参数:控件y方法偏移的值
        */
        composeButton.frame = CGRectOffset(rect, 2 * width, 0)
    }
  • 新建一个UIButton分类
 class func create(imageName: String, backImageName: String) -> UIButton
    {
        let btn = UIButton()
        // 1.设置背景图片
        btn.setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)

        // 2.设置普通图片
        btn.setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
        btn.setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)

        btn.sizeToFit()

        return btn
    }

虽然以下方法可以快速创建一个UIButton对象, 但是Swift风格不是这样写的
在Swift开发中, 如果想快速创建一个对象, 那么可以提供一个便利构造器(便利构造方法)
只要在普通构造方法前面加上一个convenience, 那么这个构造方法就是一个便利构造方法

  • 定义便利构造器步骤:
    • 1.编写一个构造方法
    • 2.在构造方法前面加上 convenience
    • 3.在构造方法中调用当前类的其他”非便利构造器”初始化对象
 convenience init(imageName: String, backImageName: String)
 {
   self.init()      
  // 1.设置背景图片
     setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
     setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)

  // 2.设置普通图片
     setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
     setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)

     sizeToFit()
    }
  • 监听点击事件
  // 注意: 由于点击事件是由NSRunLoop发起的, 并不是当前类发起的, 所以如果在点击方法前面加上private, 那么NSRunLoop无法找到该方法
    // OC是基于运行时动态派发事件的, 而Swift是编译时就已经确定了方法
    // 如果想给监听点击的方法加上private, 并且又想让系统动态派发时能找到这个方法, 那么可以在前面加上@objc, @objc就能让这个方法支持动态派发
    @objc private func composeBtnClick()
    {
        NJLog("")
    }

七 访客视图

  • 有一个判断逻辑
  // 通过代码创建一个控件就会调用
    override init(frame: CGRect) {
        super.init(frame: frame)
//        backgroundColor = UIColor.purpleColor()
    }
    // 通过XIB/SB 创建一个控件就会调用
    // 在Swift中, 为了简化业务逻辑, 默认情况下如果说自定义一个View, 那么建议要么是自定义代码的, 要么是自定义XIB/SB
    required init?(coder aDecoder: NSCoder) {
        // fatalError: 致命错误
  //    fatalError("init(coder:) has not been implemented")
        super.init(coder: aDecoder) //既要代码可以创建,XIB/SB也可以创建
    }
  • 创建view上子控件
 // MARK: - 懒加载
    /// 转盘
    private lazy var homeIcon: UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_image_smallicon"))
    /// 图标
    private lazy var icon: UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_image_house"))
    /// 文本标签
    private lazy var title: UILabel = {
       let lb = UILabel()
        lb.numberOfLines = 0
        lb.textColor = UIColor.lightGrayColor()
        lb.text = "放假快乐短时间恢复了开始登记后方可洛杉矶放假快乐短时间"
        return lb
    }()
    /// 注册按钮
    private lazy var registerButton: UIButton = {
        let btn = UIButton()
        btn.setTitle("注册", forState: UIControlState.Normal)
        btn.setTitleColor(UIColor.orangeColor(), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: "common_button_white_disable"), forState: UIControlState.Normal)
        return btn
    }()
    /// 登录按钮
    private lazy var loginButton: UIButton = {
        let btn = UIButton()
        btn.setTitle("登录", forState: UIControlState.Normal)
        btn.setTitleColor(UIColor.orangeColor(), forState: UIControlState.Normal)
        btn.setBackgroundImage(UIImage(named: "common_button_white_disable"), forState: UIControlState.Normal)
        return btn
    }()
    /// 背景颜色图片
    private lazy var maskImageView: UIImageView = UIImageView(image: UIImage(named: "visitordiscover_feed_mask_smallicon"))
}
  • 添加和布局子控件
 // MARK: - 内部控制方法
 private func setupUI()
 {
        // 1.添加子控件
        addSubview(homeIcon)
        addSubview(maskImageView)
        addSubview(icon)
        addSubview(title)
        addSubview(registerButton)
        addSubview(loginButton)

        // 2.布局子控件(第三方框架SnapKit)
        // 2.1布局转盘
        homeIcon.snp_makeConstraints { (make) -> Void in
            make.center.equalTo(self)
        }
        // 2.2布局图标
        icon.snp_makeConstraints { (make) -> Void in
            make.centerX.equalTo(self)
            make.centerY.equalTo(self).offset(15)
        }
        // 2.3布局标题
        title.snp_makeConstraints { (make) -> Void in
            make.centerX.equalTo(self)
            make.top.equalTo(homeIcon.snp_bottom).offset(15)
            make.width.equalTo(225)
        }
        // 2.4布局注册按钮
        registerButton.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(title)
            make.top.equalTo(title.snp_bottom).offset(15)
            make.width.equalTo(100)
        }
        // 2.5布局登录按钮
        loginButton.snp_makeConstraints { (make) -> Void in
            make.right.equalTo(title)
            make.top.equalTo(title.snp_bottom).offset(15)
            make.width.equalTo(100)
        }
        // 2.6布局蒙版
        maskImageView.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(self)
            make.right.equalTo(self)
            make.top.equalTo(self)
            make.bottom.equalTo(registerButton.snp_top)
        } 
        // 2.7设置view的背景颜色
        backgroundColor = UIColor(white: 235.0/255.0, alpha: 1.0)
    }
  • 不同的控制器view显示不同的view
 // MARK: - 外部控制方法
    func setupVisitorInfo(imageName: String?, title: String)
    {
        // 设置标题
        self.title.text = title
        guard let name = imageName else{
            // 首页
            startAnimation()
            return
        }
        // 不是首页
        // 设置中间图标
        icon.image = UIImage(named: name)
        // 隐藏转盘
        homeIcon.hidden = true
    }
  • 拿到访客视图
 /// 访客视图
    var visitorView: VisitorView?
    override func loadView() {
        login ? super.loadView() : setupVisitorView()
    }
  • 设置首页
    • 其他viewcontroller的雷同
  override func viewDidLoad() {
     super.viewDidLoad()   
     // 1.判断是否登录
     if !login{
       visitorView?.setupVisitorInfo(nil, title: "关注一些人,回这里看看有什么惊喜")
          return
        }    
    }
  • 执行转盘旋转动画
private func startAnimation()
    {
     // 1.创建动画对象
     let anim = CABasicAnimation(keyPath: "transform.rotation") 
     // 2.设置动画属性
       anim.toValue = 2 * M_PI
       anim.repeatCount = MAXFLOAT
       anim.duration = 10.0
      // 设置动画不自动移除, 等到view销毁的时候才移除
       anim.removedOnCompletion = false  
      // 3.将动画添加到图层上
        homeIcon.layer.addAnimation(anim, forKey: nil)
    }
  • 初始化未登录界面
    • 监听点击(没有用通知、代理和block)
private func setupVisitorView()
    {
     // 1.创建访客视图
     visitorView = VisitorView()
     view = visitorView

     // 2.监听访客视图按钮的点击
     visitorView?.registerButton.addTarget(self, action: Selector("registerDidClick"), forControlEvents: UIControlEvents.TouchUpInside)
     visitorView?.loginButton.addTarget(self, action: Selector("loginDidClick"), forControlEvents: UIControlEvents.TouchUpInside)

     // 3.添加导航条注册登录按钮
     navigationItem.leftBarButtonItem = UIBarButtonItem(title: "注册", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("registerDidClick"))
     navigationItem.rightBarButtonItem = UIBarButtonItem(title: "登录", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("loginDidClick"))
    }
  • tineColor设置可以放到启动项里面 AppDelegate.swift
//  一般情况下全局性的属性都放到程序已启动设置
private func setupAppearance()
    {
        UINavigationBar.appearance().tintColor = UIColor.orangeColor()
        UITabBar.appearance().tintColor = UIColor.orangeColor()
    }
  • 抽取图片分类
extension UIImageView
{
    convenience init(imageName: String)
    {
        self.init(image: UIImage(named: imageName))
    }
}
  • 抽取Label分类
extension UILabel
{
    // 遍历构造方法的参数不能指定默认参数
    convenience init(color: UIColor, lines: Int)
    {
        self.init()
        textColor = color
        numberOfLines = lines
    }
}

七 首页图片按钮

  • 初始化导航条
private func setupNav()
    {
    navigationItem.leftBarButtonItem = UIBarButtonItem(imageName: "navigationbar_friendattention", target: self, action: Selector("leftBtnClick"))
        navigationItem.rightBarButtonItem =  UIBarButtonItem(imageName: "navigationbar_pop", target: self, action: Selector("rigthBtnClick"))
    }
  • 抽取一个分类UIBarButtonItem
extension UIBarButtonItem
{
    /**
    创建item
    - parameter imageName: item显示图片
    - parameter target:    谁来监听
    - parameter action:    监听到之后执行的方法
    */
    convenience init(imageName: String, target: AnyObject?, action: Selector)
    {
        let btn = UIButton()
        btn.setImage(UIImage(named: imageName), forState: UIControlState.Normal)
        btn.setImage(UIImage(named: imageName + "_highlighted"), forState: UIControlState.Highlighted)
        btn.addTarget(target, action: action, forControlEvents: UIControlEvents.TouchUpInside)
        btn.sizeToFit()    
        self.init(customView: btn)
    }
}

你可能感兴趣的:(Swift系列)