2017年4月7日 星期五

Swift: MVC, Class vs Struct, Mutating Keyword, Dictionary




  • MVC

Model (Should be UI independent.), View, Control 
三者獨立的運行自己的工作,但以”溝通“的方式互相協調、互不干預。



  1.  Model絕不干涉UI

  • Class vs Struct

Class has inheritance, Struct don't.
Class live in Heap, pointers pointing to them.
Struct move by copying them.
Struct has initializer automatically, Class don't.

以下內容來自:Developer's Note: Swift

1. 建構物件時

struct


var sRect = SRectangle()
// 或者 

sRect = SRectangle(width:300)

sRect.width // 結果就是 300

class


var cRet = CRectangle()
// class 不能直接用 CRectangle(width:300) 必需要定義一個 constructor
cRect.width // 為 200

主要的差別就是 class 在產生物件時不能很自然把 property 放在 constructor 的參數裡

2. 指定給另一個變數的行為不同 

struct


var sRect = SRectangle()
// 或者 

var sRect2 = sRect

sRect2.width // 目前值是 200,因為 sRect 直接 copy 一份完整記憶體給 sRect2
sRect2.width = 500
sRect.width // sRect.width 值不受 sRect2 影響還是 200

class


var cRect = CRectangle()
// 或者 

var cRect2 = cRect

cRect2.width // 目前值是 200,因為 sRect 直接 copy 一份完整記憶體給 sRect2
cRect2.width = 500
cRect.width // cRect.width 也改變成了 500

以上是 value type 和 reference type 最大的不同,在每次做 assignment 的時候,value type 都會複製一份完整相同的內容給另一個變數,而 class 則是把記憶體的位置給變數。所以 reference type 大多會保有一份記憶體而重覆利用。

  • Mutating func in struct

3. 關於 immutable 變數 

在 Swift 這個語言的特色之一就是可變動內容的變數和不可變動內容的變數用 var 和 let 來區別。如果一開始用 let 來修飾變數就會造成 compiler 的錯誤。如下

var name = "Michael"
name.write(" Pan") // 這樣是正常

let name = "Michael"
name.write(" Pan") // 會造成 compile 錯誤

struct

大至也遵循這個規則如下

let sRect = SRectangle()

sRect.width = 500 // 會造成錯誤

class


let cRect = CRectangle()

cRect.width = 500 // 預設可以直接更改雖然是 let 修飾的 cRect

let 這個效果無法延申至 class 。不過要提醒大家在 Swift 常用的 String, Array, Dictionary 都是 struct 所以 let 是會有效果的

4. mutating function 

我們先要為 struct 和 class 新增一個 method 名為 changeWidth() 而且我們在不改變原始的程式碼為前提下,新增一個 method。如下 

struct 


struct SRectangle {
    var width = 200
    
}

extension SRectangle {
    mutating func  changeWidth(width:Int){
        self.width = width
    }
}

class 


class CRectangle {
    var width = 0
}

extension CRectangle {
    func changeWidth(width:Int){
        self.width = width
    }
}

這裡用了 extension 新增 class 裡的 method 而不需要改到原本的程式碼。 以。struct 和 class 的差別是 struct 的 function 要去改變 property 的值的時候需要加上 mutating 字樣,而 class 不用這樣做

The Mutating Keyword

Let’s say you want to add an area function to your struct:
1
2
3
4
5
6
7
8
struct Rectangle {
    var width = 1
    var height = 1
     
    func area() -> Int {
        return width * height
    }
}
It’s just as you expect! This area function multiplies the existing width and height of the rectangle and returns the result. The key here is that this function does NOT change the width or height variables – it only uses the existing values.
In contrast, let’s say we wanted to have a function that scales the rectangle:
1
2
3
4
5
6
7
8
9
struct Rectangle {
    var width = 1
    var height = 1
    mutating func scaleBy(value: Int) {
        width *= value
        height *= value
    }
}
Notice that this function actually changes the width and height variables of the rectangle. So this is where you have to use the mutating keyword – when you’re actually changing the variables in your struct! (Via:Natasha the robot)

  • Dictionary usage 

Creating an Empty Dictionary




As with arrays, you can create an empty Dictionary of a certain type by using initializer syntax:
  1. var namesOfIntegers = [Int: String]()
  2. // namesOfIntegers is an empty [Int: String] dictionary
This example creates an empty dictionary of type [Int: String] to store human-readable names of integer values. Its keys are of type Int, and its values are of type String.
If the context already provides type information, you can create an empty dictionary with an empty dictionary literal, which is written as [:] (a colon inside a pair of square brackets):
  1. namesOfIntegers[16] = "sixteen"
  2. // namesOfIntegers now contains 1 key-value pair
  3. namesOfIntegers = [:]
  4. // namesOfIntegers is once again an empty dictionary of type [Int: String]

Creating a Dictionary with a Dictionary Literal




You can also initialize a dictionary with a dictionary literal, which has a similar syntax to the array literal seen earlier. A dictionary literal is a shorthand way to write one or more key-value pairs as a Dictionary collection.
key-value pair is a combination of a key and a value. In a dictionary literal, the key and value in each key-value pair are separated by a colon. The key-value pairs are written as a list, separated by commas, surrounded by a pair of square brackets:
  • [key 1: value 1, key 2: value 2, key 3: value 3]
The example below creates a dictionary to store the names of international airports. In this dictionary, the keys are three-letter International Air Transport Association codes, and the values are airport names:
  1. var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
The airports dictionary is declared as having a type of [String: String], which means “a Dictionarywhose keys are of type String, and whose values are also of type String”.


沒有留言:

張貼留言