技能 1. 關于自定義標記
對于OC中 我們想在DEBUG狀態下做事情,但是不在 RELease中實現的時候,我們一般是定義宏,來實現,一般寫在.pch文件中. 代碼如下
#ifdef DEBUG
#define LXLLog(...) NSLog(@"%s\n %@\n\n", __func__, [NSString stringWithFormat:__VA_ARGS__])
#else
#endif
對于Swift中,由于沒有了宏定義這個一個功能,我們只能自己建造標記來定義,什么時候是 DEBUG,什么時候是RELEASE. 可以利用 方法來定義 對用的console 語句
// T指泛型,可由可無,任意類型. 此方法,可以輸出對應的文件, 方法名, 以及行號
func LXLLog<T>(message: T, file: String = __FILE__, method: String = __FUNCTION__, line: Int = __LINE__)
{
#if LXL_DEBUG
print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
#endif
}
但只是定義這么一個語句是不被使用的, 對已這個帶有標記的語句, 要進行再Swift中注冊說明
技能2: 關于SBRefrence 也就是 Storyboard refrence的使用
對于SBRefrence 的使用比較好, 可以很好的改變程序的結構,但是又不影響程序的正常使用.
技能3: Swift中main函數的消失
官方解釋:
In Xcode, Mac templates default to including a “main.swift” file, but for iOS apps the default for new iOS project templates is to add @UIApplicationMain to a regular Swift file. This causes the compiler to synthesize a mainentry point for your iOS app, and eliminates the need for a “main.swift” file.
Swift項目中添加了@UIApplicationMain 到swift文件中,使得編譯器合成了一個app入口,所以不需要main.swift文件
當然我們也可以手動創建程序的入口 main 函數:
1.注銷掉 @UIApplicationMain
2.手動創建名字為main的文件
import Foundation
import UIKit
UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(UIApplication), NSStringFromClass(AppDelegate))
`
技能4: 對于便利構造器(比較方便的構造器, convenience)的使用
對已一般對象的初始化, 我們經常使用 init() 進行初始化, 當然有時候我們會進行 對已經初始化的對象 添加新的屬性, 對于 便利構造器而言, 添加屬性可以重寫 init()方法進行添加, 這種以 init 方法開頭的重寫方法, 在Swift中我們稱之為 便利構造器, 它的使用必須 調用本類的指定構造器 也就是 必須 對本類所有 屬性進行初始化才可以使用.
Swift中 對于以 init()作為初始化的方法, 沒有返回值, 默認返回self, OC中是有返回值得, 并且確保 已經初始化父類屬性,才可以使用
還有一種構造方法稱之為 中 , 內部創建對象, 并且對于對象的屬性進行初始化, 并返回對象, 起始就是 對象建立的過程, 進行了二次封裝而已
/*
如果想給系統的類新增構造方法, 那么只能新增一個便利構造方法
如果構造方法是以 init 開頭, 那么該構造方法是一個指定構造方法
如果構造器方法的 init 前面還有 convenience, 那么這個構造方法 就是一個 遍歷構造方法
指定構造器和 便利構造 區別:
指定構造器:
必須初始化當前類的所有屬性
便利構造器:
不用初始化當前類的所有屬性, 但是它依賴于當前類中的其他構造方法 -- >其他構造方法已經 進行了類的初始化
在開發中, 不要隨便定義便利構造器,只有需要提供一個方法快速
*/
convenience init(imageName: String , backgroudImageName: String){
self.init()
setImage(UIImage(named: imageName), forState: .Normal)
setImage(UIImage(named: imageName + "_highlighted"), forState: .Highlighted)
setBackgroundImage(UIImage(named: backgroudImageName), forState: .Normal)
setBackgroundImage(UIImage(named: backgroudImageName + "_highlighted"), forState: .Highlighted)
sizeToFit()
}
技能4. 命名空間的使用
對于Swift中不可以根據字符串來創建對應的類, 必須借助于命名空間才可以創建對應的類 其中格式有: "空間名稱"+"."+"類名" 并且確定類名必須存在才可.
當然OC中可以直接創建. 因為OC沒有空間命名這么一個概念, 所有文件之間沒有聯系, 只能通過 導入 import 才可以使用
但是Swift中, 在同一個project中處于相同的工作空間, 具有相同的命名空間,對于新創建的類, 必須確定其命名空間才可以使用
這個命名空間 一般就是 自己創建應用的名稱
命名空間是哪一個那? 圖例說明:
代碼中的獲取:
// 1. 獲取當前應用程序的命名空間
// 在info 中 查詢 對應 "CFBundleExecutable"的值,取出, 這里使用 guard 是為了解包.
guard let nsp = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] as? String else{
return
}
print(nsp)
獲取到 對應的命名空間, 就可以 建立對應的 類的對象了, 這里并不是簡單的獲取類名而已 , 由字符串創建對應的類
// 注意: 在Swift中想通過字符串創建類, 必須加上命名空間
guard let cls: AnyClass = NSClassFromString(nsp + "." + (childControllerName ?? "")) else{
return
}
使用類創建對象, 必須先進行類的對象, 說明類的類型, 方可使用,,, as
guard let clsType = cls as? UIViewController.Type else {
return
}
// 對于這種以類型 進行創建的對象, 只能使用 init() 創建
let childController = clsType.init()
此時, 已經創建對應類型的 控制器, 可以進行使用了
技能5: 動態加載控制器. OC Swift 都可以使用
這里所用的思想, 就是 對于控制器的加載, 不能僅僅 依靠的固定的模式, 要將其統一到一個可以控制器的文件中 進行加載, 這樣我們 只要通過改變文件, 就可以改變控制器的加載, 讓程序處于不同的展示. 對于這樣的情況, 我們可以讓程序 下載對應的控制器文件, 然后根據文件 加載對應的控制器, 這里我們需要考慮網速的問題, 但是, 如果沒有網, 我們加載個屁
我們通過 plist文件進行加載:
這里我不在重復說明plist文件中 JSON 數組的組成 , 對于Swift創建空文件,內部進行填充數據即可.
// 1.獲取JSON文件路徑
let path = NSBundle.mainBundle().pathForResource("MainVCSettings", ofType: "json")!
// 2.加載JSON數據
let data = NSData(contentsOfFile: path)!
// 3.序列號JSON數據, 這里使用try? 來捕獲異常,發生異常返回null, 使用guard,來解包,沒有解包返回else
guard let objc = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) else {
addChildViewController("HomeTableViewController", title: "首頁", imageName: "tabbar_home")
addChildViewController("MessageTableViewController", title: "消息", imageName: "tabbar_message_center")
addChildViewController("NullViewController", title: "", imageName: "")
addChildViewController("DiscoverTableViewController", title: "發現", imageName: "tabbar_discover")
addChildViewController("ProfileTableViewController", title: "我", imageName: "tabbar_profile")
return
}
// 4. 類型確認
guard let array = objc as? [[String: AnyObject]] else {
return
}
// 遍歷 創建
for dict in array {
addChildViewController(dict["vcName"] as? String, title: dict["title"] as? String, imageName: dict["imageName"] as? String
}
技能6: 對于自定義控件中的問題 code
創建問題
這里需要說明, 對于初始化控件, 一般都是兩種方式: 1. 純代碼, 2. xib 或者SB創建.
required init?(coder aDecoder: NSCoder) {
// fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
setup()
}
上述方法中 注銷的語句,指的是致命錯誤方法,, 會直接導致應用的崩潰的
因為在Swift中, 推薦要么使用純代碼,要么使用文件進行創建
一旦我注銷掉, 就意味著, 兩種方式我都可以進行創建的
技能7: 核心動畫的使用. CABaseAnimation
同OC用法一致, 先設置需要 改變的屬性:
animationWithKeyPath: ""
這里有多個屬性和一進行選擇:
transform.scale = 比例轉換
transform.scale.x = 闊的比例轉換
transform.scale.y = 高的比例轉換
transform.rotation.z = 平面圖的旋轉
opacity = 透明度
margin
zPosition
backgroundColor 背景顏色
cornerRadius 圓角
borderWidth
bounds
contents
contentsRect
cornerRadius
frame
hidden
mask
masksToBounds
opacity
position
shadowColor
shadowOffset
shadowOpacity
shadowRadius
fromValue , 起始動畫位置
toVaue: 終止動畫位置
removedOnCompletion: 動畫完成后是否回到起始狀態, 也有防止動畫中斷的意思在理面
duration: 動畫時長
repeatCount: 動畫重復次數
動畫創建完畢后就能加入圖層了
func startAnimation() {
// 1.創建動畫
let anim = CABasicAnimation(keyPath: "transform.rotation")
// 2.設置動畫屬性
anim.toValue = 2 * M_PI
anim.duration = 5.0
anim.repeatCount = MAXFLOAT
// 告訴系統不要自動移除動畫
anim.removedOnCompletion = false
// 3.將動畫添加到圖層
imageView.layer.addAnimation(anim, forKey: nil)
}
技能8: 對于分類的建立
對于OC中 , 有專門的分類建立, Category.
但是對于Swift中, 建立分類必須自己建立獨立文件, 自己填寫繼承
因為Swift 是全局性的文件創建, 命名空間,只有加入特定詞匯 private, 才能是私有屬性, 所以這里的 分類,可以說是分類, 也可以說是繼承吧, 對于此種的方法, 同分類的使用方法是一樣的.
對于一些合并類屬性, 以及一些可以封裝類屬性, 皆可以用分類組成, 也可以用自定義組成.
對于分類 和 繼承, 一個重要的區別就是, 繼承是重寫已經有的方法, 分類是為了添加沒有的方法
技能9: 對于Swift盡量使用SB, 不要使用xib
Swift 中 要求盡量使用sb 去 圖形化創建界面 而不要使用xib', 這點從 launch由以前的 xib到現在的 sb 就可以看得出來
這一點又有一些矛盾, 對于創建過程 , 先找xib 在進行純碼創建