枚舉類型
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
}
方式二對于枚舉數(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)體為我們提供了默認的構(gòu)造函數(shù),需要我們?yōu)榻Y(jié)構(gòu)體中每一個屬性賦值。但我們也可以自定義構(gòu)造函數(shù)。
- 構(gòu)造函數(shù)用init開頭;
- 構(gòu)造函數(shù)不需要返回值;
- 構(gòu)造函數(shù)必須保證所有成員屬性被初始化
在上面結(jié)構(gòu)體中添加這個函數(shù)
假設(shè)我們需要傳入一個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)體對應(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中,類可以繼承一個父類或者不繼承,自己為根類。
類的定義
定義屬性和方法
class Person {
//存儲屬性
var name : String = ""
var score1 : Double = 100
var score2 : Double = 88
var score3 : Double = 94
//計算屬性--> 只讀屬性
var averageScore : Double {
return (self.score1 + self.score2 + self.score3) * 0.5
}
//類屬性:和這個類相關(guān),并且通過類名進行訪問
static var courseCount : Int = 0
//函數(shù)
func getAverageScore() -> Double {
return (self.score1 + self.score2 + self.score3) * 0.5
}
}
與結(jié)構(gòu)體一樣,類中的成員變量需要先初始化。swift中的計算屬性是只讀屬性,我感覺與oc中屬性的get方法類似。oc還有類屬性,直接與類關(guān)聯(lián),我們可以通過類名對它進行訪問
var stu = Student()
//修改成員變量
stu.name = "zzq"
//獲取只讀屬性
print(stu.averageScore)
//修改類屬性
Student.courseCount = 3
類的屬性監(jiān)聽器
當我們類中屬性發(fā)生變化時,我們可以通過屬性監(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)改變,默認情況下,willSet提供了newVlue參數(shù)告訴我們新的值是什么,didSet提供oldValue參數(shù)告訴我們舊的值是什么。
類的構(gòu)造函數(shù)
與結(jié)構(gòu)體一樣,默認情況下系統(tǒng)會提供默認的構(gòu)造函數(shù),我們也可以自定義構(gòu)造函數(shù),當我們自定義構(gòu)造函數(shù)后,默認的構(gòu)造函數(shù)將無法使用,如果要使用,我們需要手動重寫一下默認的構(gòu)造函數(shù)。
//類的構(gòu)造函數(shù)
class Person {
var name : String = ""
var age : Int = 0
//如果自定義構(gòu)造函數(shù),會覆蓋系統(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沒有對應(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可以快速對類中成員變量進行初始化賦值。
析構(gòu)函數(shù)
與oc類似,swift也是通過引用計數(shù)來判斷對象聲明周期的,當對象銷毀時會調(diào)用類的析構(gòu)函數(shù)。
class Person {
var name : String = ""
var age : Int = 0
//析構(gòu)函數(shù)
deinit {
print("對象 銷毀")
}
}
系統(tǒng)會默認生成析構(gòu)函數(shù),我們也可以重寫deinit方法來處理一些事情
循環(huán)引用
與oc差不多,由于生命周期通過引用計數(shù)管理,當對象之間相互持有時會導致循環(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
為了解決這個問題,我們可以在成員變量前添加weak關(guān)鍵字,這樣就不會產(chǎn)品循環(huán)引用了。
可選鏈
在上一篇類型中我們已經(jīng)知道,為了代碼的嚴謹和安全,對所有可能為nil的對象都是可選類型。為了使用起來更加方便,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)自動判斷該可選類型是否有值,如果有值解包,沒有賦值為nil
let price = p.dog?.toy?.price
p.dog?.toy?.flying()
我們可以通過 `?.的格式快速訪問對象中的可選類型。并交給系統(tǒng)進行解包或賦值為nil
協(xié)議
協(xié)議的定義格式
protocol SprortProtocol {
func play1()
func play2()
}
在swift中默認情況下,如果遵守了協(xié)議,就必須實現(xiàn)協(xié)議中所有的方法。
class Teacher : SprortProtocol {
func play1() {
print("play1")
}
func play2() {
print("play2")
}
}
如果我們希望協(xié)議中的方法是選擇實現(xiàn)的,我們需要使用到oc中的optional關(guān)鍵字,并且在協(xié)議和方法前添加@objc關(guān)鍵字
@objc protocol SprortProtocol {
@objc optional func play1()
func play2()
}
這樣play1方法就不是必須要實現(xiàn)的了
給協(xié)議指定可遵守的類型
在swift中,類,結(jié)構(gòu)體甚至是枚舉都可以遵守協(xié)議。這就讓我們的代碼變得不那么嚴謹,我們可以在協(xié)議名后指定可遵守該協(xié)議的類型來讓我們代碼看起來更嚴謹。
protocol SprortProtocol: class {
func buy()
}
這樣,就只有class可以遵守該協(xié)議了。這樣寫往往是用于我們的代理設(shè)計模式。
代理模式
protocol buyDelegate : class {
func buy()
}
class Person {
//定義代理屬性
weak var delegate : buyDelegate?
func going() {
self.delegate?.buy()
}
}
為了防止循環(huán)引用,代理對象前最好添加weak關(guān)鍵字。