1、willSet与didSet(属性观察)
willSet: 在属性变化前做点什么,didSet:在属性发生变化后做些什么,另外注意:根据苹果的注释,在初始化方法中设置属性不会调用 willSet 和 didSet。当设置的值和原来的值一样时,willSet和didSet也会被调用。
和set/get的区别是,要获取旧值和新值,写起来更简洁。
2、lazy延迟加载
和OC中getter方法实现懒加载一样,在使用的时候才创建。注意:lazy属性必须是变量(var修饰符),因为常量属性(let修饰符)必须在初始化之前就有值,所以常量属性不能定义为lazy。
lazy var names: NSArray = {
let names = NSArray()
print("只在首次访问输出")
return names
}()
【 扩展知识点:这些方法可以配合像 map 或是 filter 这类接受闭包并进行运行的方法一起,让整个行为变成延时进行的。在某些情况下这么做也对性能会有不小的帮助 】
3、NotificationCenter
添加监听:
NotificationCenter.default.addObserver(self, selector: #selector(bookPickASpotClassSuccess), name: NSNotification.Name.init("kBookPickASpotClassSuccess"), object: nil)
移除监听:
deinit {
/// 移除通知 NotificationCenter.default.removeObserver(self)
}
发送监听:
/// 发送简单数据
NotificationCenter.default.post(name: NSNotification.Name.init("XMNotification"), object: "Hello 2017")
/// 发送额外数据
let info = ["name":"Eric","age":21] as [String : Any]
NotificationCenter.default.post(name: NSNotification.Name.init("XMNotification"), object: "GoodBye 2016", userInfo: info)
4、protocol
语法:
protocol SomeProtocol {
// protocol definition goes here
}
遵守协议:
struct SomeStructure : FirstProtocol, AnotherProtocol {// structure definition goes here}
当一个类既有父类,又遵守其他协议时,将父类名写在所遵守协议的前面
协议可以像类一样,继承自其他多个协议,通过将AnyObject(class)协议添加到协议的继承列表中,来限制该协议只适用于class类型,而不适用于枚举和结构体。
【 扩展 】:参考链接:https://www.jianshu.com/p/d939c3443686
5、几种属性的分类
- 存储属性:一般属性,用于存储常量和变量
- 计算属性:计算属性并不存储实际的值,而是提供一个getter和一个可选的setter来间接获取和设置其它属性,计算属性一般只提供getter方法
var averageScore : Double {
get {
return (chineseScore + mathScore) / 2
}
// 没有意义,因为之后获取值时依然是计算得到的
// newValue是系统分配的变量名,内部存储着新值
set {
self.averageScore = newValue
}
}
- 类属性
类属性是与类相关联的,而不是与类的实例相关联
所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
类属性的设置和修改,需要通过类来完成
类属性使用static来修饰
static var corseCount : Int = 0
- 全局属性
写在类外面的属性
6、属性访问控制
Swift 中由低至高提供了 private,fileprivate,internal,public 和 open 五种访问控制的权限。默认的 internal。
- public和open的区别是,open修饰的属性和方法可以在target外访问,并且可以被继承和重写,public是只能被访问,但不能被继承和重写。
private和fileprivate的区别: - fileprivate修饰的属性和方法只要在同一个文件中,都可以被访问。private只能在同一个文件的这个类的作用域里面访问或者同一个文件的该类的类扩展中访问。不管子类在不在同一个文件,都不能访问。
7、Swift的方法参数的内部名称和外部名称
init(red redColor: Double) {
}
其中red是外部参数名,外面的类调用的时候显示的参数名,redColor是内部参数名,如果只有参数的内部名称,没有外部名称,编译器会自动为参数创建一个和内部名称相同的外部名称。
8、Swift 4.0 @objc的使用
@objc是为了标记可能会被OC调用的swift方法,之前只要继承自NSObject,就默认都会被隐式地标记为@objc,现在是不会全部标记。
- 在 Swift 4 中隐式 @objc 自动推断只会发生在下面这种必须要使用 @objc 的情况:
1)覆盖父类的 Objective-C 方法
2)符合一个 Objective-C 的协议 - 大多数地方必须手工显示地加上 @objc。
class MyClass: NSObject {
@objc func print() { } //显示的加上 @objc
@objc func show() { } //显示的加上 @objc
}
- 如果在类前加上 @objcMembers,那么它、它的子类、扩展里的方法都会隐式的加上 @objc。
@objcMembers
class MyClass: NSObject {
func print() { } //包含隐式的 @objc
func show() { } //包含隐式的 @objc
}
extension MyClass {
func baz() { } //包含隐式的 @objc
}
- 如果在扩展(extension)前加上 @objc,那么该扩展里的方法都会隐式的加上 @objc。
class SwiftClass { }
@objc extension SwiftClass {
func foo() { } //包含隐式的 @objc
func bar() { } //包含隐式的 @objc
}
- 如果在扩展(extension)前加上 @nonobjc,那么该扩展里的方法都不会隐式的加上 @objc。
@objcMembers
class MyClass : NSObject {
func wibble() { } //包含隐式的 @objc
}
@nonobjc extension MyClass {
func wobble() { } //不会包含隐式的 @objc
}
网友评论