1. 程式人生 > 其它 >Swift學習-Enumerate、Structure

Swift學習-Enumerate、Structure

1.列舉

1.1列舉定義

//列舉型別可以省略
enum enumName : type?{
    case value1
    case value2
}

定義一個星期列舉

enum DaysOfAWeek{
    case Monday
    case Tuesday
    case Wednesday
}
也可以寫為
enum DaysOfAWeek{
    case Monday, Tuesday,Wednesday
}

//列舉值按以下方式指定給變數
var today = DaysOfAWeek.Monday
today = .Tuesday

//與Switch聯合使用
switch today {
case .Monday:
    print("Today is Monday")
case .Tuesday:
    print("Today is Tuesday")
case .Wednesday:
    print("Today is Wednesday")
default:
    print("Today is neither Monday nor Tuesday")

}

定義列舉初始值

enum DaysOfAWeek{
    case Sunday
    case Monday
    case Tuesday
    case Wednesday
    init() {
        self = .Sunday
    }
}
var today = DaysOfAWeek()
//此時預設為:Sunday

關聯值,列舉允許每個case有一個或更多型別引數

enum ValuesOfDifferentType{
    case Str(String)
    case Inte(Int)
    case Numb(Double)
    case LatLng(Double,Double)
    case Boo(Bool)
    init(){
        self = .Str("Hello World")
    }
}

此時可以結合switch,根據case中的入參,返回不同的值

enum ValuesOfDifferentType{
    case Str(String)
    case Inte(Int)
    case Numb(Double)
    case LatLng(Double,Double)
    case Boo(Bool)
    init(){
        self = .Str("Hello World")
    }
}

在moya網路請求封裝中就使用到了;使用moya封裝網路請求時,需要定義一個列舉,遵循TargetType;列舉中定義需要訪問的介面型別,大多根據介面功能定義case;因為我們專案請求介面定義比較標準,大都使用一個入參格式,所以我沒有將全部的介面展示,只區分了上傳、下載以及post請求。程式碼片段如下

public enum SWNetworkAPI{
    case requestWithVersion(params: [String: Any])//請求
    case requestUploadImage(params: [String: Any],urlParams:[String : Any])//上傳圖片
    case requestUploadImages(params: [UIImage],urlParams:[String : Any])//批量上傳圖片
}

//通過擴充套件遵循協議 : 當一個型別已經符合了某個協議中的所有要求,卻還沒有宣告遵循該協議時,可以通過空擴充套件體的擴充套件來遵循該協議:
//從現在起,SWNetworkAPI的例項可以作為 TargetType 型別使用:
extension SWNetworkAPI : TargetType {
  //伺服器地址
    public var baseURL: URL {
        switch self {
        case .requestWithVersion:
            return URL.init(string: TSP_BASE_URL)!
        case .requestUploadImage:
            return URL.init(string: TSP_BASE_URL)!
        case .requestUploadImages:
            return URL.init(string: TSP_BASE_URL)!
        }
     }
    //各個請求的具體路徑
     public var path: String {
        switch self {
        case .requestWithVersion:
            return TSP_POST_PATH
        case .requestUploadImage:
            return TSP_UPLOAD_IMAGE
        case .requestUploadImages:
            return TSP_UPLOAD_IMAGES
        }
    }
    
    //請求型別
    public var method: Moya.Method {
        switch self {
        case .requestWithVersion:
            return .post
        case .requestUploadImage:
            return .post
        case .requestUploadImages:
            return .post
        }
    }

    //請求任務事件(帶上引數)
    public var task: Task {
        switch self {
        case .requestWithVersion(let params):
		//根據入參,生成task,返回task
            return .requestParameters(parameters: params, encoding: JSONEncoding.default)
        case .requestUploadImage(let params,let urlParams):
        case .requestUploadImages(let params,let urlParams):
            return .uploadCompositeMultipart(formDataArray as! [Moya.MultipartFormData], urlParameters: urlParams)
        }
    }
    //定義請求頭
    public var headers: [String : String]? {
        switch self {
        case .requestWithVersion:
            return ["Content-type" : "application/json;charset=utf-8;","Accept-Language":"zh-CN"]
        case .requestUploadImage:
            return ["Content-Type" : "Multipart/form-data","Accept": "application/json;charset=utf-8"]
        case .requestUploadImages:
            return ["Content-Type" : "Multipart/form-data","Accept": "application/json;charset=utf-8"]

        }
    }
}

言歸正傳!!!

定義列舉型別,列舉可以向變數和常量一樣定義一個型別;下面定義的就是一個String型別的列舉。

*注意:
1.列舉型別的原始值,必須是字面量
2.只有定義了列舉型別,才可以給case賦值
3.如果沒有定義列舉型別

enum DaysOfAWeek : String{
    case Sunday = "Today is Sunday"
    case Monday = "Today is Monday"
    case Tuesday = "Today is Tuesday"
    case Wednesday
}

然後可以根據rawValue獲取,列舉的具體值

var today = DaysOfAWeek.Sunday.rawValue//列印結果:Today is Sunday
today = DaysOfAWeek.Wednesday.rawValue//列印結果:Wednesday

也可以通過rawValue檢索列舉中的case值。

var possibleDay = DaysOfAWeek(rawValue: "Today is Monday")
print(possibleDay ?? "Day doesn't exist")
//列印結果:Monday
possibleDay = DaysOfAWeek(rawValue: "Thursday")
print(possibleDay ?? "Day doesn't exist")
//列印結果:Day doesn't exis

自動設定原始值
列舉可以自動設定case原始值,當列舉型別為Int、Double、float

//例子1
enum Numbers : Int{
    case caseOne = 100, caseTwo
    case caseThree
}
var num = Numbers.caseOne.rawValue//列印結果:100
num = Numbers.caseTwo.rawValue//列印結果:101
num = Numbers.caseThree.rawValue//列印結果:102
//例子2
enum NumbersO : Int{
    case caseOne
    case caseTwo = 2
    case caseThree
}
var numO = NumbersO.caseOne.rawValue//列印結果:0
numO = NumbersO.caseTwo.rawValue//列印結果:2
numO = NumbersO.caseThree.rawValue//列印結果:3
//例子3
enum NumbersT : Int{
    case caseOne = 100, caseTwo = 2
    case caseThree
}
var numT = NumbersT.caseOne.rawValue//列印結果:100
numT = NumbersT.caseTwo.rawValue//列印結果:2
numT = NumbersT.caseThree.rawValue//列印結果:3

將列舉轉換成字串

enum DaysOfAWeek : String{
    case Sunday
    case Monday
    case Tuesday
    case Wednesday
    func day()->String{
        return self.rawValue
    }
}
var str = DaysOfAWeek.Sunday.day()
print(str)//列印結果:Sunday

2.Struct

struct 定義

struct Name{
    //properities here
}

定義一個矩形

struct Rectangle{
    var width = 0
    var height = 0
}

要訪問或修改結構體的屬性我們用點操作符

var rectangle = Rectangle()
print(rectangle.width)//列印結果:0
print(rectangle.height)//列印結果:0

rectangle.width = 10
rectangle.height = 10

如果初始化的結構,是常量,結構體中的屬性值不能修改

let rectangleConstant = Rectangle()
rectangleConstant.height = 20//報錯
rectangleConstant.width = 20//報錯

struct Circle{
    let radius = 0
}

var circle = Circle()
circle.radius = 10//報錯

結構體中定義函式

struct Rectangle {
    var width = 0
    var height = 0
    //手動輸入寬高,獲取面積
    func area(width :Int, height: Int) -> String
    {
         return "Area is  \(width*height)"
    }
    //根據結構體內部引數值,獲取面積
    func area() -> String{
        return "Return area is \(self.width * self.height)"
    }
    //修改引數
    mutating func printModifiedWidth() -> String
    {

        width = width*2
        return "Modified width is \(width)"
    }
    //自定義初始化方法
    init(width: Int, height: Int) {
        self.width = width*2
        self.height = height*2
    }
    //初始化委託
    init(width: Int){
        self.init(width: width,height: width)
    }
    //預設宣告,不然空初始化會報錯
    init(){
        self.init(width: 0,height: 0)
    }
    //靜態函式
    static func printString() -> String
    {

    return "Hello how you're doing"
    }
}
//使用如下所示的結構例項呼叫函式
var rectangle = Rectangle()
rectangle.width = 10
rectangle.height = 10
rectangle.area(width:rectangle.width,height:rectangle.height)
rectangle.area()

//如果要在函式中修改屬性值,我們需要用關鍵字mutating來標記函式,然後給屬性重新賦值
//結構體中的屬性不能在內部函式中修改,將函式宣告為內部突變函式,將允許我們改變結構體中的屬性
rectangle.printModifiedWidth()
print(rectangle.width)//列印結果:20

//結構體初始化有兩種形式,
//1.空的初始化()
var rectangleInitial = Rectangle()
//2.也可以是在括號內列出結構屬性的成員初始值設定項,以便可以為它們指定新值,但是麻煩再需要給每個屬性都賦值
var rectangleInitialMemberWise = Rectangle(width:10,height:10)

//我們也可以在結構體內部自定義初始化方法
var rectangleCustom = Rectangle(width: 10, height: 10)
print(rectangleCustom.width) //prints 20
print(rectangleCustom.height) //prints 20

var square = Rectangle.init(width:20)
print(square.width) //prints 40
print(square.height) //prints 40

//結構體內部的靜態函式可以在不建立結構例項的情況下呼叫
Rectangle.printString()//列印結果:Hello how you're doing

可以使用以下語法動態計算屬性
get:當屬性值改變時,自動改變area

struct Rectangle {
    var width = 0
    var height = 0
    
    var area: Int {
        get {//計算結果
            return width*height
        }
        set {//初始值
            area = 0
        }
    }
}
var rectangle = Rectangle()
print(rectangle.area) //prints 0
rectangle.width = 20
rectangle.height = 20
print(rectangle.area) //prints 400

Swift結構是通過值傳遞的,而不是通過引用傳遞的

var rect = rectangle
rect.width = 30
print(rectangle.width) //prints 20 and NOT 30