枚舉類型
swift中使用enum關(guān)鍵字聲明枚舉碧聪。并且可以指定枚舉的類型
方式一冒版、
enum Dirction : Int{
case east = 0
case west = 1
case north = 2
case south = 3
}
enum NethodType : String{
case get = "get"
case post = "post"
case put = "put"
case delete = "delete"
}
方式一枚舉類型甚至可以為String類型。
方式二逞姿、
enum type : Int{ //這種方式只支持Int
case enum1 = 0,enum2,enum3,enum4,enum5
}
方式二對(duì)于枚舉數(shù)量較多的情況下可以快速書寫辞嗡,但這種方式類型只支持Int
創(chuàng)建具體的枚舉
第一種:
let type1 : NethodType = .get
第二種:
let type2 = NethodType.post
結(jié)構(gòu)體
結(jié)構(gòu)體定義格式如下:
struct 結(jié)構(gòu)體名稱 {
屬性或方法
}
與oc不同,swift中結(jié)構(gòu)體可以添加方法
定義結(jié)構(gòu)體
struct location {
//屬性
var x : Double
var y : Double
//方法
func test() {
print("結(jié)構(gòu)體中的test方法")
}
}
結(jié)構(gòu)體的構(gòu)造函數(shù)
一般情況下滞造,結(jié)構(gòu)體為我們提供了默認(rèn)的構(gòu)造函數(shù)续室,需要我們?yōu)榻Y(jié)構(gòu)體中每一個(gè)屬性賦值。但我們也可以自定義構(gòu)造函數(shù)谒养。
- 構(gòu)造函數(shù)用init開頭挺狰;
- 構(gòu)造函數(shù)不需要返回值;
- 構(gòu)造函數(shù)必須保證所有成員屬性被初始化
在上面結(jié)構(gòu)體中添加這個(gè)函數(shù)
假設(shè)我們需要傳入一個(gè)string為10买窟,20丰泊,將10賦值給x,將20賦值給y
init(xyStr : String) {
let array = xyStr.components(separatedBy: ",")
let item1 = array[0]
let item2 = array[1]
//?? 先判斷前面可選類型是否有值蔑祟, 有值系統(tǒng)解包趁耗,無值使用后面提供的值
self.x = Double(item1) ?? 0
self.y = Double(item2) ?? 0
}
改變成員屬性
我們可以直接在函數(shù)中修改結(jié)構(gòu)體中成員屬性的值沉唠,但需要在函數(shù)前加上mutation關(guān)鍵字
mutating func moveH(distance : Double) {
self.x += distance
}
結(jié)構(gòu)體的使用
//創(chuàng)建結(jié)構(gòu)體對(duì)應(yīng)值
var center = location(x: 20, y: 30)
//調(diào)用函數(shù)修改成員屬性
center.moveH(distance: 20)
//使用自定義構(gòu)造函數(shù)初始化
location(xyStr: "20,30")
swift中的類
類的定義格式
class 類名 : SuperClass {
//定義屬性和方法
}
和結(jié)構(gòu)體定義類似疆虚,但在swift中,類可以繼承一個(gè)父類或者不繼承满葛,自己為根類径簿。
類的定義
定義屬性和方法
class Person {
//存儲(chǔ)屬性
var name : String = ""
var score1 : Double = 100
var score2 : Double = 88
var score3 : Double = 94
//計(jì)算屬性--> 只讀屬性
var averageScore : Double {
return (self.score1 + self.score2 + self.score3) * 0.5
}
//類屬性:和這個(gè)類相關(guān),并且通過類名進(jìn)行訪問
static var courseCount : Int = 0
//函數(shù)
func getAverageScore() -> Double {
return (self.score1 + self.score2 + self.score3) * 0.5
}
}
與結(jié)構(gòu)體一樣嘀韧,類中的成員變量需要先初始化篇亭。swift中的計(jì)算屬性是只讀屬性,我感覺與oc中屬性的get方法類似锄贷。oc還有類屬性译蒂,直接與類關(guān)聯(lián)曼月,我們可以通過類名對(duì)它進(jìn)行訪問
var stu = Student()
//修改成員變量
stu.name = "zzq"
//獲取只讀屬性
print(stu.averageScore)
//修改類屬性
Student.courseCount = 3
類的屬性監(jiān)聽器
當(dāng)我們類中屬性發(fā)生變化時(shí),我們可以通過屬性監(jiān)聽器來知道屬性即將改變和已經(jīng)改變柔昼,并作出相應(yīng)處理
class Person {
//成員變量需要初始化
var name : String = "" {
//監(jiān)聽屬性即將改變哑芹,還沒改變
willSet {
print(newValue)
print("即將改變")
}
//監(jiān)聽屬性已經(jīng)改變
didSet {
print(oldValue)
print("發(fā)生改變")
}
}
}
在屬性后使用括弧,使用willSet
方法監(jiān)聽即將改變捕透,didSet
方法監(jiān)聽已經(jīng)改變聪姿,默認(rèn)情況下,willSet
提供了newVlue
參數(shù)告訴我們新的值是什么乙嘀,didSet
提供oldValue
參數(shù)告訴我們舊的值是什么末购。
類的構(gòu)造函數(shù)
與結(jié)構(gòu)體一樣,默認(rèn)情況下系統(tǒng)會(huì)提供默認(rèn)的構(gòu)造函數(shù)虎谢,我們也可以自定義構(gòu)造函數(shù)盟榴,當(dāng)我們自定義構(gòu)造函數(shù)后,默認(rèn)的構(gòu)造函數(shù)將無法使用婴噩,如果要使用曹货,我們需要手動(dòng)重寫一下默認(rèn)的構(gòu)造函數(shù)。
//類的構(gòu)造函數(shù)
class Person {
var name : String = ""
var age : Int = 0
//如果自定義構(gòu)造函數(shù)讳推,會(huì)覆蓋系統(tǒng)提供的構(gòu)造函數(shù)覆蓋
init(name : String , age : Int) {
self.name = name;
self.age = age
}
//重寫系統(tǒng)構(gòu)造函數(shù)
init() {
}
}
使用KVC
KVC是oc中的一種特性顶籽,如果需要在swift類中使用KVC必須滿足以下條件
- 繼承NSObject類
- 先調(diào)用super.init()
- 如果字典中某key沒有對(duì)應(yīng)屬性,需要重寫setvalue forundefinekey方法
class Person : NSObject {
var name : String = ""
var age : Int = 0
//使用KVC
forundefinekey
init(dict : [String : Any]) {
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {
}
}
通過KVC可以快速對(duì)類中成員變量進(jìn)行初始化賦值银觅。
析構(gòu)函數(shù)
與oc類似礼饱,swift也是通過引用計(jì)數(shù)來判斷對(duì)象聲明周期的,當(dāng)對(duì)象銷毀時(shí)會(huì)調(diào)用類的析構(gòu)函數(shù)究驴。
class Person {
var name : String = ""
var age : Int = 0
//析構(gòu)函數(shù)
deinit {
print("對(duì)象 銷毀")
}
}
系統(tǒng)會(huì)默認(rèn)生成析構(gòu)函數(shù)镊绪,我們也可以重寫deinit
方法來處理一些事情
循環(huán)引用
與oc差不多,由于生命周期通過引用計(jì)數(shù)管理洒忧,當(dāng)對(duì)象之間相互持有時(shí)會(huì)導(dǎo)致循環(huán)引用蝴韭,出現(xiàn)內(nèi)存無法釋放的問題。
class Person {
var name : String = ""
var book : Book?
deinit {
print("person - deinit")
}
}
class Book {
weak var owner : Person?
deinit {
print("book - deinit")
}
}
var p : Person? = Person()
var b : Book? = Book()
p!.book = b
b!.owner = p
p = nil
b = nil
為了解決這個(gè)問題熙侍,我們可以在成員變量前添加weak關(guān)鍵字榄鉴,這樣就不會(huì)產(chǎn)品循環(huán)引用了。
可選鏈
在上一篇類型中我們已經(jīng)知道蛉抓,為了代碼的嚴(yán)謹(jǐn)和安全庆尘,對(duì)所有可能為nil的對(duì)象都是可選類型。為了使用起來更加方便巷送,swift提供了可選鏈方便我們調(diào)用驶忌。
class Person {
var name : String = ""
var dog : Dog?
}
class Dog {
var weight : Double = 0.0
var toy : Toy?
}
class Toy {
var price : Double = 0
func flying() -> Void {
print("飛")
}
}
let p = Person()
p.name = "zzq"
let d = Dog()
d.weight = 14
let t = Toy()
t.price = 100
p.dog = d
d.toy = t
//?.就是可選鏈,系統(tǒng)自動(dòng)判斷該可選類型是否有值笑跛,如果有值解包付魔,沒有賦值為nil
let price = p.dog?.toy?.price
p.dog?.toy?.flying()
我們可以通過 `?.的格式快速訪問對(duì)象中的可選類型聊品。并交給系統(tǒng)進(jìn)行解包或賦值為nil
協(xié)議
協(xié)議的定義格式
protocol SprortProtocol {
func play1()
func play2()
}
在swift中默認(rèn)情況下,如果遵守了協(xié)議几苍,就必須實(shí)現(xiàn)協(xié)議中所有的方法杨刨。
class Teacher : SprortProtocol {
func play1() {
print("play1")
}
func play2() {
print("play2")
}
}
如果我們希望協(xié)議中的方法是選擇實(shí)現(xiàn)的,我們需要使用到oc中的optional關(guān)鍵字擦剑,并且在協(xié)議和方法前添加@objc關(guān)鍵字
@objc protocol SprortProtocol {
@objc optional func play1()
func play2()
}
這樣play1
方法就不是必須要實(shí)現(xiàn)的了
給協(xié)議指定可遵守的類型
在swift中妖胀,類,結(jié)構(gòu)體甚至是枚舉都可以遵守協(xié)議惠勒。這就讓我們的代碼變得不那么嚴(yán)謹(jǐn)赚抡,我們可以在協(xié)議名后指定可遵守該協(xié)議的類型來讓我們代碼看起來更嚴(yán)謹(jǐn)。
protocol SprortProtocol: class {
func buy()
}
這樣纠屋,就只有class可以遵守該協(xié)議了涂臣。這樣寫往往是用于我們的代理設(shè)計(jì)模式。
代理模式
protocol buyDelegate : class {
func buy()
}
class Person {
//定義代理屬性
weak var delegate : buyDelegate?
func going() {
self.delegate?.buy()
}
}
為了防止循環(huán)引用售担,代理對(duì)象前最好添加weak關(guān)鍵字赁遗。