我有一个myName在我班上命名的房产,如:
@property (nonatomic, strong) NSString *myName;
Run Code Online (Sandbox Code Playgroud)
当myName属性的值发生变化时,我需要发送通知.
现在我做的事情如下:
- (void)setMyName:(NSString *)name
{
_myName = name;
[[NSNotificationCenter defaultCenter] postNotificationName:CHANGE_NOTIFICATION object:nil];
}
Run Code Online (Sandbox Code Playgroud)
我知道在iOS中有类似Key-Value Observing的东西.但我不知道如何实现它,我阅读了整个文档,但无法得到很好的理解.
请帮助我了解如何在不使用自定义setter的情况下实现相同的功能.
我已经阅读了很多关于KVO的文档,但我仍然对何时使用它感到困惑.
如果objA想监视某个属性objB,如下:
self.objB = [[ObjB alloc] init];
[self.objB addObserver:self
forKeyPath:@"address"
options:0
context:nil];
Run Code Online (Sandbox Code Playgroud)
所以,如果objB属性发生变化,并且只能更改self,为什么不这样做:
self.objB.property = @"newValue";
[self doSomethingBasedOnNewValueOfObjBnewProperty];
Run Code Online (Sandbox Code Playgroud)
代替
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if(keyPath == @"address") {
[self doSomethingBasedOnNewValueOfObjBnewProperty];
}
}
Run Code Online (Sandbox Code Playgroud)
当与单例一起使用时可能很有用,例如self.objB = [ObjB sharedInstance],其中属性可能被其他对象更改.这是唯一的用例吗?
似乎UIView没有像" didRemoveFromSuperview"或" willRemoveFromSuperview" 那样的方法.那么,当UIView从superView中删除时,如何监听事件?我应该使用KVO吗?提前致谢!
我的应用程序类A和类B中有两个类.A类和B类都是UIViewController的实例.A类有一个按钮,推送时将B类推入堆栈.B类有一个A类想要观察的字符串,并根据需要更新它的接口.我已经能够使用:
[self addObserver:self forKeyPath:@"name" options:0 context:NULL];在B类中查看对字符串的更改.当我尝试在A类viewWillAppear方法中使用以下内容时:
ClassB *b = [[ClassB alloc]init];
[b addObserver:self forKeyPath:@"name" options:0 context:NULL];
Run Code Online (Sandbox Code Playgroud)
并添加方法:
(void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object
change:(NSDictionary )change
context:(void )context
Run Code Online (Sandbox Code Playgroud)
尝试从A中查看B中所做的更新时没有触发任何操作.我觉得这个问题很傻但是KVO如何在iOS中的两个类之间工作?我知道这应该有效.
NSProxy对于那些尚不存在的对象来说,它们看起来效果非常好.例如.
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.target methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.target];
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将透明地将任何方法调用传递给代理所代表的目标.但是,它似乎没有处理目标上的KVO观察和通知.我试图使用一个NSProxy子类代表要传递给的对象NSTableView,但我收到以下错误.
Cannot update for observer <NSAutounbinderObservance 0x105889dd0> for
the key path "objectValue.status" from <NSTableCellView 0x105886a80>,
most likely because the value for the key "objectValue" has changed
without an appropriate KVO notification being sent. Check the
KVO-compliance of the NSTableCellView class.
Run Code Online (Sandbox Code Playgroud)
有没有办法让透明NSProxy符合KVO标准?
我在我的应用程序中遇到随机崩溃(我无法在我拥有的设备上重现),例外情况:
无法从AVPlayerLayer 0xaddress中删除关键路径"readyForDisplay"的观察者Foundation.NSKeyValueObservation 0xaddress,因为它未注册为观察者.
当我释放包含AVPlayerLayer的UIView时会发生这种情况.
我的初学者:
private var playerLayer : AVPlayerLayer { return self.layer as! AVPlayerLayer }
init(withURL url : URL) {
...
self.asset = AVURLAsset(url: url)
self.playerItem = AVPlayerItem(asset: self.asset)
self.avPlayer = AVPlayer(playerItem: self.playerItem)
super.init(frame: .zero)
...
let avPlayerLayerIsReadyForDisplayObs = self.playerLayer.observe(\AVPlayerLayer.isReadyForDisplay, options: [.new]) { [weak self] (plLayer, change) in ... }
self.kvoPlayerObservers = [..., avPlayerLayerIsReadyForDisplayObs, ...]
...
}
Run Code Online (Sandbox Code Playgroud)
我的deinit抛出异常:
deinit {
self.kvoPlayerObservers.forEach { $0.invalidate() }
...
NotificationCenter.default.removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)
根据Crashlytics的说法,它发生在不同iPhone上的iOS 11.4.1上.
导致的代码deinit非常简单:
// Some UIViewController context.
self.viewWithAVLayer?.removeFromSuperview()
self.viewWithAVLayer …Run Code Online (Sandbox Code Playgroud) 我想知道这个方法的参数会返回什么.
- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context;
Run Code Online (Sandbox Code Playgroud)
在文档中说
keyPath相对于对象的键路径,已更改的值.
object key path keyPath的源对象.
change一个字典,描述对关键路径keyPath的属性值所做的更改相对于object.
context注册接收器以接收键值观察通知时提供的值.
您能否为我解释这些参数,因为我发现文档有点难以理解.
我试图得到一些非常类似于WWV 2017基金会谈论KVO观察的例子.我看到的唯一不同于那次谈话的差异是,我不得不调用super.init(),我不得不隐藏地解开"kvo"令牌.
以下用于游乐场:
struct Node {
let title: String
let leaf: Bool
var children: [String: Node] = [:]
}
let t = Node(title:"hello", leaf:false, children:[:])
let k1 = \Node.leaf
let k2 = \Node.children
t[keyPath: k1] // returns "false" works
t[keyPath: k2] // returns "[:]" works
@objcMembers class MyController : NSObject {
dynamic var tr: Node
var kvo : NSKeyValueObservation!
init(t: Node) {
tr = t
super.init()
kvo = observe(\.tr) { object, change in
print("\(object) \(change)")
}
}
}
let x …Run Code Online (Sandbox Code Playgroud) 我刚刚更新到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工作所必需的).
编辑:
我不确定它是否不会触发,因为它根本不起作用或者是由于我尝试归档的原因.总的来说,我希望通过推动硬件音量摇杆来获得有关音量变化的通知.
当视图中的内容发生变化时,如何在失去焦点后自动处理从特定POI的"点击到焦点"切换回"自动对焦"状态?如果您注意到相机应用程序或UIImagePickerController中的焦点行为,在您点击一些区域并移动手机后,相机可以自动切换到屏幕中央的连续自动对焦.
我需要比UIImagePickerController可以提供的更多的灵活性,所以我需要首先使用AVFoundation来模仿UIImagePickerController行为......
ios ×6
objective-c ×4
cocoa ×2
iphone ×2
swift ×2
autofocus ×1
avfoundation ×1
camera ×1
nsproxy ×1
parameters ×1
properties ×1
swift4 ×1
swiftlint ×1
uiview ×1
xcode9 ×1