一、Swift趨勢(shì)
雖然還處于過渡時(shí)期,但趨勢(shì)很明朗了,Swift 必然會(huì)替代 Objective-C,并且比想象中來得快。現(xiàn)在就應(yīng)該做好準(zhǔn)備了。假如之前已經(jīng)掌握了 Objective-C,切換到 Swift 也不難。Swift 中很多概念在 Objective-C 中已經(jīng)存在。隨著時(shí)間推移,Swift 在整個(gè) iOS/Mac 工程中占的代碼比例會(huì)越來越多,而 Objective-C 作為粘合層還是會(huì)存在。
二、Swift優(yōu)缺點(diǎn)
用Swift的經(jīng)驗(yàn)尚淺,所以都是一些比較淺薄的理解,后面有更深刻的理解再補(bǔ)上。
優(yōu)點(diǎn):
- 代碼簡(jiǎn)潔。類的聲明和實(shí)現(xiàn)在一個(gè)文件中。
- 統(tǒng)一對(duì)屬性和方法的調(diào)用,都用.。
- 如果不加額外的訪問控制,所有的符號(hào)都是整個(gè)項(xiàng)目可見,無需考慮頭文件的問題。
- 結(jié)合playground,做到真正意義上的所見即所得
- 字符串處理太方便了。
//字符串比較和拼接實(shí)在是太方便了
let foo = "abc"
let bar = "abc"
if foo == bar {
//blablabla
}
print("====\(foo)+\(bar)")
- 語言上支持延遲加載。
lazy var imageView : UIImageView = {
var imageView = UIImageView(image: UIImage(named: "empty_hint"))
imageView.contentMode = .ScaleAspectFit
return imageView
}()
lazy var infoLabel : UILabel = {
var infoLabel = UILabel()
infoLabel.lineBreakMode = .ByWordWrapping //支持換行
infoLabel.numberOfLines = 0
return infoLabel
}()
lazy var button : UIButton = {
var button = UIButton()
button.titleLabel?.font = UIFont.systemFontOfSize(15)
button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
button.setBackgroundImage(UIImage(named: "buy_instance_hint_button"), forState: .Normal)
button.hidden = true
return button
}()
- 多返回值。比如下面這個(gè)函數(shù),如果使用Objective-C寫還是比較麻煩的。
//將 "創(chuàng)建中&#FA8C35" 翻譯成對(duì)應(yīng)的 "(字符串對(duì)象, 顏色對(duì)象)"
func YWSTranslateRichText (str : String) -> (text : String, color : UIColor) {
let statusArray = str.componentsSeparatedByString("&")
if statusArray.count == 0 {
return ("", UIColor.lightGrayColor())
}
if statusArray.count == 1 {
return (statusArray[0], UIColor.lightGrayColor())
}
return (statusArray[0], UIColor.fromHexString(statusArray[1]))
}
//使用方式如下
let (text, color) = YWSTranslateRichText(instanceStatusConf)
- 支持字符串作為枚舉值。
enum YWSECSInstanceStatus : String {
case Starting = "Starting"
case Running = "Running"
case Stopping = "Stopping"
case Stopped = "Stopped"
}
//使用方法
cell.ECSInstanceStatus = YWSECSInstanceStatus(rawValue: instanceStatus!)
//轉(zhuǎn)換成字符串
textDetailLabel.text = YWSECSInstanceStatus.Starting.rawValue
缺點(diǎn):
- Swift靈活性非常大,既能用OP,又能用OO,語法寫法還比較多樣化,所以團(tuán)隊(duì)項(xiàng)目合作中必須注意,盡量能統(tǒng)一風(fēng)格,否則會(huì)導(dǎo)致一片亂~
- Optional讓人頭疼,大量的?和!,沒處理好很容易導(dǎo)致崩潰。
- 強(qiáng)類型和Optional,給JSON解析帶來了災(zāi)難。
- 目前Xcode不支持對(duì)Swift寫的代碼做重構(gòu)。
- Build Settings里面設(shè)置Treat Warnings as Errors對(duì)Swift代碼無效。
- Swift不支持宏,OC里面比較常用的宏,比如下面這個(gè)UIColorFromRGB就沒法用了。
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
- 不支持與C++混編,必須通過OC包一下C++的接口,Swift才能使用。使用一些跨端的C++庫(kù)(OpenGL、全文搜索、網(wǎng)絡(luò)底層等)比較麻煩。
- Swift的錯(cuò)誤信息非常不準(zhǔn)確,難以準(zhǔn)確定位
坑
- 用private修飾的類,如果使用KVC來給屬性設(shè)置值,編譯不會(huì)報(bào)錯(cuò),運(yùn)行時(shí)也不會(huì)報(bào)錯(cuò),但就是設(shè)置不上。去掉private就好了。
- Swift和OC混著寫的時(shí)候,有時(shí)候會(huì)出現(xiàn)OC的類在CloudConsoleApp-Bridging-Header.h里面提供給Swift使用,但是這個(gè)類又需要引入CloudConsoleApp-Swift.h使用Swift的一些功能,這樣就循環(huán)包含了,沒法玩下去了。
Swift代碼規(guī)范指南
- Swift Style Guide | 中文版
- 推薦閱讀官方的 API Design Guidelines
三、資源整理
1.蘋果官方資源
-
蘋果官方為開發(fā)者提供的Swfit學(xué)習(xí)資源:https://developer.apple.com/swift/resources/
14998280519388.jpg
-
Swfit的官方網(wǎng)站:https://swift.org
這里會(huì)介紹Swift的開源階段成果和一些使用指導(dǎo),Swift的官方博客和Swift的一些動(dòng)向信息可以在這里看到
14998282182999.jpg -
Github上的官方資源是swift-evolution
可以在這個(gè)庫(kù)里看到Swift的最新進(jìn)度。因?yàn)镾wift是一門開源的語言,你可以在這里按照一定格式提出改進(jìn)的建議。
14998284728990.jpg
2. 第三方資源
這份指南匯集了Swift語言主流學(xué)習(xí)資源,并以開發(fā)者的視角整理編排。http://dev.swiftguide.cn
這個(gè)倉(cāng)庫(kù)“匯集了Swift語言主流學(xué)習(xí)資源,并以開發(fā)者的視角整理編排”。不得不說整理的非常的用心,也很全面。美中不足的是對(duì)于一個(gè)剛?cè)腴T的開發(fā)者忽然看到收集的這么多資源可能會(huì)不知從何下手。需要好好找出一些適合自己的資源。
從開發(fā)者角度介紹被廣泛運(yùn)用于實(shí)際Swift項(xiàng)目中的開源庫(kù)。
這個(gè)倉(cāng)庫(kù)篩選了被廣泛應(yīng)用在Swift項(xiàng)目中的優(yōu)質(zhì)開源庫(kù)。并且嘗試整理一些這些流行的庫(kù)的相關(guān)資源。如果你打算用Swift開發(fā)一個(gè)實(shí)際項(xiàng)目,希望這個(gè)倉(cāng)庫(kù)里收集的庫(kù)會(huì)對(duì)你有參考意義。
- 還有一個(gè)值得一提的是SwiftGG翻譯組:http://swift.gg 。定期會(huì)翻譯Swift的相關(guān)文章,對(duì)于日常的學(xué)習(xí)精進(jìn)也很有幫助。
14998295823327.jpg
視頻
- 斯坦福課程Stanford University: Developing iOS 8 Apps with Swift(中文字幕版 By @網(wǎng)易公開課)
14998416372889.jpg
書籍
推薦objccn出版的幾本書:《Swift開發(fā)者必備Tips》、《函數(shù)式Swift》、《Swift進(jìn)階》。這幾本書都很有很高的質(zhì)量,對(duì)于提高對(duì)Swift的掌握很有幫助。
優(yōu)秀Swift開發(fā)者推薦
如果你還使用微博的話我有幾個(gè)優(yōu)秀的Swift開發(fā)者推薦給你:
@StackOverflowError,被apple多次推薦的pin的開發(fā)者。知乎專欄地址:https://zhuanlan.zhihu.com/cocoanotes
@an00na,微博著名第三方客戶端墨客開發(fā)者。
@圖拉鼎,獨(dú)立開發(fā)者。iOS 作品:@奇點(diǎn)微博客戶端。
@沒故事的卓同學(xué)
優(yōu)秀網(wǎng)站推薦
- 輔助將舊的
Objective-C
代碼轉(zhuǎn)成Swift
Swiftify | Objective-C to Swift Converter
14998428932894.jpg -
swiftmi
致力于打造一個(gè)國(guó)內(nèi)專業(yè)的Apple Swift交流和分享地方
14998450192866.jpg
四、項(xiàng)目實(shí)戰(zhàn)之混編
簡(jiǎn)介
-
混編無非兩種情況:
- 在Objective - C工程或者文件使用Swift的文件
- 在Swift工程或者文件使用Objective - C文件
-
在混編的過程中最重要的兩個(gè)文件:
橋接文件:
橋接文件ProjectName-Bridging-Header.h
,在首次創(chuàng)建其他文件的時(shí)候,會(huì)自動(dòng)生成。如果不小心刪除后,也可以手動(dòng)添加,不過名字必須是工程名-Bridging-Header.h
,如果名字記不清也可以自己新建Header file后,在Targets-->Build Settings-->Swift Compiler - General-->Objective-C Bridging Header
配置文件路徑,這個(gè)文件主要是Swift使用OC類時(shí)使用。Objective-C Generated Interface Header Name
文件
這個(gè)文件是混編時(shí),系統(tǒng)生成的Swift文件對(duì)應(yīng)的Objective-C的頭文件,具體可以在Targets-->Build Settings-->Swift Compiler - General-->Objective-C Generated Interface Header Name
進(jìn)行配置,默認(rèn)文件名是工程名-Swift.h
,一般不做改動(dòng)。
使用
- Swift使用Objective-C
這種情況占絕大多數(shù)。只需要在ProjectName-Bridging-Header.h
這個(gè)頭文件中包含相關(guān)的頭文件就行。
pod組件另外一種引入的方式是通過#import引入。
比如SDWebImage可以通過下面兩種方式引入。
//在Bridging頭文件包含下面這個(gè)頭文件
#import <SDWebImage/UIImageView+WebCache.h>
//另外一種辦法,在Swift文件中引入。
import SDWebImage
Objective-C寫的類和方法都會(huì)被改成Swift的使用方式,下面是兩個(gè)很典型的例子。使用的時(shí)候需要嘗試一下才能找到翻譯的Swift方法。
//Objective-C
titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
titleLabel.numberOfLines = 0;
//Swift
cell.nameLabel?.lineBreakMode = .ByWordWrapping //全寫是 NSLineBreakMode.ByWordWrapping
cell.nameLabel?.numberOfLines = 0
//Objective-C
UIImage *image = [UIImage imageNamed:@"abc"];
//Swift
let image = UIImage(named: "abc")
- Objective-C使用Swift
當(dāng)在OC文件中調(diào)用Swift文件中的類的時(shí)候,首先在OC文件中要加上 #import "ProjectName-swift.h"
這個(gè)文件雖然在工程中看不到,但是它真實(shí)存在,編譯后,你可以按住Command+單擊該文件名,就會(huì)看到具體生成的代碼。
引入后,具體類的使用,直接按照OC的方式使用即可
混編注意事項(xiàng)
- 對(duì)于需要混編的Swift類添加@objc聲明或繼承NSObject或NSObject的子類
class TestClass
{
// 屬性
// 實(shí)現(xiàn)
}
如果要在Objective-C類中使用TestClass類,應(yīng)當(dāng)使用@objc加以聲明,或者將TestClass繼承自NSObject或NSObject的子類,否則,引入ProductName-Swift.h之后,程序找不到對(duì)應(yīng)類。
使用第三方Framework
設(shè)置: target-->build setting -->Packaging -->Defines Module為 “Yes”;
然后,配置文件Target -> Build Phases -> Link Binary,添加要導(dǎo)入的Framework;
最后,還是要配置橋接文件,比如要使用 abc-lib.framework庫(kù)中的 abc.h 就要這樣配置:#import"abc-lib/abc.h";
Subclass子類問題對(duì)于自定義的類而言,Objective-C的類,不能繼承自Swift的類,即要混編的OC類不能是Swift類的子類。反過來,需要混編的Swift類可以繼承自O(shè)C的類。 注解
OC宏文件
如Swift文件要使用OC中定義的宏,只能使用常量簡(jiǎn)單宏文件。
- Swift中使用OC的block
Swift 2.* :Swift中使用閉包Closure
不能使用Block作為屬性進(jìn)行傳值,必須是初始化方法或函數(shù)。
Objective-C文件中:
typedef void (^Myblock)(NSString *arg);
@interface FirViewController : UIViewController
@property (copy, nonatomic) Myblock myBlock;
//Swift 2.*版本,這種作為公共參數(shù)的形式,如果在Swift類中去回調(diào)的話,是有問題的。提示沒有初始化方法,所以使用下面的以Block為參數(shù)的方法
- (void)transValue:(Myblock) block
@end
下面是.m文件
- (void)transValue:(Myblock)block{
if (block) {
block(@"firBack");
}
}
在Swift文件回調(diào):
@IBAction func goFirstAction(sender: AnyObject) {
let firVC:FirViewController = FirViewController()
firVC. transValue { ( arg:String !) -> Void in
self.aBtn?.setTitle(arg, forState: UIControlState.Normal)
}
self.navigationController?.pushViewController(firVC, animated: true)
}
經(jīng)測(cè)試現(xiàn)在swift版本已經(jīng)支持
firVC?.myBlock = { (arg) -> Void in
//....
}
五、問題解答
1. 那是不是 Objective-C 就不需要學(xué)習(xí)呢?
并非如此。Swift 還沒有很好地解決好跟 C 和 C++ 混編的問題。很多項(xiàng)目底層核心庫(kù)會(huì)采用 C/C++,界面和大部分邏輯采用 Swift 編寫,需要 Objective-C 作為粘合層。另外還存留很多庫(kù)是用 Objective-C 編寫的,使用這些庫(kù)需要一定 Objective-C 知識(shí)。
2. 為什么要選擇swift?
很多人現(xiàn)在還沒有學(xué)習(xí) Swift, 覺得它沒有什么優(yōu)點(diǎn),只是一個(gè)語言大雜燴。只是等你真正使用 Swift 編寫一兩個(gè)項(xiàng)目,就回不了頭。Swift 有些簡(jiǎn)便快速的寫法,在 Objective-C 中是沒有辦法做到的。并且 Swift 的一些語言特性避免了很多 Objective-C 的坑。使用 Swift 編寫的任何功能,使用 Objective-C 也可以做到,但是會(huì)麻煩得多。而假如太麻煩的話,明知道是好的,也不會(huì)去做。
很多事情,你還沒有見識(shí)過的時(shí)候,會(huì)覺得不需要。但等你真正接觸過了,就難以忍受再次失去了。比如幾年前項(xiàng)目還沒有采用 ARC。現(xiàn)在看來假如沒有 ARC,代碼寫起來太麻煩了,那時(shí)還沒有更先進(jìn)的寫法,根本不會(huì)有這樣的感覺。Swift 比 Objective-C 先進(jìn)。現(xiàn)在 Swift 還不穩(wěn)定,語言、庫(kù)、相關(guān)工具將會(huì)快速變動(dòng),而這恰好說明它在發(fā)展。
3. 公司項(xiàng)目開發(fā)怎么選擇
很多大公司為求穩(wěn),會(huì)仍然采用 Objective-C。而個(gè)人開發(fā)者和小團(tuán)隊(duì),新項(xiàng)目應(yīng)該直接采用 Swift 編寫,舊項(xiàng)目的新模塊也應(yīng)該使用 Swift 編寫。這樣慢慢將整個(gè)語言重心從 Objective-C 切換到 Swift。Swift 的代碼更簡(jiǎn)潔,開發(fā)效率更高。原有 Objective-C 項(xiàng)目,已經(jīng)使用 Objective-C 編寫的比較穩(wěn)定的庫(kù),不需要也不建議要用 Swift 重新編寫,直接混編,讓它慢慢過渡就行了。大公司傾向于不犯錯(cuò),求穩(wěn)。 個(gè)人開發(fā)者和小團(tuán)隊(duì),求穩(wěn)一定不能跟大公司競(jìng)爭(zhēng)的,更應(yīng)該求好求變。