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來接收判斷
Any和AnyObject的轉(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 遷出自備忘錄