类的定义
所有的属性和方法都是全局共享的,不需要 import
1 2 3 4 5 6 7 8
| import UIKit
class Person: NSObject {
var name: String
}
|
构造函数
给属性分配空间,设置初始值,父类提供了构造函数需要对父类的构造函数进行扩展,使用关键字override
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import UIKit class Person: NSObject {
var name: String
override init() { name = "Zhang San" super.init() } }
let p = Person() print(p.name);
|
函数重载
函数名相同,参数个数和类型不同
1 2 3 4 5 6 7 8 9
| class Person: NSObject { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } }
|
KVC
Key-value coding,通过Key名直接访问对象属性或赋值,而不需要调用明确的存取方法
1 2 3 4 5 6 7 8 9 10 11 12
| class Person: NSObject { var name: String? var age: Int = 0
init(dict: [String: Any]) { super.init() setValuesForKeysWithDictionary(dict) } }
let p = Person(["name": "Zhang San", "age": 20])
|
便利构造函数
能够提供条件检测,允许返回nil
,默认的构造函数必须要创建对象,便利构造函数必须以self.
的方式调用其他构造函数创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Person: NSObject { var name: String? var age: Int = 0
init(dict: [String: Any]) { super.init() setValuesForKeysWithDictionary(dict) }
convenience init?(name: String, age: Int) { if age < 0 || age > 100 { return nil } self.init(dict: ["name": name, "age": age]) } } let p = Person("name": "Zhang San", age: 101)
print("name: \(p!.name), age: \(p!.age)")
print("name: \(p?.name), age: \(p?.age)");
|
对象释放方法,与dealloc
类似,主要负责对象被销毁前的内存释放工作,不允许重载,不允许带参数,不允许直接调用,会先调用子类的释放函数再调用父类的
需要程序员销毁的内容
- 通知 (不注销不会崩溃)
- KVO (不注销会崩溃)
- NSTimer (会对target (self) 进行强引用)
1 2 3 4 5
| class Person: NSObject { deinit { print("Person deinit") } }
|
懒加载
本质上是一个闭包,第一次访问属性时会执行后面的闭包,将返回值保存在属性中,下次访问就不会执行闭包,直接获取属性的值
如果没有lazy,会在initWithCoder
方法中被调用,当二进制的storyboard
被还原成视图控制器对象后,就会被调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import UIKit class ViewController: UIViewController { lazy var person: Person = { print("懒加载") return Person() }()
let personFunc = { () -> Person in print("懒加载") return Person() } lazy var demoPerson: Person = self.personFunc()
lazy var demoPerson: Person = Person()
var name: String? = "Zhang San" lazy var title: String? = { return "Mr " + (self.name ?? "") } }
|
getter和setter
在Swift中极少用,仅供参考
OC中使用getter
进行懒加载,而Swift提供了lazy
关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Person: NSObject { private var _name: String var name: String? { get { return _name } get { _name = newValue } } }
let p = Person() p.name = "Zhang San" print(p.name);
|
read only
只读属性,也叫计算型属性,每次调用时都会执行大括号中的代码
只写getter
方法
1 2 3 4 5 6 7 8 9 10
| print var _name: String? var name: String? { get { return _name } }
var name: String? { return _name }
|
懒加载与计算型属性的区别
懒加载
- 只计算一次
- 需要开辟单独的空间保存计算结果
- 闭包的代码再也不会被调用
- 如果计算量很大,需要提前准备
计算型属性
类函数(静态函数)
1 2 3 4 5 6 7 8 9 10
| import UIKit class Person: NSObject { static var text: String = "Test" class func staticFunc() { print("类函数") } }
|
单例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import UIKit class Person: NSObject { static var instance: Person? static var onceToken: dispatch_once_t = 0 class func person() -> Person { dispatch_once(&onceToken) { () -> Void in instance = Person() } return instance! } static let person2: Person = { return Person() }() }
|
extension
对在已存在的类、类型进行扩展,但不能覆盖现有功能
计算属性
1 2 3 4 5 6 7 8 9 10 11
| extension Double { var km: Double { return self * 1000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1000.0 } var ft: Double { return self / 3.28084 } }
let threeFeet = 3.ft print("3英尺是 \(threeFeet) 米");
|
扩展方法
以下例子是对Int
使用,也可以对自定义的类使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| extension Int { func repetitions(task: () -> Void) { for _ in 0..<self { task() } } }
3.repetitions { print("Hello"); }
3.repetitions(task: { print("Hello"); })
|
视图模型
模型通常继承自NSObject
,可以使用KVC设置属性,简化对象构造
而视图模型没有父类,所有内容都要从头构造
视图模型是封装业务逻辑,通常没有复杂的属性
1 2 3 4 5 6 7 8 9
| import Foundation class UserAccountViewModel { var account: UserAccount? init() {
} }
|
协议
类似接口,用于制定属性和方法,让其他遵守协议的地方实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import UIKit protocol Pet { var name: String { get set } func playWith() func fed() } class Animal { var type: String = "mammal" }
class Dog: Animal, Pet { var name: String = "Puppy" func playWith() { print("wong") } func fed() { print("I love Bones") } }
|
属性观察者
在属性即将赋值、赋值后进行操作,默认赋值和init
初始化方法中的赋值不会触发属性观察者
1 2 3 4 5 6 7 8 9 10 11 12 13
| import UIKit class person { var age = 0 { willSet(newAge) { print("原值:\(age),即将被赋值为:\(newAge)") } didSet(oldAge) { print("原值:\(oldAge),即将被赋值为:\(age)") } } }
|