Ete*_*ack 13 key-value-observing ios swiftlint swift4 xcode9
我刚刚更新到Swift 4和Xcode 9并得到(swiftlint)警告,以下代码告诉我现在应该使用KVO:
警告:
(基于块的KVO违规:在使用Swift 3.2或更高版本时,首选基于新块的KVO API和键路径.(block_based_kvo))
旧代码:
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
if keyPath == "outputVolume"{
guard let newKey = change?[NSKeyValueChangeKey.newKey] as? NSNumber else {
fatalError("Could not unwrap optional content of new key")
}
let volume = newKey.floatValue
print("volume " + volume.description)
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试修复:
let audioSession = AVAudioSession.sharedInstance()
audioSession.observe(\.outputVolume) { (av, change) in
print("volume \(av.outputVolume)")
}
Run Code Online (Sandbox Code Playgroud)
Apple 在这里声称大多数属性应该是dynamic(我知道这是AVPlayer而不是AVAudioSession).我查了一下,但dynamic在AVPlayer属性中找不到任何声明,并想知道它是如何工作的(如果我没有弄错,那些是KVO工作所必需的).
编辑:
我不确定它是否不会触发,因为它根本不起作用或者是由于我尝试归档的原因.总的来说,我希望通过推动硬件音量摇杆来获得有关音量变化的通知.
Rob*_*ier 11
我假设你指的是这条线:
您可以使用键值观察(KVO)来观察许多玩家动态属性的状态变化......
这种"动态"的使用与Objective-C @dynamic或Swift的不同dynamic.文档只是意味着"在这种情况下改变的属性",并且它们告诉您AVPlayer通常非常符合KVO并且打算以这种方式观察."符合KVO"意味着它遵循更改通知规则.有很多方法可以实现这一点,包括自动和手动.文档只是承诺AVPlayer.
(关于Cocoa与C许多其他系统区分的一个重要观点是,Cocoa按照惯例处理了许多事情.在代码中没有办法说"这是符合KVO的"并且编译器没有办法强制执行它,但是Cocoa开发人员往往非常善于遵守规则.当ARC开发时,它在很大程度上依赖于Cocoa开发人员多年来根据非常具体的规则命名方法的事实,这些规则指示了如何处理内存管理.它只是增加了编译器的执行规则Cocoa开发人员总是随手操作.这就是Cocoa开发人员对命名约定和大小写非常嘈杂的原因.Cocoa的主要部分完全依赖于遵循一致的命名规则.)
记住AVPlayer接口是一个恰好被桥接到Swift的Objective-C API,dynamic在这种情况下没有相应的Swift关键字.这是一个关键字告诉Swift可以观察到这个属性,因此它的访问器不能优化为静态调度.这不是Objective-C所要求的(或者可以做到的;所有ObjC属性在这个意义上都是"动态的").
Objective-C @dynamic是一个完全不同的东西,只与KVO有很弱的相关性(虽然它出现在许多像KVO这样的重要环境中,比如Core Data).它只是意味着"即使你无法在任何地方找到这个属性的访问器实现,相信我,到运行时,实现将是可用的." 这依赖于ObjC的运行时动态生成实现或以程序员控制的方式调度的能力(这仍然存在于Swift中,通过操纵ObjC运行时,但它实际上不是"Swift"特性).
至于KVO是如何工作的,它是Cocoa中为数不多的真正"魔术"之一.有关快速介绍,请参阅键值观察实施详细信息.简短版本是:
willChangeValue...和didChangeValue...周围的超类的属性访问器的所有调用.编辑:原始问题从未提及它无法正常工作.它不起作用的原因是因为你没有NSKeyValueObservation在属性中分配返回的内容; 你只是扔掉它.我很惊讶没有关于此的警告; 我可以开雷达.
当返回的NSKeyValueObservation解除分配时,观察消失,因此这会产生观察并立即销毁它.您需要将其存储在属性中,直到您希望观察消失为止.
OP的解决方案。
它需要存储在属性中。不是变量,_而是属性。否则它不会工作。像这样:
class YourViewController: UIViewController {
var obs: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
let audioSession = AVAudioSession.sharedInstance()
self.obs = audioSession.observe( \.outputVolume ) { (av, change) in
print("volume \(av.outputVolume)")
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4766 次 |
| 最近记录: |