- 存儲(chǔ)屬性
- 計(jì)算屬性
- 屬性觀察器
- 類型屬性
-
存儲(chǔ)屬性
存儲(chǔ)常量或變量作為實(shí)例的一部分费变,用于類和結(jié)構(gòu)體摧扇。
- 常量存儲(chǔ)屬性:let name = value
- 變量存儲(chǔ)屬性:var name = value
- 延遲存儲(chǔ)屬性(類似OC懶加載) : lazy var = value
栗子
等下!?? 先談?wù)凷wift中的 問(wèn)號(hào)"?" 挚歧, "!"感嘆號(hào)
問(wèn)號(hào)扛稽?
a.聲明時(shí)添加?滑负,告訴編譯器這個(gè)是Optional的在张,如果聲明時(shí)沒(méi)有手動(dòng)初始化,就自動(dòng)初始化為nil
b.在對(duì)變量值操作前添加矮慕?帮匾,判斷如果變量時(shí)nil,則不響應(yīng)后面的方法痴鳄。
嘆號(hào)瘟斜!
a.聲明時(shí)添加!痪寻,告訴編譯器這個(gè)是Optional的螺句,并且之后對(duì)該變量操作的時(shí)候,都隱式的在操作前添加槽华!
b.在對(duì)變量操作前添加壹蔓!,表示默認(rèn)為非nil猫态,直接解包進(jìn)行處理
所以
可以理解為: '!'修飾的變量不可為nil, '?'修飾的變量可為nil. 所以在訪問(wèn)'!'修飾的變量一旦不小心為nil佣蓉,則Crash
// MARK: Property
let name1: String = "String" // 可設(shè)置屬性類型
let name2 = "sd" // 可不設(shè)置屬性類型
var namevar1: String? // 可不設(shè)初始值
var namevar2: String = "namevar2" //可設(shè)置初始值
var mainView = UIView() // 初始值為一個(gè)UIView對(duì)象
lazy var label: UILabel = {
let tempLabel = UILabel()
// Config
return tempLabel
}() // lazy 創(chuàng)建一個(gè)label
// MARK: func
override func viewDidLoad() {
super.viewDidLoad()
print("name1=",name1)
print("name2=",name2)
print("namevar1=",namevar1) // 若訪問(wèn)為空的屬性,會(huì)報(bào)警告提示 "namevar1 ?? <#default value#>"
print("namevar2=",namevar2)
print("mainView=",mainView)
print("label=",label)
/*
打印結(jié)果:
name1= String
name2= sd
namevar1= nil
namevar2= namevar2
mainView= <UIView: 0x7fa2dad09ea0; frame = (0 0; 0 0); layer = <CALayer: 0x600000034200>>
label= <UILabel: 0x7fa2dad063a0; frame = (0 0; 0 0); userInteractionEnabled = NO; layer = <_UILabelLayer: 0x608000092890>>
*/
}
注意:
必須將延遲存儲(chǔ)屬性聲明成變量(使用 var 關(guān)鍵字)亲雪,因?yàn)閷傩缘某跏贾悼赡茉趯?shí)例構(gòu)造完成之后才會(huì)得到勇凭。而常量屬性在構(gòu)造過(guò)程完成之前必須要有初始值,因此無(wú)法聲明成延遲屬性义辕。
-
計(jì)算屬性
類似OC重寫Setter Getter 虾标。
**類 ** 結(jié)構(gòu)體 枚舉 可定義計(jì)算屬性。
通常通過(guò)計(jì)算屬性間接獲取或設(shè)置其他屬性 或 變量值灌砖。
栗子
還是拿官方栗子吧(設(shè)置Center
可以改變point
, 當(dāng)然設(shè)置point
size
可獲取center
)
“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)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// 打印 "square.origin is now at (10.0, 10.0)”
只讀計(jì)算屬性: ( 只有 getter
沒(méi)有 setter
聲明可以去掉 getter
關(guān)鍵字和花括號(hào))
private var width: NSInteger?
private var height: NSInteger?
var perimeter: NSInteger {
return width! + height!
}
override func viewDidLoad() {
super.viewDidLoad()
width = 10
height = 10
print(perimeter) //輸出: 20
}
注意:
計(jì)算屬性只能使用關(guān)鍵字 var 定義,為毛璧函?因?yàn)樗亲兊摹?/p>
-
屬性觀察器
檢測(cè)屬性的變化
每次屬性被賦值的時(shí)候調(diào)用
延遲屬性(lazy), 計(jì)算屬性不可直接使用
栗子
/*
// 不賦初始值
var stringData: String?{
willSet{
}
didSet{
}
}
*/
//賦初始值 演示:
var stringData: String = "First"{
willSet{
print("stringData=",stringData,"newValue=",newValue)
}
didSet{
print("stringData=",stringData,"oldValue=",oldValue)
}
}
override func viewDidLoad() {
super.viewDidLoad()
stringData = "hello,world"
/*
輸出:
stringData= First newValue= hello,world
stringData= hello,world oldValue= First
*/
}
`willSet` 在新的值被設(shè)置之前調(diào)用(觀察器會(huì)將新的屬性值作為常量參數(shù)傳入”默認(rèn)名稱`newValue`)
`didSet` 在新的值被設(shè)置之后立即調(diào)用(觀察器會(huì)將舊的屬性值作為參數(shù)傳入傀蚌,可以為該參數(shù)命名或者使用默認(rèn)參數(shù)名 `oldValue`。如果在 didSet 方法中再次對(duì)該屬性賦值蘸吓,那么新值會(huì)覆蓋舊的值善炫。)
任意選哪個(gè)都可,也可全選,視編碼時(shí)具體情況而定
-
類型屬性
跟實(shí)例的存儲(chǔ)型屬性不同,必須給存儲(chǔ)型類型屬性指定默認(rèn)值
使用關(guān)鍵字 static 來(lái)定義库继,通過(guò)類型本身來(lái)訪問(wèn)
它們只有在第一次被訪問(wèn)的時(shí)候才會(huì)被初始化箩艺。即使它們被多個(gè)線程同時(shí)訪問(wèn),系統(tǒng)也保證只會(huì)對(duì)其進(jìn)行一次初始化宪萄,并且不需要對(duì)其使用 lazy
修飾符艺谆。
栗子
下面栗子演示了“存儲(chǔ)型和計(jì)算型類型屬性的語(yǔ)法:
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
/*
在為類定義計(jì)算型類型屬性時(shí),可以改用關(guān)鍵字 class 來(lái)支持子類對(duì)父類的實(shí)現(xiàn)進(jìn)行重寫
*/
}
官方的一個(gè)很好的栗子,如果你看懂了這個(gè)??.恭喜你兄弟??拜英。你已經(jīng)掌握了Swift的屬性篇.
struct AudioChannel {
static let thresholdLevel = 10 //“音量的最大上限閾值”常量存儲(chǔ)型類型屬性
static var maxInputLevelForAllChannels = 0 //“最大音量”變量存儲(chǔ)型類型屬性
var currentLevel: Int = 0 {
didSet {
if currentLevel > AudioChannel.thresholdLevel {
// 將當(dāng)前音量限制在閥值之內(nèi)(可在這兒直接賦值,放心這不會(huì)造成屬性觀察器被再次調(diào)用)
currentLevel = AudioChannel.thresholdLevel
}
if currentLevel > AudioChannel.maxInputLevelForAllChannels {
// 存儲(chǔ)當(dāng)前音量作為新的最大輸入音量
AudioChannel.maxInputLevelForAllChannels = currentLevel
}
}
}
}
總結(jié):
雖然平時(shí)開(kāi)發(fā)中静汤,已經(jīng)編入Swift了。但想好好研究鞏固Swift,所以今天結(jié)合了下官方文檔寫了這篇文章居凶。寫完之后感覺(jué)爽爽噠撒妈。嘿嘿嘿Swift屬性篇完成了,兄弟們?nèi)绻矚g的話,敬請(qǐng)期待我的Swift下一篇文章.別忘點(diǎn)贊啊排监,給哥們動(dòng)力。感謝杰捂!