Swift和OC的區(qū)別(基于Swift3.0)

swift無疑是IOS程序員的未來,但是目前蘋果公司還在不端更新和改變swift,甚至在語法層面還在不斷探索,雖然xcode提供一些直接適配新版本swift語法的快捷鍵,但給我們學(xué)習(xí)不免造成一些影響,這里是基于swift3.0和oc的一些基礎(chǔ)性知識(shí)的比較。

####一。基礎(chǔ)部分

1.Swift的類型是在C和Objective-C的基礎(chǔ)上提出的,Int是整型;Double和Float是浮點(diǎn)型;Bool是布爾型;String是字符串。Swift還有兩個(gè)有用的集合類型,Array和Dictionary,(類型第一個(gè)字母大寫)

2.Swift還增加了Objective-C中沒有的類型比如元組(Tuple)。元組可以讓你創(chuàng)建或者傳遞一組數(shù)據(jù),比如作為函數(shù)的返回值時(shí),你可以用一個(gè)元組可以返回多個(gè)值。

元組(tuples)把多個(gè)值組合成一個(gè)復(fù)合值。元組內(nèi)的值可以使任意類型,并不要求是相同類型。

let?http404Error?=(404,"Not?Found")

(404,"Not Found")元組把一個(gè)Int值和一個(gè)String值組合起來表示HTTP狀態(tài)碼的兩個(gè)部分:一個(gè)數(shù)字和一個(gè)人類可讀的描述。這個(gè)元組可以被描述為“一個(gè)類型為(Int,String)的元組”。

你可以把任意順序的類型組合成一個(gè)元組,這個(gè)元組可以包含所有類型。只要你想,你可以創(chuàng)建一個(gè)類型為(Int,Int,Int)或者(String,Bool)或者其他任何你想要的組合的元組。

你還可以通過下標(biāo)來訪問元組中的單個(gè)元素,下標(biāo)從零開始:

println("The?status?code?is?\(http404Error.0)")

你可以在定義元組的時(shí)候給單個(gè)元素命名:

let?http200Status?=(statusCode:?200,description:?"OK")

給元組中的元素命名后,你可以通過名字來獲取這些元素的值:

println("The?status?code?is?\(http200Status.statusCode)")

注意:元組在臨時(shí)組織值的時(shí)候很有用,但是并不適合創(chuàng)建復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。如果你的數(shù)據(jù)結(jié)構(gòu)并不是臨時(shí)使用,請(qǐng)使用類或者結(jié)構(gòu)體而不是元組。

3.Swift還增加了可選(Optional)類型,用于處理值缺失的情況??蛇x表示“那兒有一個(gè)值,并且它等于x”或者“那兒沒有值”。可選有點(diǎn)像在Objective-C中使用nil,但是它可以用在任何類型上,不僅僅是類??蛇x類型比Objective-C中的nil指針更加安全也更具表現(xiàn)力,它是Swift許多強(qiáng)大特性的重要組成部分。

Swift定義的常量和變量是沒有默認(rèn)值的,所以引入了可選的概念,用?修飾變量,標(biāo)示該變量的值可能為空也可能為某個(gè)值,然后獲取的時(shí)候用!強(qiáng)制解析,此時(shí)必須有值,否則報(bào)運(yùn)行時(shí)錯(cuò)誤。

比如你定義一個(gè)String類型的變量

var str:String?

str="ass"

print("str=\(str!)")

如果不使用!強(qiáng)制解析,可以使用可選綁定(optional binding)來判斷可選是否包含值,如果包含就把值賦給一個(gè)臨時(shí)常量或者變量。

if let realstr = str

{

print("realstr=\(realstr)")

}else

{

print("str為空")

}

有的函數(shù)的返回值就是可選類型,默認(rèn)是使用?修飾的,也需要!強(qiáng)制解析或者可選綁定解析。

let?convertedNumber?=?possibleNumber.toInt()

//?convertedNumber被推測為類型"Int?",或者類型"optional?Int"

ifconvertedNumber?{

println("\(convertedNumber!)")

}else{

println("could?not?be?converted")

}

隱式解析可選

有時(shí)候在程序架構(gòu)中,第一次被賦值之后,可以確定一個(gè)可選總會(huì)有值。在這種情況下,每次都要判斷和解析可選值是非常低效的,因?yàn)榭梢源_定它總會(huì)有值。

這種類型的可選被定義為隱式解析可選(implicitly unwrapped optionals)。把想要用作可選的類型的后面的問號(hào)(String?)改成感嘆號(hào)(String!)來聲明一個(gè)隱式解析可選。

let?possibleString:?String?=?"An?optional?string."

println(possibleString!)//需要驚嘆號(hào)來獲取值

//輸出"An?optional?string."

let?assumedString:?String!?=?"An?implicitly?unwrapped?optional?string."

println(assumedString)//不需要感嘆號(hào)

//輸出"An?implicitly?unwrapped?optional?string."

自判斷鏈接

自判斷鏈接(Optional Chaining)是一種可以請(qǐng)求和調(diào)用屬性、方法及子腳本的過程,它的自判斷性體現(xiàn)于請(qǐng)求或調(diào)用的目標(biāo)當(dāng)前可能為空(nil)。如果自判斷的目標(biāo)有值,那么調(diào)用就會(huì)成功;相反,如果選擇的目標(biāo)為空(nil),則這種調(diào)用將返回空(nil)。多次請(qǐng)求或調(diào)用可以被鏈接在一起形成一個(gè)鏈,如果任何一個(gè)節(jié)點(diǎn)為空(nil)將導(dǎo)致整個(gè)鏈?zhǔn)А?/p>

如果用!解析一個(gè)可選類型為空時(shí)會(huì)報(bào)運(yùn)行時(shí)異常

如果改用?解析就可以避免

print(stu.room!.person.name)

room==nil所以報(bào)運(yùn)行時(shí)錯(cuò)誤

print(stu.room?.person.name)

就打印nil

更正規(guī)的寫法可以使用if let

如果numberOfRooms為Int類型,john.residence?.numberOfRooms就是Int?類型

iflet?roomCount?=?john.residence?.numberOfRooms

{

}else

{

}

如果printNumberOfRooms()返回值為Void類型,john.residence?.printNumberOfRooms()就是Void?類型

ifjohn.residence?.printNumberOfRooms()

{

}else

{

}

4.常量的值一旦設(shè)定就不能改變,而變量的值可以隨意更改。常量和變量必須在使用前聲明,用let來聲明常量,用var來聲明變量。所謂改變,對(duì)于基本數(shù)據(jù)類型而言,值改變就是改變,而對(duì)于引用數(shù)據(jù)類型而言,指針指向改變才是改變。

Swift中整數(shù)(Integer)、浮點(diǎn)數(shù)(floating-point)、布爾值(Booleans)、字符串(string)、數(shù)組(array)和字典(dictionaries),都是值類型,并且都是以結(jié)構(gòu)體的形式在后臺(tái)所實(shí)現(xiàn)。

eg: var arr=[“a”,”b”,”c”]

var arrcopy =arr

//此時(shí)arr-“a,b,c”arrcopy-“abc”

arrcopy[0]=“fuck”

//此時(shí)arr-“a,b,c”arrcopy-“fuck,b,c”

class Person

{

varname:String=“a”

}

var arr=[person1,person2,person3]

var arrcopy =arr

//此時(shí)arr,arrcopy指向一塊區(qū)域,一同改變

5.類型別名(type aliases)就是給現(xiàn)有類型定義另一個(gè)名字。你可以使用typealias關(guān)鍵字來定義類型別名。

當(dāng)你想要給現(xiàn)有類型起一個(gè)更有意義的名字時(shí),類型別名非常有用。假設(shè)你正在處理特定長度的外部資源的數(shù)據(jù):

typealias?AudioSample?=?UInt16

定義了一個(gè)類型別名之后,你可以在任何使用原始名的地方使用別名:

varmaxAmplitudeFound?=?AudioSample.min

6.控制流

兩種形式的for循環(huán)

//傳統(tǒng)獲取index的語法

for i in 0…10

{

}

//快速訪問對(duì)象的語法

for obj in arr

{

}

二.函數(shù)

普通函數(shù)定義和使用

func add(param1:String,param2:String)->String

{

return param1+param2

}

print(add(param1: "w",param2: "q"))

可以給參數(shù)添加默認(rèn)值,使用時(shí)也可以不傳此參數(shù)

func add2(param1:String,param2:String="q")->String

{

return param1+param2

}

print(add2(param1: "w"))

inout修飾函數(shù)參數(shù)

變量形參只能在函數(shù)本身內(nèi)改變。如果你想讓函數(shù)改變形參值,并想要在函數(shù)調(diào)用結(jié)束后保持形參值的改變,那你可以把形參定義為in-out形參。

func change(param:inout String)

{

param="wowo"

}

var kaka:String="kaka"

change(param: &kaka)

print(kaka)//此時(shí)kaka=“wowo”

復(fù)雜函數(shù)定義和使用

函數(shù)可以作為形參和另一個(gè)函數(shù)的返回值

三.類

class Person: NSObject {

//普通屬性方法定義

var name:String?

func sayHi(mes:String)->String{

return "person\(mes)"

}

//靜態(tài)屬性方法定義(屬性用static修飾,方法用static或class修飾)

static var age:String?

class func sayMessage()

{

print("i am person\(age!)")

}

}

屬性

lazy修飾的屬性必須初始化它會(huì)在使用該屬性的時(shí)候才去執(zhí)行初始化的代碼一般用在消耗不少時(shí)間的變量上比如文件打開

lazy特性;局部范圍的常量或變量不會(huì)延遲計(jì)算。

set get方法

//既有set又有g(shù)et方法

var firstName:String

{

get

{

return "first"+self.name!

}

//newValue代表set參數(shù)值

set

{

self.name="setName:"+newValue

}

}

//只有g(shù)et方法

var lastName:String

{

return "last"+self.name!

}

屬性監(jiān)視器

willSet didSet方法

willSet在設(shè)置新的值之前調(diào)用

didSet在新的值被設(shè)置之后立即調(diào)用

//需要設(shè)置默認(rèn)值

var idcard:Double = 0.0

{

willSet

{

print("willSet")

}

didSet

{

print("didSet")

}

}

繼承

如果子類實(shí)現(xiàn)和父類相同的方法或者屬性就是重寫。必須用overriding關(guān)鍵字表明。

重寫overriding方法

class Student: Person {

override func sayHello(mes: String)-> String {

//可以使用super關(guān)鍵字調(diào)用父類方法

return super.sayHello(mes:mes)

}

}

重寫overriding屬性

override var name: String?

{

set

{

}

get

{

return super.name

}

}

原則:你可以將一個(gè)繼承來的只讀屬性重寫為一個(gè)讀寫屬性,只需要你在重寫版本的屬性里提供getter和setter即可。但是,你不可以將一個(gè)繼承來的讀寫屬性重寫為一個(gè)只讀屬性。

防止重寫

你可以通過把方法,屬性或附屬腳本標(biāo)記為final來防止它們被重寫

構(gòu)造方法

與Objective-C中的構(gòu)造器不同,Swift的構(gòu)造器無需返回值,它們的主要任務(wù)是保證新實(shí)例在第一次使用前完成正確的初始化。

構(gòu)造器分位指定構(gòu)造器和便利構(gòu)造器

原則:指定構(gòu)造器是向上調(diào)用的,便利構(gòu)造器是橫向調(diào)用的.

規(guī)則1:指定構(gòu)造器必須調(diào)用其父類的指定構(gòu)造器

規(guī)則2:便利構(gòu)造器必須調(diào)用同一類中調(diào)用的其他構(gòu)造器

規(guī)則3:便利構(gòu)造器必須以調(diào)用一個(gè)指定構(gòu)造器結(jié)束

//指定構(gòu)造器(默認(rèn)構(gòu)造方法),因?yàn)楦割愐灿性摲椒ǎ杂胦verride

override init()

{

super.init()

print("Student init")

}

//指定構(gòu)造器(自定義構(gòu)造方法,父類沒有該方法,不需要override)

init(size:Double)

{

super.init(size: size)

print("Student init with size")

}

//便利構(gòu)造器(使用關(guān)鍵詞convenience,需要調(diào)用自己的構(gòu)造方法)

convenience init(size:Double,friendNums:Double){

self.init(size:size)

self.friendNums=friendNums

}

類擴(kuò)展

相當(dāng)于OC分類

Swift中的擴(kuò)展可以:

1.添加計(jì)算型屬性和計(jì)算靜態(tài)屬性

注意:擴(kuò)展可以添加新的計(jì)算屬性,但是不可以添加存儲(chǔ)屬性,也不可以向已有屬性添加屬性觀測器(property observers)

2.定義實(shí)例方法和類型方法

3.提供新的構(gòu)造器

4.定義下標(biāo)

5.定義和使用新的嵌套類型

6.使一個(gè)已有類型符合某個(gè)接口

extension Room

{

var newSize:Double

{

return self.size+100

}

func sayExtensionRoom(){

print("sayExtensionRoom\(self.newSize)")

}

}

協(xié)議

四.自動(dòng)引用計(jì)數(shù)

總體基本和oc一致,在解決循環(huán)引用的問題有點(diǎn)區(qū)別。

可以使用弱引用weak和無主引用unowned修飾一方變量。

1.兩個(gè)屬性的值都可能是nil,并有可能產(chǎn)生強(qiáng)引用環(huán)。這種場景下適合使用弱引用。

var a:A?

weak b:B?

2.一個(gè)屬性可以是nil,另外一個(gè)屬性不允許是nil,并有可能產(chǎn)生強(qiáng)引用環(huán)。這種場景下適合使用無主引用。

var a:A?

unowned b:B

override init(){

self.b=B()

}

3.兩個(gè)屬性都必須有值,且初始化完成后不能為nil。這種場景下,則要一個(gè)類用無主引用屬性,另一個(gè)類用隱式展開的可選屬性。

var a:A!

override init(){

self.a=A()

}

unowned b:B

override init(){

self.b=B()

}

五.類型轉(zhuǎn)換

檢查類型

用類型檢查操作符(is)來檢查一個(gè)實(shí)例是否屬于特定子類型。類型檢查操作符返回true若實(shí)例屬于那個(gè)子類型,若不屬于返回false。

library中添加Movie和Song

foriteminlibrary?{

ifitem?is?Movie?{

++movieCount

}elseifitem?is?Song?{

++songCount

}

}

向下轉(zhuǎn)型(簡稱下轉(zhuǎn))

某類型的一個(gè)常量或變量可能在幕后實(shí)際上屬于一個(gè)子類。你可以相信,上面就是這種情況。你可以嘗試向下轉(zhuǎn)到它的子類型,用類型轉(zhuǎn)換操作符(as)

如果強(qiáng)制轉(zhuǎn)型肯定成功,可以使用as!,如果使用as?,那么返回結(jié)果成功則為該轉(zhuǎn)的類型,失敗則為空,此時(shí)可以使用if let來接收判斷

AnyAnyObject的轉(zhuǎn)換

Swift為不確定類型提供了兩種特殊類型別名:

1. AnyObject可以代表任何class類型的實(shí)例。

2. Any可以表示任何類型(基礎(chǔ)類型和class類型),除了方法類型(function types)。

六.閉包

Swift中的閉包與C和Objective-C中的blocks有點(diǎn)類似。

閉包表達(dá)式語法

{(parameters)->?returnTypein

statements

}

捕獲

閉包可以在其定義的上下文中捕獲常量或變量。即使定義這些常量和變量的原作用域已經(jīng)不存在,閉包仍然可以在閉包函數(shù)體內(nèi)引用和修改這些值。

//makeIncrementor函數(shù)返回值是一個(gè)()->Int類型的函數(shù)

func makeIncrementor(amount: Int)->()-> Int {

var runningTotal = 0

func incrementor()-> Int {

runningTotal += amount

return runningTotal

}

return incrementor

}

//閉包捕獲amount參數(shù)的值,然后每次都可以使用

let incrementByTen = makeIncrementor(amount: 10)

print(incrementByTen())//10

print(incrementByTen())//20

print(incrementByTen())//30

七.應(yīng)用

swift讀取文件為String類型

let path:String = Bundle.main.path(forResource: "demo2.js",ofType:nil)!

if let spath = try?String.init(contentsOf: URL.init(fileURLWithPath: path),encoding:String.Encoding.utf8)

{

}else

{

}

2017-2-8 遷出自備忘錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容