- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我无法让KVO处理在Cocoa应用程序中绑定在一起的文本字段。当使用按钮在NSTextFields中设置字符串时,我已经使用了它,但是它不适用于绑定。与往常一样,非常感谢Stack Overflow提供的任何帮助。
我的代码的目的是:
将几个文本字段绑定在一起
当在一个字段中输入数字时,让其他字段自动更新
观察文本字段中的更改
这是我的MainClass代码,它是一个NSObject子类:
#import "MainClass.h"
@interface MainClass ()
@property (weak) IBOutlet NSTextField *fieldA;
@property (weak) IBOutlet NSTextField *fieldB;
@property (weak) IBOutlet NSTextField *fieldC;
@property double numA, numB, numC;
@end
@implementation MainClass
static int MainClassKVOContext = 0;
- (void)awakeFromNib {
[self.fieldA addObserver:self forKeyPath:@"numA" options:0 context:&MainClassKVOContext];
[self.fieldB addObserver:self forKeyPath:@"numB" options:0 context:&MainClassKVOContext];
[self.fieldC addObserver:self forKeyPath:@"numC" options:0 context:&MainClassKVOContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context != &MainClassKVOContext) {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
return;
}
if (object == self.fieldA) {
if ([keyPath isEqualToString:@"numA"]) {
NSLog(@"fieldA length = %ld", [_fieldA.stringValue length]);
}
}
if (object == self.fieldB) {
if ([keyPath isEqualToString:@"numB"]) {
NSLog(@"fieldB length = %ld", [_fieldB.stringValue length]);
}
}
if (object == self.fieldC) {
if ([keyPath isEqualToString:@"numC"]) {
NSLog(@"fieldC length = %ld", [_fieldC.stringValue length]);
}
}
}
+ (NSSet *)keyPathsForValuesAffectingNumB {
return [NSSet setWithObject:@"numA"];
}
+ (NSSet *)keyPathsForValuesAffectingNumC {
return [NSSet setWithObject:@"numA"];
}
- (void)setNumB:(double)theNumB {
[self setNumA:theNumB * 1000];
}
- (double)numB {
return [self numA] / 1000;
}
- (void)setNumC:(double)theNumC {
[self setNumA:theNumC * 1000000];
}
- (double)numC {
return [self numA] / 1000000;
}
- (void)setNilValueForKey:(NSString*)key {
if ([key isEqualToString:@"numA"]) return [self setNumA: 0];
if ([key isEqualToString:@"numB"]) return [self setNumB: 0];
if ([key isEqualToString:@"numC"]) return [self setNumC: 0];
[super setNilValueForKey:key];
}
@end
最佳答案
在NSTextField上观察键值
在-awakeFromNib
方法的实现中,您已经编写了
[self.fieldA addObserver:self
forKeyPath:@"numA"
options:0
context:&MainClassKVOContext];
self.fieldA
的
numA
不是
key-value coding compliant:如果尝试将键为
-valueForKey:
的
-setValue:forKey:
或
@"numA"
发送到
self.fieldA
,您将获得以下例外:
NSTextField
实例也不符合
@"numA"
的键值观察标准:某些键的KVO兼容的第一要求是该键的KVC兼容。
stringValue
外还符合KVO。这使您可以执行
what I described earlier。
NSTextField
上调用
@"stringValue"
时,观察
-setStringValue:
的值是可行的。这是KVO内部的结果。
NSTextField
指针也将更改。您可以通过覆盖
isa
看到这种情况
- (void)addObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
{
NSLog(@"%p, %@", self->isa, NSStringFromClass(self->isa));
[super addObserver:observer
forKeyPath:keyPath
options:options
context:context];
NSLog(@"%p, %@", self->isa, NSStringFromClass(self->isa));
}
-addObserver:forKeyPath:options:context:
更改为
Object
。
NSKVONotifying_Object
的
-addObserver:forKeyPath:options:context:
实例上调用了
Object
-一个
@"property"
实例符合KVC的键-下次我们在
Object
实例上调用
-setProperty:
Object
(实际上,现在是
NSKVONotifying_Object
的实例),以下消息将发送到该对象
-willChangeValueForKey:
通过
@"property"
-setProperty:
通过
@"property"
-didChangeValueForKey:
通过
@"property"
_NSSetObjectValueAndNotify
中调用的。
-observeValueForKeyPath:ofObject:change:context:
实例的观察者中调用了
Object
方法,以获取来自
@"property"
的关键路径
-didChangeValueForKey:
。这是堆栈跟踪的顶部:
-[Observer observeValueForKeyPath:ofObject:change:context:]
NSKeyValueNotifyObserver ()
NSKeyValueDidChange ()
-[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] ()
NSTextField
和
@"stringValue"
有何关系?
-awakeFromNib
上的文本字段添加观察者。这意味着您的文本字段已经是
NSKVONotifying_NSTextField
的实例。
-setStringValue
。之所以能够观察到此更改,是因为-作为
NSKVONotifying_NSTextField
的实例-您的文本字段在收到
setStringValue:value
后实际上已收到
willChangeValueForKey:@"stringValue"
setStringValue:value
didChangeValueForKey:@"stringValue"
didChangeValueForKey:@"stringValue"
内,所有正在观察
@"stringValue"
的文本字段值的对象都被通知此键的值在其自己的
-observeValueForKeyPath:ofObject:change:context:
实现中已更改。特别是对于您添加为
-awakeFromNib
文本字段的观察者的对象而言,这是正确的。
@"stringValue"
的文本字段值的变化,因为您将自己添加为该键的文本字段的观察者,并且因为在文本字段上调用了
-setStringValue
。
NSTextField
上调用
@"stringValue"
时,观察
-setStringValue:
的值是可行的。
NSTextField
时,甚至在用户结束编辑之后(例如,通过跳出文本字段),都不会在文本字段上调用
-setStringValue:
。 (此外,不是手动调用
-willChangeValueForKey:
和
-didChangeValueForKey:
。如果是,则我们的KVO可以工作;但是不能。)这意味着,当
@"stringValue"
上的
-setStringValue:
被调用时,我们在
@"stringValue"
上的KVO可以工作。文本字段,当用户自己输入文本时它不起作用。
NSTextField
的
WindowController
上的KVO不够好,因为它不适用于用户输入。
WindowController.m
)创建示例项目。 (
Here's the project I'm starting from on GitHub.)在
stringA
中的类扩展中添加了属性
WindowController
:
@interface WindowController ()
@property (nonatomic) NSString *stringA;
@end
WindowController
实例。因此,请选择“文件的所有者”。发生这种情况时,“ Controller Key”字段将被清空,而“ Model Key Path”字段将变为“ self”。
stringA
实例的属性
self.stringA
,因此将“模型键路径”更改为
WindowController
:
stringA
的属性
stringA
。
stringA
设置为某个值,则当窗口加载时,该值将显示在文本字段中:
- (id)init
{
self = [super initWithWindowNibName:@"WindowController"];
if (self) {
self.stringA = @"hello world";
}
return self;
}
NSTextField
。我们可以通过覆盖它的设置器来检查它:
- (void)setStringA:(NSString *)stringA
{
NSLog(@"%s: stringA: <<%@>> => <<%@>>", __PRETTY_FUNCTION__, _stringA, stringA);
_stringA = stringA;
}
-[WindowController setStringA:]: stringA: <<(null)>> => <<some text>>
NSTextField
指出
NSContinuouslyUpdatesValueBindingOption
可用的一个绑定选项是
stringA
。瞧,在Bindings Inspector中,有一个复选框与此NSTextField的值相对应。继续并选中该框。
NSTextField
属性的更新:
-[WindowController setStringA:]: stringA: <<(null)>> => <<t>>
-[WindowController setStringA:]: stringA: <<t>> => <<th>>
-[WindowController setStringA:]: stringA: <<th>> => <<thi>>
-[WindowController setStringA:]: stringA: <<thi>> => <<thin>>
-[WindowController setStringA:]: stringA: <<thin>> => <<thing>>
-[WindowController setStringA:]: stringA: <<thing>> => <<things>>
-[WindowController setStringA:]: stringA: <<things>> => <<things >>
-[WindowController setStringA:]: stringA: <<things >> => <<things i>>
-[WindowController setStringA:]: stringA: <<things i>> => <<things in>>
stringA
!
Here's the project with three synchronized text fields.
WindowController
中删除属性
numberA
并将其替换为
numberB
,
numberC
和
quantity
:
@interface WindowController ()
@property (nonatomic) NSNumber *numberA;
@property (nonatomic) NSNumber *numberB;
@property (nonatomic) NSNumber *numberC;
@end
quantity
。
@interface WindowController ()
@property (nonatomic) NSNumber *quantity;
@property (nonatomic) NSNumber *numberA;
@property (nonatomic) NSNumber *numberB;
@property (nonatomic) NSNumber *numberC;
@end
numberA
的单位转换为
quantity
的单位,依此类推,因此添加
static float convertToA = 1000.0f;
static float convertToB = 573.0f;
static float convertToC = 720.0f;
- (NSNumber *)numberA
{
return [NSNumber numberWithFloat:self.quantity.floatValue * convertToA];
}
- (void)setNumberA:(NSNumber *)numberA
{
self.quantity = [NSNumber numberWithFloat:numberA.floatValue * 1.0f/convertToA];
}
- (NSNumber *)numberB
{
return [NSNumber numberWithFloat:self.quantity.floatValue * convertToB];
}
- (void)setNumberB:(NSNumber *)numberB
{
self.quantity = [NSNumber numberWithFloat:numberB.floatValue * 1.0f/convertToB];
}
- (NSNumber *)numberC
{
return [NSNumber numberWithFloat:self.quantity.floatValue * convertToC];
}
- (void)setNumberC:(NSNumber *)numberC
{
self.quantity = [NSNumber numberWithFloat:numberC.floatValue * 1.0f/convertToC];
}
quantity
的间接机制,非常适合于绑定。剩下要做的只有一件事:只要更改
+ (NSSet *)keyPathsForValuesAffectingNumberA
{
return [NSSet setWithObject:@"quantity"];
}
+ (NSSet *)keyPathsForValuesAffectingNumberB
{
return [NSSet setWithObject:@"quantity"];
}
+ (NSSet *)keyPathsForValuesAffectingNumberC
{
return [NSSet setWithObject:@"quantity"];
}
关于objective-c - 将KVO用于绑定(bind)在一起的NSTextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13170217/
我有一个 foo 类,它有一个 bar 方法,它接受可调用的东西(函数指针/仿函数)。这个可调用的东西应该作为绑定(bind)元素传递给另一个方法 doit 和第三个方法 bar_cb 方法。 #in
我正在尝试在我的 WPF 4.0 应用程序(使用 VS 2010 Pro RTM)中创建自定义 TabItem 模板/样式,但尽管一切似乎都正常工作,但我注意到跟踪窗口中存在绑定(bind)错误。 我
作为一名刚接触 Android 的开发人员,我想我可能误解了绑定(bind)服务。 我创建了一项服务来结束对服务器的访问。作为此服务的一部分,该服务正在监听多播地址,以识别本地网络上的设备何时出现和消
这个问题在这里已经有了答案: What is the use of the JavaScript 'bind' method? (23 个回答) 关闭 7 年前。 所以我一直在尝试了解一些 JS 上
我不明白这三种语法之间的区别: where a = f (b) do a <- f (b) do let a = f (b) 我确实明白了a <- f(b)与其他两个不同,在大多数情况下,我尝试了所有
我在将 Cocoa 项目从手动同步接口(interface)模型转换为绑定(bind)模型时遇到问题,这样我就不必担心接口(interface)粘合代码。 我关注了 CocoaDevCentral C
我正在尝试找出一种好的方法来对处理大数据集的代码进行并行化,然后将结果数据导入 RavenDb。 数据处理受 CPU 限制和数据库导入 IO 限制。 我正在寻找一种解决方案,以对 Environmen
我正在 foreach 循环中生成单选按钮。我试图将选中的属性绑定(bind)到父级中的基本可观察值。不幸的是,当单击单选按钮时,父级的属性似乎没有在单击处理程序中更新。 基于一些previous w
在我的 Windows Phone 应用程序中,我有两个 LongListSelectors并排在页面上。我想做到这一点,以便当用户滚动其中一个时,另一个滚动相同的量。 两个 LongListSele
我在网上看到这个问题准备面试: Given a non-preemptive kernel which type of process will get affected morein terms o
我有一个 foreach 绑定(bind),如下所示: Summary Permitting 原因是有两个选项卡始终存在,并且我根据是否添加了其他选项卡来添加其他选项
任何人都有绑定(bind)相同的情况DataContext到 TextBlock 中的 Text 属性(例如)。 我必须分配 DataContext以我的风格反射(reflect)基于 Datacon
给定以下代码: Login 和下面的javascript $(function () { $('#btnLogin').click(function () { co
我使用 boost::asio 创建了一个服务器。我在绑定(bind)到端点时遇到问题。所以,如果我在构造函数中初始化一个接受器: Server::Server(QWidget *parent) :
我正在将现有项目从 MySQL 转换为 Postgres。代码中有相当多的原始 SQL 文字使用 ? 作为占位符,例如 SELECT id FROM users WHERE
似乎在绑定(bind)某些数据时出错了,有人可以帮我解决我哪里出错了,尽管我无法弄清楚。 真的不需要在这里显示太多,这是 Binding,我已经通过移除背景并在其中放置颜色来测试背景,效果很好。 编辑
我正在尝试使用 wcf 构建一个 http 监听器(web 服务)。这个监听器是一个更大的桌面应用程序的一部分。此桌面应用程序还会调用 http 监听器。 当监听器接收到数据时,它应该被传递到桌面应用
嘿嘿。 我正在使用 Node.JS 和 child_process 来生成 bash 进程。我试图了解我是否正在执行 I/O 绑定(bind)、CPU 绑定(bind)或两者兼而有之。 我正在使用 p
尝试执行以下操作并出现“Got interpolation ({{}}) where expression was expected”错误。 {{item.name}} 谢谢!
我有一个导入的 Java 库,它是我解决方案中的“绑定(bind)库”项目。 我正在尝试从解决方案中的另一个项目绑定(bind)到第 3 方库中的服务。 第 3 方库文档 [在 java 中] 非常简
我是一名优秀的程序员,十分优秀!