主界面

1、我没有用storyboard布局,是在delegate里面手写代码创建的,代码如下

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window?.backgroundColor = UIColor.whiteColor()
    self.window?.makeKeyAndVisible()

    self.window?.rootViewController = XY_MainTabBarController.CustomTabBar()

    return true
}

在其中遇到一些小困难,因为初学swift,还没有搞明白?和!的用法,因此被坑了一大会儿。初开始是这样写的

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    self.window? = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window?.backgroundColor = UIColor.whiteColor()
    self.window?.makeKeyAndVisible()

    self.window?.rootViewController = XY_MainTabBarController.CustomTabBar()

    return true
}

由于在self.window? = UIWindow…这句话中用了?导致window一直为nil,并没有创建出来,所有在模拟器中看到的是大黑屏。
这里说一下原因,先看下面代码
代码
当我们在声明一个变量的时候,如果不给其初始值,则会报错。
类似这种写法

var stringValue:String //error: variable 'stringValue' used before being initialized

无论是变量还是常量在声明时是需要给其初始值的,如果你不想给其初始值,则需要用到Option了,在这里我简单的理解为?,其实Optional的原理在swift中的?和!

一旦声明为Optional的,如果不显示的赋值就会有个默认的值nil,因此上面的window为何为nil也得到了解释。

那?该如何用呢?

在看文档中,有提到,使用?得时候需要在具体的操作,比如调用方法、属性、下标索引等前面加上一个?,其意思是询问是否响应后面这个方法,和oc中的isResponseToSelector有些类似,如果是nil值,则不能响应后面的方法,反之执行。
!是表示前面的值肯定不为nil,直接就能调用后面的方法,而如果值一旦为nil,则会crash掉

2、

整体图

在XY_MainTabBarController中定义一个类型属性,代码如下

class func CustomTabBar()->UITabBarController {

    let viewControllerArray = ["XY_MessageController","XY_ContactListController","XY_HomeController","XY_DiscoverController","XY_MineController"]
    let tabBarVC = XY_MainTabBarController()

    let tabbarArray = ["message","mail","home","discover","mine"]
    var index:Int = 0
    //循环像tabbarcontroller中添加对应的子控制器
    for str in viewControllerArray{

        let vc = NSClassFromString(str) as UIViewController.Type
        //获取到对应的控制器类
        let viewcontroller = vc.self.init()
        //创建导航控制器
        let nav : UINavigationController = XY_NaviController(rootViewController: viewcontroller)
        tabBarVC.addChildViewController(nav)
        //设置对应的tabbaritem
        let normalStr:String = tabbarArray[index]
        let selectStr:String = normalStr+"_pre"
        nav.tabBarItem = UITabBarItem(title: nil, image: XY_Public.getImgView(normalStr), selectedImage: XY_Public.getImgView(selectStr))
        //调整对应tabbaritem的位置,制作成不规则的tabbar
        if index==2{
            nav.tabBarItem.imageInsets = UIEdgeInsetsMake(-9, 0, 9, 0)
        }else{
            nav.tabBarItem.imageInsets = UIEdgeInsetsMake(10, 0, -10, 0)
        }

        index++
    }
    //设置tabbar的背景
    tabBarVC.tabBar.translucent=false
    tabBarVC.tabBar.barStyle = .Black
    tabBarVC.tabBar.barTintColor = UIColor(patternImage: UIImage(named: "Main_tabBar_background")!)

    tabBarVC.tabBar.backgroundImage = UIImage(named: "Main_tabBar_background")
    return tabBarVC
}

其中碰到的问题是关于NSClassFromString在swift中不起作用,还有获得到对应控制器的名字如何实例化出来?
解决方法

1、NSClassFromString不起作用
在你传入的str中的类声明为

@objc(str)

2、如何实例化出对应的控制器
可以通过vc.self.init()创建出来,当然在使用该方法的前提是要声明vc的类型是viewController

例如这样的

import UIKit
@objc(XY_MineController)
class XY_MineController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    self.navigationItem.title = "我的"
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}