【非凡程序员】对KVC、KVO的学习翻译整理

在阅读博客时看到英文论述大概翻译如下

How Cocoa Bindings Work (via KVC and KVO)

2010年11月05

脚注

[1]现有的值也可以是原语等 BOOL int,因为现有的取值和赋值方法将执行自动装箱。例如,一个 BOOL值将被auto-boxed成一个NSNumber*.

[2]当我说绑定同步两个关键路径,这不是技术上正确的。它实际上要同步绑定和一个关键路径。绑定是一个字符串,就像一个关键路径但不保证现有的兼容,虽然它可以。请注意,该示例代码使用 @"address"但从未使用作为一个关键路径 @"value"作为一个关键路径。这是因为 @"value"是一个绑定,它可能不是一个有效的关键路径。

 

Cocoa绑定可能有点混乱,特别是新人。一旦你了解底层概念,绑定并不太难。在这篇文章中,我将解释背后的概念绑定的,首先解释了键值编码(现有的),然后观察(KVO)键值,最后说明可可绑定是建立在知识和KVO

键值编码(KVC)

第一个你需要了解的概念键值编码(KVC)KVO和绑定是建立其基础之上的。

对象有一定的属性。例如,一个 Person对象可能一个 name property和一个 address property。在KVC, Person对象有一个值 name, address键。“key”都是字符串,“value”可以是任何类型的对象[1]。在最基本的层面上,KVC只有两个方法:一个方法来改变这个值对于一个给定的键(mutator),和一个方法来检索值对于一个给定的键(访问)。这里有一个例子:

voidChangeName(Person*p,NSString*newName)

{

//using the KVC accessor (getter) method

NSString*originalName=[pvalueForKey:@"name"];

//using the KVC mutator (setter) method.

[psetValue:newNameforKey:@"name"];

NSLog(@"Changed %@'s name to: %@",originalName,newName);

}

现在让我们来看 Person对象有第三个key:一个 spouse键。 spouse键是另一个 Person对象的值。KVC可以让你进行这样的操作:

voidLogMarriage(Person*p)

{

//just using the accessor again, same as example above

NSString*personsName=[pvalueForKey:@"name"];

//this line is different, because it is using

//a "key path" instead of a normal "key"

NSString*spousesName=[pvalueForKeyPath:@"spouse.name"];

NSLog(@"%@ is happily married to %@",personsName,spousesName);

}

Cocoa“key”“KeyPath”有所区分。“key”允许您获取一个值在一个对象。一个“KeyPath”允许您链接多个键,用点隔开。例如,这个……

[pvalueForKeyPath:@"spouse.name"];

是完全相同的,因为这

[[pvalueForKey:@"spouse"]valueForKey:@"name"];

所有你需要知道的知识。

让我们继续KVO

-值观察(KVO)

-值观察(KVO)是建立在KVC上的。在对象值改变时,它允许您观察(观察)一个KVC key path对象值。例如,让我们写一些代码,手表,看看一个人的地址更改。有 三种方法对下面的代码:

  • watchPersonForChangeOfAddress:开始观察

  • observeValueForKeyPath:ofObject:change:context:(被用为:Key Path的特定对象的value每次观被观察改变??此处不明确具体称呼方式~~~~~~~

  • dealloc停止观察

static NSString*constKVO_CONTEXT_ADDRESS_CHANGED=@"KVO_CONTEXT_ADDRESS_CHANGED"

@implementationPersonWatcher

-(void)watchPersonForChangeOfAddress:(Person*)p;

{

//this begins the observing

[paddObserver:selfforKeyPath:@"address"options:0context:KVO_CONTEXT_ADDRESS_CHANGED];

//keep a record of all the people being observed,

//because we need to stop observing them in dealloc

[m_observedPeopleaddObject:p];}

//whenever an observed key path changes, this method will be called

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)objectchange:(NSDictionary*)changecontext:(void*)context;

{

//use the context to make sure this is a change in the address,

//because we may also be observing other things

 if(context==KVO_CONTEXT_ADDRESS_CHANGED)

{

NSString*name=[objectvalueForKey:@"name"];

NSString*address=[objectvalueForKey:@"address"];

NSLog(@"%@ has a new address: %@",name,address);

}

}

-(void)dealloc;

{

//must stop observing everything before this object is

//deallocated, otherwise it will cause crashes

for(Person*pinm_observedPeople)

{

[premoveObserver:selfforKeyPath:@"address"];

}

[m_observedPeoplerelease];

m_observedPeople=nil;[superdealloc];

}

-(id)init;

{

if(self=[superinit])

{

m_observedPeople=[NSMutableArraynew];

}

returnself;

}

@end

这是KVO所有。它允许你去观察一个key path在一个对象的值发生变化时得到通知。

Cocoa Bindings

现在你理解概念背后的KVCKVO, Cocoa Bindings不会太神秘了。

Cocoa Bindings允许你 synchronise  两个key paths [2]所以他们拥有相同的key 。当一个key paths更新,另一个也是如此。

例如,让我们假设你有一个 Person对象和一个 NSTextField编辑人的地址。我们知道,每一个 Person对象有一个 address,多亏了Cocoa Bindings Reference,我们也知道,每一个 NSTextField对象有 value键使用绑定。我们想要的是这两个key paths是同步的(即绑定)。这意味着,如果用户类型 NSTextField,它会自动更新地址 Person对象。另外,如果我们以编程方式更改的地址 Person对象,我们希望它会自动出现在 NSTextField。这可以这样实现:

voidBindTextFieldToPersonsAddress(NSTextField*tf,Person*p)

{

//This synchronises/binds these two together:

//The `value` key on the object `tf`

//The `address` key on the object `p`

[tfbind:@"value"toObject:pwithKeyPath:@"address"options:nil];

}

下面会发生什么是 NSTextField开始观察 address键在 Person通过KVO对象。如果地址的变化, Person对象,---NSTextField得到通知的改变,它将更新的新值。在这种情况下, NSTextField这类似于:

-(void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionary*)changecontext:(void*)context;

{

if(context==KVO_CONTEXT_VALUE_BINDING_CHANGED)

{

[selfsetStringValue:[objectvalueForKeyPath:keyPath]];

}

}

当用户开始输入 NSTextField, NSTextField使用现有的更新 Person对象。在这种情况下, NSTextField这类似于:

-(void)insertText:(id)aString;

{

NSString*newValue=[[selfstringValue]stringByAppendingString:aString];

[selfsetStringValue:newValue];

//if "value" is bound, then propagate the change to the bound object

if([selfinfoForBinding:@"value"])

{

idboundObj=...;//omitted for brevity

NSString*boundKeyPath=...;//omitted for brevity

[boundObjsetValue:newValueforKeyPath:boundKeyPath];

}

}

结论

这是KVC KVO和绑定工作的基本知识,。视图使用现有的更新模型,并使用KVO注意模型。我有了不少的细节为了保持文章简短,但是希望它给了你一个公司掌握的概念和原则。

你可能感兴趣的:(非凡程序员)