苏州手机网站开发公司,域名交易网站建设,wordpress 设置用户权限,网站的营销方式有哪些KVC
KVC意思是键值编码#xff0c;是一种可以通过键名来访问对象属性的机制#xff0c;也可以对属性进行赋值#xff0c;包括私有属性#xff0c;由于KVC的定义是对OC中的NSObject的扩展进行实现的#xff0c;所以如果要使用KVC机制#xff0c;那么这个类需要继承NSObje…KVC
KVC意思是键值编码是一种可以通过键名来访问对象属性的机制也可以对属性进行赋值包括私有属性由于KVC的定义是对OC中的NSObject的扩展进行实现的所以如果要使用KVC机制那么这个类需要继承NSObject同时属性需添加objc关键字。如图
class Person:NSObject{objc var name:String{set{_name newValueprint(name被赋值了)}get{print(name被访问了)return _name}}objc var age:Intinit(age: Int) {self.age age}var _name
}
在上面的示例中name和age变量的用了objc修饰所以可以通过KVC机制对这两个变量进行读写而_name没有objc关键字修饰则不能通过KVC机制进行读写。
使用KVC机制进行读写访问
let p Person(age: 20)
p.setValue(Ally, forKey: name)//使用KVC进行赋值操作
let pName p.value(forKey: name) as! String//使用KVC进行访问操作
print(pName)
在使用KVC对计算属性(上面示例中的name属性进行读写操作时会分别调用属性的getter和setter方法。
执行结果如图 补充 计算属性在Swift中计算属性不直接存储值而是提供一个 getter 和一个可选的 setter 来间接获取和设置其他属性的值。计算属性可以不需要初始化因为计算属性并不会占用内存。 KVC机制和.语法的区别
我们知道对类的属性进行读写时可以创建对象然后通过.语法对属性进行读写操作那么两者的区别是什么呢
对于KVC机制它是在运行时才会检查错误比如访问某个不存在的属性安全性较低而点语法在编译时会进行类型检查同时.语法不能访问或修改私有成员变量而KVC机制可以。
KVC赋值和取值的原理
赋值
优先查找setKey方法或_setKey的第一个访问器。找到则直接完成。如果没有找到访问器则会检查类方法accessInstanceVariablesDirectly是否为YES如果是YES则会查找名称为_ key 、_is key 、 key 或is key 的实例变量。如果找到则直接完成。如果没有访问器或实例变量时调用setValue:forUndefinedKey:。这将在默认情况下引发异常。
取值
首先查找getKey、Key、isKey或_Key的方法找到则直接调用。
如果都没找到KVC则会查找countOfKey,objectInKeyAtIndex或KeyAtIndexes格式的方法。如果countOfKey方法和另外两个方法中的一个被找到那么就会返回一个可以响应NSArray所有方法的代理集合(它是NSKeyValueArray是NSArray的子类)调用这个代理集合的方法或者说给这个代理集合发送属于NSArray的方法就会以countOfKey,objectInKeyAtIndex或KeyAtIndexes这几个方法组合的形式调用。还有一个可选的getKey:range:方法。所以你想重新定义KVC的一些功能你可以添加这些方法需要注意的是你的方法名要符合KVC的标准命名方法包括方法签名。
如果上面的方法没有找到那么会同时查找countOfKeyenumeratorOfKey,memberOfKey格式的方法。如果这三个方法都找到那么就返回一个可以响应NSSet所的方法的代理集合和上面一样给这个代理集合发NSSet的消息就会以countOfKeyenumeratorOfKey,memberOfKey组合的形式调用。
如果还没有找到再检查类方法 (BOOL)accessInstanceVariablesDirectly,如果返回YES(默认行为)那么和先前的设值一样会按_key,_isKey,key,isKey的顺序搜索成员变量名。如果重写了类方法 (BOOL)accessInstanceVariablesDirectly返回NO的话那么会直接调用valueForUndefinedKey:
还没有找到的话调用valueForUndefinedKey:
KVC在实际应用中可以字典转模型如
let p Person(age: 20)
let dict [name:BBB,age:30,_name:_name] as [String : Any]p.setValuesForKeys(dict)
print(p.name)
print(p.age)
print(p._name)
运行结果 KVO
KVO意思是键值观察是基于KVC以及动态派发技术实现的它是观察者模式的一种衍生其思想是当被观察对象的某个属性发生变化时另一个类可以通过观察获取通知并做出处理。
KVO是对NSObject的扩展来实现的当使用KVO时需要继承NSObject并且观察属性需要添加objc dynamic标识如 class Person:NSObject{objc dynamic var name:String{set{_name newValueprint(name被赋值了)}get{print(name被访问了)return _name}}objc var age:Intinit(age: Int) {self.age age}objc var _name deinit {removeObserver(self, forKeyPath: name)}}
注意observer对资源消耗大建议在类销毁的时候移除观察者如上示例中的析构deinit()中.
接着我们定义一个ModelB类负责监听A类中的属性name如
class Model:NSObject{let p2 Person(age: 30)override init(){super.init()p2.addObserver(self as! NSObject, forKeyPath: name, options: .new, context: nil)}//响应回调事件的重写需要继承NSObjectoverride func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {print(22)if p2.name ! {print(p2s name is changed,is \(p2.name))}}}
注意你需要继承NSObject类从而对响应回调事件进行重写。
接着我们创建实例修改p2的name值
let model Model()
model.p2.name good
当p2.name值被修改后会调用响应事件运行结果如下 KVO在iOS实际开发中的举例
import UIKit
import Foundationclass Persons:NSObject {objc dynamic var name: String?init(name: String? nil) {self.name name}
}class ViewController: UIViewController {//实例化被观察对象var person Persons(name: Aliy)override func viewDidLoad() {super.viewDidLoad()self.view.backgroundColor .red//添加观察者self.person.addObserver(self, forKeyPath: name, options: .new, context: nil)//3s后执行被观察对象值的改变self.perform(#selector(ChangeName), with: nil, afterDelay: 3.0)}override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {if person.name ! {print(The new person is \(person.name!))self.view.backgroundColor . green}}}extension ViewController {objc func ChangeName(){person.name John}
}
这里注意ViewController不需要再去继承NSObject类因为它已经继承了UIViewController而Swift 中的 UIViewController 继承自 UIResponder而 UIResponder继承自 NSObject 类。