一:Appdelegate
import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { /* 總結: 1:1:window為可選類型,可選類型的定義:var window: UIWindow?,可選類型就是可以為空值nil或是有值,若是想獲得可選類型的值,則可以進行可選綁定或是強制解包,若是強制解包必須要保證強制解包的值不為nil,若為nil會產生崩潰,一般可選綁定用guard else進行校驗(let會自動解包) 2:var window: UIWindow?,為該類的屬性,定義屬性的時候,必須保證屬性有初始化值,或是定義成可選類型,否則會報錯 2:需要自己去創建window:創建對象就用構造函數:RHTabBarViewController(),獲得實例對象之后,調用方法可以使用點語法window?.makeKeyAndVisible() window = UIWindow(frame:UIScreen.main.bounds) window?.rootViewController = RHTabBarViewController() window?.makeKeyAndVisible() 3:設置全局tabBar的樣式:設置tabBar的tintColor,就是改變tabbarItem的圖片文字顏色,若不設置,則系統會自動將圖片和文字渲染為藍色:UITabBar.appearance().tintColor = UIColor.orange 4:設置全局的函數,或是全局的樣式,都在AppDelegate文件中去設置 */ var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { //MARK:-1:創建window window = UIWindow(frame:UIScreen.main.bounds) window?.rootViewController = RHTabBarViewController() window?.makeKeyAndVisible() //MARK:-2:設置全局tabbar的樣式 UITabBar.appearance().tintColor = UIColor.orange DLog(message: "123") return true } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. } func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } } //MARK:-3:定義全局的DLog:使用全局函數:傳默認參數 /* 總結:1:設置全局函數都在AppDelegate中進行設置,class 類聲明之后 2: 自定義Log: 定義Log 1. 定義Log的打印內容 獲取所在的文件 #FILE 獲取所在的方法 #FUNCTION 獲取所在的行 #LINE 默認參數:當在方法中傳參數時,也可以傳入默認參數,定義:file : String = #file,默認參數在外界傳遞參數的時候不會顯示 全局函數:在AppDelegate中定義全局函數:<T>表示泛型,傳打印內容:func DLog<T> (message: T,fileName:String = #file,funcName:String = #function,lineNum:Int = #line) 2.DLog在Debug下 打印,在release下 不打印 定義標記項 —>buildSettings—>搜索swift flag—>Debug -> -D DEBUG 做標記--------在項目中實現:#if DEBUG #endif 3:1:#if DEBUG //DEBUG模式下 let file = (fileName as NSString).lastPathComponent; print("\(file):\(funcName):\(lineNum):\("打印內容"):\(message)") #endif 2:let file = (fileName as NSString).lastPathComponent;獲取文件的擴展名,(fileName as NSString)將swift的字符串轉為OC字符串,並調用OC的方法,關鍵字as,在截取字符串的時候也通常將swift的字符串轉為OC字符串來進行截取 3: print("\(file):\(funcName):\(lineNum):\("打印內容"):\(message)"):插值運算:插值運算"\()"來表示。 */ func DLog<T> (message: T,fileName:String = #file,funcName:String = #function,lineNum:Int = #line) { #if DEBUG let file = (fileName as NSString).lastPathComponent; print("\(file):\(funcName):\(lineNum):\("打印內容"):\(message)") #endif }
二:RHTabBarViewController
import UIKit class RHTabBarViewController: UITabBarController { /** 總結:1:1:在RHTabBarViewController上添加子控制器:需要封裝一個函數(封裝的函數寫在class類里),外部傳控制器對象,title,imageName 2:swift支持方法的重載,方法的重載:方法名稱相同,但是參數不同. --> 1.參數的類型不同 2.參數的個數不同,在定義函數時使用private修飾,表示在當前文件中可以訪問,但是其他文件不能訪問private func addChildViewController(_ childController: UIViewController,title : String,imageName:String),其中第一個參數的下划線可以省略,那么如果省略外部調用,第一個參數名就會顯示出來, addChildViewController(childController: <#T##UIViewController#>, title: <#T##String#>, imageName: <#T##String#>) 如果不省略: addChildViewController(<#T##childController: UIViewController##UIViewController#>, title: <#T##String#>, imageName: <#T##String#>) 2:創建對象用的是構造函數:RHHomeTableViewController(),在封裝的方法中,設置tabBar的標題,圖片:childController.title, childController.tabBarItem.image, childController.tabBarItem.selectedImage 其中: childController.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted"),字符串與字符串的拼接就用 + ,添加子控制器:addChildViewController(childNav),可以省略self去調用 */ override func viewDidLoad() { super.viewDidLoad() //MARK:-通過json文件創建初始化控制器 //1:讀取json文件的路徑 /* let urlPath = Bundle.main.path(forResource: "MainVCSettings.json", ofType: nil)//urlPath為可選類型 guard (urlPath != nil) else { DLog(message: "獲取文件路徑失敗") return } 不能:swift中沒有非0即真,不能時候如下寫法,不許有明確的值,(urlPath != nil) guard urlPath else { DLog(message: "獲取文件路徑失敗") return } */ guard let urlPath = Bundle.main.path(forResource: "MainVCSettings.json", ofType: nil) else { DLog(message: "獲取文件路徑失敗") return } guard let data = try? Data.init(contentsOf: URL(fileURLWithPath: urlPath)) else { DLog(message: "獲取文件data失敗") return } guard let infoArr = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) else { DLog(message: "獲取文件infoDic失敗") return } guard let dataArr = infoArr as? [[String : AnyObject]] else { DLog(message: "獲取文件dataArr失敗") return } /* 1:從數組或是字典中取出的數據都是AnyObject類型,需要將AnyObject類型轉為可選類型,用as?來進行轉換,轉成為string類型的可選類型 2:一般可選類型都與guard else進行校驗,as?,將其他類型轉為可選類型 */ for dic in dataArr { guard let vcName = dic["vcName"] as? String else { continue } guard let title = dic["title"] as? String else { continue } guard let iamgeName = dic["imageName"] as? String else { continue } addSubChildViewController(className: vcName, title: title, imageName: iamgeName) } // //MARK:-1:添加子控制器 // // //首頁 // addChildViewController(RHHomeTableViewController(), title: "首頁", imageName: "tabbar_home") // // //信息 // addChildViewController(RHMessageTableViewController(), title: "信息", imageName: "tabbar_message_center") // // //發現 // addChildViewController(RHDiscoverViewController(), title: "發現", imageName: "tabbar_discover") // // //我 // addChildViewController(RHProfileTableViewController(), title: "我", imageName: "tabbar_profile") } //MARK:-1:添加子控制器:private:私有方法, private func addChildViewController(_ childController: UIViewController,title : String,imageName:String) { //1:設置子控制器tabBarItem的標題圖片 childController.title = title; childController.tabBarItem.image = UIImage(named: imageName) childController.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted") //2:添加子控制器 let childNav = UINavigationController(rootViewController: childController) addChildViewController(childNav) } private func addSubChildViewController(className:String,title:String,imageName:String) { /* 1: let nameSpace = Bundle.main.infoDictionary,此時的nameSpace為一個可選類型的字典,而我們能確定此可選類型的info.plist文件中肯定有值所以可以強制解包,Bundle.main.infoDictionary!["CFBundleExecutable"],此時強制解包出來的nameSpace為Any的類型,需要將Any轉換為String?的可選類型用as?來進行轉換 2:從數組或是字典取出來的數據為都為Any?的可選類型,1:如果一定有值的話,直接!進行強制解包,變為Any類型,還需要將Any類型的nameSpace轉換為string?類型的可選類型,用as?來進行轉換 2:如果不確定一定有值的話,可以用1:可選綁定 2:用guard else 進行校驗 3: guard 校驗兩種寫法:1: let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String; guard (nameSpace != nil) else { return } 2: guard let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else { return } */ ///1:獲取命名空間 // let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String; /* 此句代碼沒有進行解包,只是判斷可選類型是否為nil */ guard let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else { return } ///2:獲取類名 /* 1:獲取的類名,classfullName的類型為AnyClass?類型 let classfullName = NSClassFromString(nameSpace! + "." + className) 2:直接用guard else進行校驗,當用 let classfullName = NSClassFromString(nameSpace! + "." + className)此種類型為可選綁定,有值的話,直接將可選類型進行解包 3:如果 guard (nameSpace != nil) else { return } 此種寫法,不會對nameSpace進行解包 */ ///3:創建對象 guard let classfullName = NSClassFromString(nameSpace + "." + className) else { return } guard let childVC = classfullName as? UIViewController.Type else { return } let childVCtroller = childVC.init(); childVCtroller.title = title childVCtroller.tabBarItem.image = UIImage(named: imageName) childVCtroller.tabBarItem.selectedImage = UIImage(named: imageName + "_highlighted") let childNav = UINavigationController(rootViewController: childVCtroller) addChildViewController(childNav) } }
三:異常處理
import UIKit /** 總結:1:當調用某個函數有throw標志的時候,是表示該函數會拋出異常,swift拋出異常的方式有三種,try:都 catch 捕獲異常,error有異常信息,try?:可選類型捕獲異常,有異常會返回控制nil,try!:方式危險,若是有異常,直接會發生崩潰 2:三種表達方式:1:try:do catch do { let regex = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive) } catch { print(error) } 2:try?:可選類型,用guard else去校驗 guard let regex = try? NSRegularExpression(pattern: pattern, options: .CaseInsensitive) else { return } 3:try!:方式危險,若是有異常,直接會發生崩潰 let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive) */ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 正則表達式 // 1.創建正則表達式的規則 let pattern = "abc" // 2.創建正則表達式對象 // 方式一:try方式 // do { // let regex = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive) // } catch { // print(error) // } // 方式二:try?方式: // guard let regex = try? NSRegularExpression(pattern: pattern, options: .CaseInsensitive) else { // return // } // 方式三:try!方式(危險) let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive) } }
