您好,登錄后才能下訂單哦!
常量和變量是某個特定類型的值的名字,如果在程序運行時值不能被修改的是一個常量,反之是一個變量。
Swift中的常量和變量在使用前必須先聲明。其中let
關鍵字聲明常量,var
關鍵字聲明變量:
//聲明一個名為maximumNumberOfLoginAttempts的整型常量,并且值為10let maximumNumberOfLoginAttempts = 10//聲明一個名為currentLoginAttempt的整型變量,并且值為0var currentLoginAttempt = 0
可以在同一行聲明多個變量,中間用逗號,
隔開:
var x = 0.0, y = 0.0, z = 0.0
提示
如果在程序運行的時候值不需要發生改變,應該將它們聲明為常量,否則聲明為變量
變量的值可以進行修改:
var friendlyWelcome = "Hello!"friendlyWelcome = "Bonjour!" //friendlyWelcome的值發生改變
常量的值一旦設置后就不能在修改:
let languageName = "Swift"languageName = "Swift++" //編譯時出錯
在Swift中聲明常量或者變量可以在后面用冒號:
指定它們的數據類型。
//聲明一個String類型的變量,可以存放String類型的值var welcomeMessage: String
提示
實際應用中很少需要指定變量數據類型,Swift會根據所設置的值的類型進行推導。
Swift中可以使用任意字符給常量和變量命名,包括Unicode編碼,比如中文、Emoji等:
let π = 3.14159let 你好 = "你好世界"let dog = "dogcow"
名字里面不能包含數學運算符、箭頭、非法的Unicode字符以及不能識別的字符等,并且不能以數字開頭。同一個作用域的變量或者常量不能同名。
提示
如果想用關鍵字作為變量的名字,要用(`)包裹起來。為了方便理解,如果不是萬不得已,不應該使用關鍵字作為變量的名字。
println
函數可以打印常量或者變量的值:
println(friendlyWelcome) //打印出“Bonjour!”
println
是一個全局函數,輸出時自動在結尾添加換行。print
函數與它的功能類似,只是不會在結尾添加換行符。println
與NSLog
類似,可以用來輸出復雜的日志信息。Swift使用字符串插值來輸出變量和常量。
println("The current value of friendlyWelcome is \(friendlyWelcome)")//打印“The current value of friendlyWelcome is Bonjour!”
注釋是用來幫助理解和記憶代碼功能的,并不會參與編譯。Swift有兩種注釋形式,單行注釋和多行注釋:
//這是單行注釋,用兩個斜線開頭,直到改行的結尾/*這是多行注釋, 可以橫跨很多行, /*比C語言更加NB的是,*/它竟然還支持嵌套的注釋!*/
Swift中語句結尾的分號;
不是必須的,不過如果想要在同一行中寫多個語句,則需要使用;
進行分隔。
let cat = "cat"; println(cat)//打印“cat”
屬性是依賴于某個特定的類、結構體或者枚舉類型的值。Swift有兩種屬性:存儲類型和計算類型。其中存儲類型可以作為實例的一部分存放變量或者常量的值,而計算類型的屬性值是通過運算的來的。計算類型的屬性可以在類、結構體和枚舉類型中出現,但存儲類型只可能出現在類和結構體類型中。
屬性一般依賴于一個特定類型的實例,但是也可以依賴于類本身。依賴于類型本身的屬性稱為類型屬性。
可以定義屬性觀察者來監督屬性值的改變,從而作出響應。
常量屬性let
的值在初始化后不能在改變,而變量屬性var
的值可以隨時更改。
struct FixedLengthRange { var firstValue: Int let length: Int }var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3) rangeOfThreeItems.firstValue = 6
如果一個結構體實例被賦值給一個常量,則這個實例所擁有的存儲類型的屬性都不能在改變,包括變量屬性在內。
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4) rangeOfFourItems.firstValue = 6//編譯錯誤,firstValue的值不能改變
延時存儲屬性的初始值直到第一次使用的時候才進行計算,在聲明時通過@lazy
進行標記。
提示
一定要將延時存儲屬性聲明為變量(var
),因為它的初始值可能會在實例初始化完成后才有,而常量屬性一般在實例初始化完成之前就會有值。
當屬性的初始值依賴于外部銀子,并且該因子的值在實例初始化完成之前不確定時,延時屬性非常有用。如果屬性初始化時需要進行大量的計算,也可以考慮使用延時屬性。
下面是延時屬性的示例:
class DataImporter { /* DataImporter是一個從外部文件導入數據的類。假設它需要花費較多的時間進行初始化 */ var fileName = "data.txt" //DataImporter類的數據導入功能} class DataManager { @lazy var importer = DataImporter() var data = String[]() //DataManager類提供數據管理功能} let manager = DataManager() manager.data += "Some data"manager.data += "Some more data"http://DataImporter實例還沒有創建
只有訪問DataManager
的importer
屬性時才會去創建這個對象。
println(manager.importer.filename)//創建importer屬性并打印“data.txt"
Objective-C類的對象可以使用屬性或者實例變量來存儲值。Swift中并沒有所謂的實例變量,而是將它們統一為屬性了,這樣使得屬性的聲明更加簡化。
除了存儲屬性外,類、結構體和枚舉類型還可以定義計算屬性。這些計算屬性并不能夠存儲值,而是通過getter
方法和可選的setter
方法來間接的獲取和設置其它屬性和值。
struct Point { var x = 0.0, y = 0.0}struct Size { var width = 0.0, height = 0.0}struct Rect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } }var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0)) let initialSquareCenter = square.center square.center = Point(x: 15.0, y: 15.0)println("square.origin is now at (\(square.origin.x), \(square.origin.y))")//打印”square.origin is now at (10.0, 10.0)“
這個例子定義了三個結構體來表示幾何形狀:
Point
封裝了(x, y)坐標。
Size
封裝了寬度和高度。
Rect
用坐標原點和大小定義一個矩形。
其中Rect
結構體還提供了一個center
的計算屬性。這個屬性的值是由矩形的origin
和size
屬性決定的,它本身并不需要存儲信息。但是改變center
的值,會間接的修改矩形的其它屬性。
setter
的聲明如果沒有為計算屬性的setter
的新值指定名字,則默認使用newValue
。下面是Rect
結構體的另外一種寫法:
struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }
如果一個計算屬性只有getter
而沒有聲明setter
,則它是一個只讀的計算屬性。只讀屬性只能通過點語法返回一個值,而不能對它進行設置。
提示
必須使用var
聲明計算屬性,包括只讀的計算屬性在內,因為它們的值是可能改變的。而let
只能用于常量的聲明,表示它們的值不能發生改變。
還可以省略只讀計算屬性聲明中的get
關鍵字。
struct Cuboid { var width = 0.0, height = 0.0, depth = 0.0 var volume: Double { return width * height * depth } } let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")//打印“the volume of fourByFiveByTwo is 40.0”
屬性觀察者用來觀察和響應屬性值的變化。每次設置屬性的值都會調用相應的觀察者,哪怕是設置相同的值。
可以給除延時存儲屬性以外的任何存儲屬性添加觀察者。通過重寫屬性,可以在子類中給父類的屬性(包括存儲屬性和計算屬性)添加觀察者。
提示
不需要給類本身定義的計算屬性添加觀察者,完全可以在計算屬性的setter
中完成對值的觀察。
通過下面兩個方法對屬性進行觀察:
willSet
在屬性的值發生改變之前調用。
didSet
在設置完屬性的值后調用。
如果沒有給willSet
指定參數的話,編譯器默認提供一個newValue
做為參數。同樣,在didSet
中如果沒有提供參數的話,默認為oldValue
。
提示
willSet
和didSet
觀察者在屬性進行初始化的時候不會被調用。
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { println("About to set totalSteps to \(newTotalSteps)") } didSet { if totalSteps > oldValue { println("Added \(totalSteps - oldValue) steps") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = 200//About to set totalSteps to 200//Added 200 stepsstepCounter.totalSteps = 360//About to set totalSteps to 360//Added 160 stepsstepCounter.totalSteps = 896//About to set totalSteps to 896//Added 536 steps
提示
如果在didSet
中給屬性設置新值,最終結果就是最后設置的這個值。
上面關于計算屬性和屬性觀察對全局變量和局部變量同樣成立。全局變量定義在任意的方法、函數、閉包或者類型定義之外。而局部變量則定義在方法、函數或閉包之內。
之前遇到的全局變量或者局部變量都跟存儲屬性類型,都是用來存儲值的。但實際上它們也能像計算屬性有計算變量。
提示
全局變量和常量與延時屬性類似,總是延時進行計算。但是它們并不需要使用@lazy
標記。
局部常量和變量一定不是延時計算的。
實例屬性屬于某個特定類型的實例。每次創建的實例,它都擁有自己的一組獨立的屬性值,不受其它實例對象影響。
你還可以定義屬于類型本身的屬性。這些屬性是與具體的實例無關的,不管創建多少個實例都只有一份。這種屬性稱之為類型屬性。
可以給值類型(結構體和枚舉類型)定義存儲和計算類型的類屬性,但是只能給類定義計算類型的類屬性。值類型的存儲屬性可以是變量或常量。
提示
一定要給存儲類型的類屬性設置初始值。
在C/Objective-C中只能使用全局靜態變量來定義依賴與某個屬性的變量或常量。但是在Swift中可以直接將它們定義為類型的一部分。其中結構體和枚舉類型中使用static
關鍵字,而在類類型中則使用class
關鍵字。
struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { //return an Int value here } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { //return an Int value here } } class SomeClass { class var computedTypeProperty: Int { //return an Int value here } }
提示
上面的計算屬性都是只讀的,但實際上可以定義為可讀可寫
類型屬性通過類型名字和點操作符進行訪問和設置,而不是通過實例對象:
println(SomeClass.computedTypeProperty)//print "42"println(SomeStructure.storedTypeProperty)//prints "Some value"SomeStructure.storedTypeProperty = "Another value."println(SomeStructure.storedTypeProperty)//prints "Another value."
下面演示了如何使用一個結構體來對聲道音量進行建模,其中每個聲道音量范圍為0-10。
struct AudioChannel { static let thresholdLevel = 10 static var maxInputLevelForAllChannel = 0 var currentLevel: Int = 0 { didSet { if currentLevel > AudioChannel.thresholdLevel { currentLevel = AudioChannel.thresholdLevel } if currentLevel > AudioChannel.maxInputLevelForAllChannels{ AudioChannel.maxInputLevelForAllChannels = currentLevel } } }var leftChannel = AudioChannel()var rightChannel = AudioChannel() leftChannel.currentLevel = 7println(leftChannel.currentLevel)//prints "7"println(AudioChannel.maxInputLevelForAllChannels)//prints "7"
當修改其中一個聲道的值時,整個聲道的音量最大值就可能發生改變。而每個聲道都有自己的當前音量水平。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。