Swift和Objective-C的十個(gè)不同點(diǎn)

2014年6月2號(hào)烫罩,蘋(píng)果發(fā)布了一個(gè)新的面向?qū)ο蟮恼Z(yǔ)言:Swift赏迟,做為Objective-C的替代者洪己。作為一門(mén)新的語(yǔ)言妥凳,Swift在簡(jiǎn)單易用上面獲得了大量的好評(píng),從而它的上升速度是非炒鸩叮快的逝钥。


2018年4月TIOBE排名

從圖中可以看到,Swift的排名已經(jīng)超越了Objective-C噪珊。雖然在中國(guó)可能還大部分在使用Objective-C開(kāi)發(fā)晌缘,但是逐漸轉(zhuǎn)換為Swift是一個(gè)不可逆的趨勢(shì)。

接下去我們將從以下10個(gè)方面展示Swift和Objective-C的不同痢站。

  • 可選(Optionals)
  • 控制流
  • 類(lèi)型推斷
  • 元組
  • 字符串操作
  • Guard&Defer
  • 函數(shù)式編程
  • 枚舉
  • 函數(shù)
  • Do關(guān)鍵字

可選

可選的概念在C或者Objective-C中是不存在的磷箕。它意味著這個(gè)返回值可能有或可能為nil。我們知道阵难,在Objective-C中岳枷,一個(gè)方法可能返回一個(gè)對(duì)象或可能返回nil。但是對(duì)于基本類(lèi)型int呜叫、float等空繁,則是沒(méi)有可選的返回的。但是對(duì)于Swift而言朱庆,則是

let a = "48"
let b = Int(a)
print(b!)

//output
Optional(48)

Int函數(shù)這邊返回一個(gè)可選類(lèi)型盛泡,里面包含一個(gè)48的值。但是如果原先的字符串不是數(shù)字呢娱颊?

let aa = "error"
let bb = Int(aa)
print(bb)

//output
nil

從這邊我們可以看到傲诵,它返回了一個(gè)nil。因?yàn)镮nt函數(shù)無(wú)法將非數(shù)字的字符串轉(zhuǎn)換為Int箱硕。
我們知道對(duì)于Objective-C拴竹,如果你對(duì)nil發(fā)送消息,那將什么都不會(huì)發(fā)生剧罩。但是對(duì)于Swift栓拜,編譯器則會(huì)直接報(bào)錯(cuò)。

var x = Int("188")
print(x+1)

//output
error

如果要使用的話(huà),就必須強(qiáng)制解包幕与,可以用以下兩種方式:

var x = Int("188")
print(x!+1)  //1.強(qiáng)制解包
if var y = x {  //2.optional綁定
  y += 811
  print(y)
}

控制流

對(duì)于C語(yǔ)言或者Objective-C挑势,你可能對(duì)({})非常熟悉。if語(yǔ)句或者for語(yǔ)句都會(huì)用到纽门⊙Τ埽或者可以簡(jiǎn)寫(xiě)去掉({})营罢。但是對(duì)于Swift赏陵,你必須使用{},但是()可以去掉饲漾。

let xx = 4
if xx < 5 {
  print(xx)
}

類(lèi)型推斷

Swift引入了類(lèi)型安全機(jī)制蝙搔。一旦一個(gè)變量被申明為一個(gè)類(lèi)型,那么就不能再改變了考传。同時(shí)編譯器能夠根據(jù)賦的值推斷出相應(yīng)的類(lèi)型吃型。

var str = "Some string"
// OR
var str2:String
str2 = "Other string"

而對(duì)于Objective-C,你必須顯式的申明一個(gè)變量:

NSString str = @"There is no type inference in Objective-C :("

元組

Swift支持元組類(lèi)型僚楞,它存儲(chǔ)一組值勤晚。跟數(shù)組不同,元組中的類(lèi)型不必相同的泉褐。比如:

var t:(String, Int) = ("John", 33)
print(t.0, t.1)

var j:(name:String, Int) = ("Morgan", 52)
print(j.name, j.1)

元組使用最多的是在函數(shù)的返回中:

var arr = [23, 5, 7, 33, 9]

func findPosition(el:Int, arr:[Int]) -> (found:Bool, position:Int)? {
  if arr.isEmpty {
    return nil
  }

  for (i, value) in arr.enumerated() {
    if value == el {
      return (true, i)
    }
  }

return (false, -1)
}

if let (isFound, elPosition) = findPosition(el: 5, arr: arr) {
  print(isFound, elPosition)
  // true 1
}

在Objective-C中赐写,可以用BLOCK來(lái)實(shí)現(xiàn)相似的效果,但是跟元組相比膜赃,顯然麻煩多了挺邀。

字符串操作

Swift在字符串操作上面相比Objective-C有巨大的提高。你不必為可變和非可變字符串困擾跳座,對(duì)于不可變的端铛,就使用let,對(duì)于可變的是疲眷,就使用var.
在Swift中禾蚕,字符串聚合是非常方便的:

// Swift:
var str = "My string"
str += " and another string”

而在Objective-C中,則是非常麻煩的狂丝。

// Obj-C:
NSString *myString = @"My string";
myString = [NSString stringWithFormat:@"%@ and another string", myString];

同時(shí)在Objective-C你需要使用占位符來(lái)表示不同類(lèi)型的數(shù)據(jù)换淆。但是在swift則完全不需要,直接用()包含就行美侦。

var str = "String: \(myString) | Signed 32-bit integer: \(myInt) | 64-bit floating-point number: \(myFloat)"

Guard&Defer

在Objective-C中产舞,當(dāng)你邏輯復(fù)雜,需要層層判斷時(shí)菠剩,往往會(huì)出現(xiàn)以下代碼:

enum TriangleAreaCalcError: Error {
    case AngleNotSpecified
    case InvalidAngle
    case SideANotSpecified
    case SideBNotSpecified
}

func calcTriangleArea(a: Double? , b : Double? , alpha : Double? ) throws -> Double {
    if let a = a {
        if let b = b {
            if let alpha = alpha {
                if alpha < 180 && alpha >= 0 {
                    if alpha == 180 {
                        return 0
                    }
                    return 0.5 * a * b * sin(alpha * Double.pi / 180.0)
                } else {
                    throw TriangleAreaCalcError.InvalidAngle
                }
            } else {
                throw TriangleAreaCalcError.AngleNotSpecified
            }
        } else {
            throw TriangleAreaCalcError.SideBNotSpecified
        }
    } else {
        throw TriangleAreaCalcError.SideANotSpecified
    }
}

這看上去就像一個(gè)金字塔冕碟,可讀性非常差。而在Swift中啦桌,你可以使用guard關(guān)鍵字。它表示如果條件不滿(mǎn)足哈蝇,則進(jìn)入邏輯。

func calcTriangleArea(a: Double? , b : Double? , alpha : Double? ) throws -> Double {

    guard
    let a = a
    else {
        throw TriangleAreaCalcError.SideANotSpecified
    }

    guard
    let b = b
    else {
        throw TriangleAreaCalcError.SideBNotSpecified
    }

    guard
    let alpha = alpha
    else {
        throw TriangleAreaCalcError.AngleNotSpecified
    }

    if alpha == 180 {
        return Double(0)
    }

    guard alpha < 180 && alpha >= 0
    else {
        throw TriangleAreaCalcError.InvalidAngle
    }

    return 0.5 * a * b * sin(alpha * Double.pi / 180.0)
}

Swift同時(shí)提供了defer關(guān)鍵字攘已,用于在退出當(dāng)前范圍之前執(zhí)行的操作邏輯炮赦。

func someImageFunc() -> UIImage? {

    let dataSize: Int = 64
    let destData = UnsafeMutablePointer<UInt8>.allocate(capacity: dataSize)

    // ...

    guard error1
    else {
      destData.dealloc(dataSize) // #1
      return nil
    }

    guard error2
    else {
      destData.dealloc(dataSize) // #2
      return nil
    }

    guard error3
    else {
      destData.dealloc(dataSize) // #3
      return nil
    }

    destData.dealloc(dataSize) // #4
    // ...
  }

從中我們可以看到,執(zhí)行了4次dealloc函數(shù)來(lái)保證在退出函數(shù)之前指針被釋放样勃。但是有了defer之后吠勘,我們只要寫(xiě)一次就可以了

func someImageFunc() -> UIImage? {

    let dataSize: Int = 64
        let destData = UnsafeMutablePointer<UInt8>.allocate(capacity: dataSize)

    // ...

    defer {
        destData.dealloc(dataSize)
    }

    guard error
    else {
        return nil
    }

    guard error2
    else {
        return nil
    }

    guard error3
    else {
        return nil
    }

    // ...
}

函數(shù)式編程

Swift引入了大量函數(shù)式編程特征,比如map和filter峡眶,它可以在任何實(shí)現(xiàn)了CollectionType協(xié)議的集合上使用剧防。

let a = [4, 8, 16]
print(a.map{$0 / 2})
// [2, 4, 8]

let b:[(name:String, area:String)] = [("John", "iOS"), ("Sam", "Android"), ("Paul", "Web")]

let c = b.map({"Developer \($0.name) (\($0.area))"})
// ["Developer John (iOS)", "Developer Sam (Android)", "Developer Paul (Web)”]

let d = [23, 5, 7, 12, 10]
let e = d.filter{$0 > 10}
print(e) // [23, 12]

let sum = (20...30)
  .filter { $0 % 2 != 0 }
  .map { $0 * 2 }
  .reduce(0) { $0 + $1 }

print(sum) // 250

而Objective-C原生是不支持這些函數(shù)式編程特征的,除非使用第三方庫(kù)辫樱。

枚舉

在Swift中峭拘,枚舉是非常強(qiáng)大的。它可以包含方法狮暑,可以傳參等鸡挠。以下列舉了一些用法:

enum Location {
  case Address(city: String, street: String)
  case Coordinates(lat: Float, lon: Float)

  func printOut() {
    switch self {
    case let.Address(city, street):
        print("Address: " + street + ", " + city)
    case let.Coordinates(lat, lon):
        print("Coordiantes: (\(lat), \(lon))")
    }
  }
}

let loc1 = Location.Address(city: "Boston", street: "33 Court St")
let loc2 = Location.Coordinates(lat: 42.3586, lon: -71.0590)

loc1.printOut() // Address: 33 Court St, Boston
loc2.printOut() // Coordiantes: (42.3586, -71.059)

枚舉同時(shí)可以遞歸,通過(guò)indirect關(guān)鍵字來(lái)實(shí)現(xiàn)

enum List {
    case Empty
    indirect
    case Cell(value: Int, next: List)
}

let list0 = List.Cell(value: 1, next: List.Empty)
let list1 = List.Cell(value: 4, next: list0)
let list2 = List.Cell(value: 2, next: list1)
let list3 = List.Cell(value: 6, next: list2)
let headL = List.Cell(value: 3, next: list3)

func evaluateList(list: List) - > Int {
    switch list {
        case let.Cell(value, next):
            return value + evaluateList(next)
        case .Empty:
            return 0
    }
}

print(evaluateList(headL)) // 16

函數(shù)

Swift的函數(shù)語(yǔ)法是非常隨意的搬男,既可以像C語(yǔ)言風(fēng)格的拣展,也可以像Objective-C語(yǔ)言風(fēng)格的。在Swift中止后,每個(gè)函數(shù)都有一個(gè)類(lèi)型瞎惫,它由函數(shù)的參數(shù)和返回值組成。這表示你能夠指定函數(shù)的變量或者把函數(shù)作為參數(shù)傳給另一個(gè)函數(shù)译株。

func stringCharactersCount(s: String) -> Int {
  return s.characters.count
}

func stringToInt(s: String) -> Int {
  if let x = Int(s) {
    return x
  }
  return 0
}

func executeSuccessor(f: (String) -> Int, s: String) -> Int {
  return f(s)+1
}

let f1 = stringCharactersCount
let f2 = stringToInt

executeSuccessor(f: f1, s: "5555") // 5
executeSuccessor(f: f2, s: "5555") // 5556

Swift同時(shí)允許你定義一個(gè)函數(shù)參數(shù)的默認(rèn)值瓜喇。

func myFunction(someInt: Int = 5) {
    // If no arguments are passed, the value of someInt is 5
}
myFunction(6) // someInt is 6
myFunction() // someInt is 5

Do關(guān)鍵字

do關(guān)鍵字允許你進(jìn)入一個(gè)新的范圍。

let a = "Yes"

do {
  let a = "No"
  print(a) // No
}

print(a) // Yes

do關(guān)鍵字同時(shí)允許包含一個(gè)或者多個(gè)catch分句歉糜。

do {
   try expression
   statements
} catch pattern 1 {
   statements
} catch pattern 2 where condition {
   statements
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乘寒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子匪补,更是在濱河造成了極大的恐慌伞辛,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夯缺,死亡現(xiàn)場(chǎng)離奇詭異蚤氏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)踊兜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)竿滨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事于游』俅校” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵贰剥,是天一觀的道長(zhǎng)倾剿。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蚌成,這世上最難降的妖魔是什么前痘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮笑陈,結(jié)果婚禮上际度,老公的妹妹穿的比我還像新娘葵袭。我一直安慰自己涵妥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布坡锡。 她就那樣靜靜地躺著蓬网,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鹉勒。 梳的紋絲不亂的頭發(fā)上帆锋,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音禽额,去河邊找鬼锯厢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛脯倒,可吹牛的內(nèi)容都是我干的实辑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼藻丢,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼剪撬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起悠反,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤残黑,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后斋否,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體梨水,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年茵臭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疫诽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖踊沸,靈堂內(nèi)的尸體忽然破棺而出歇终,到底是詐尸還是另有隱情,我是刑警寧澤逼龟,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布评凝,位于F島的核電站,受9級(jí)特大地震影響腺律,放射性物質(zhì)發(fā)生泄漏奕短。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一匀钧、第九天 我趴在偏房一處隱蔽的房頂上張望翎碑。 院中可真熱鬧,春花似錦之斯、人聲如沸日杈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)莉擒。三九已至,卻和暖如春瘫絮,著一層夾襖步出監(jiān)牢的瞬間涨冀,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工麦萤, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹿鳖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓壮莹,卻偏偏與公主長(zhǎng)得像翅帜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子垛孔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容