青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 42  文章 - 3  trackbacks - 0
<2012年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用鏈接

留言簿(2)

隨筆檔案

文章檔案

網(wǎng)頁收藏

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

How Cocoa Bindings Work (via KVC and KVO)

Cocoa bindings can be a little confusing, especially to newcomers. Once you have an understanding of the underlying concepts, bindings aren’t too hard. In this article, I’m going to explain the concepts behind bindings from the ground up; first explaining Key-Value Coding (KVC), then Key-Value Observing (KVO), and finally explaining how Cocoa bindings are built on top of KVC and KVO.

 

Key-Value Coding (KVC)

The first concept you need to understand is Key-Value Coding (KVC), as KVO and bindings are built on top of it.

 

Objects have certain "properties". For example, a Person object may have an name property and an address property. In KVC parlance, the Person object has a value for the name key, and for the address key. "Keys" are just strings, and "values" can be any type of object[1]. At it’s most fundamental level, KVC is just two methods: a method to change the value for a given key (mutator), and a method to retrieve the value for a given key (accessor). Here is an example:

 

void ChangeName(Person* p, NSString* newName)

{

    //using the KVC accessor (getter) method

    NSString* originalName = [p valueForKey:@"name"];

 

    //using the KVC mutator (setter) method.

    [p setValue:newName forKey:@"name"];

 

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

}

Now let’s say the Person object has a third key: a spouse key. The value for the spouse key is another Person object. KVC allows you to do things like this:

 

void LogMarriage(Person* p)

{

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

    NSString* personsName = [p valueForKey:@"name"];

 

    //this line is different, because it is using

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

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

 

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

}

Cocoa makes a distinction between "keys" and "key paths". A "key" allows you to get a value on an object. A "key path" allows you to chain multiple keys together, separated by dots. For example, this…

 

[p valueForKeyPath:@"spouse.name"];

is exactly the same as this…

 

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

That’s all you need to know about KVC for now.

 

Let’s move on to KVO.

 

Key-Value Observing (KVO)

Key-Value Observing (KVO) is built on top of KVC. It allows you to observe (i.e. watch) a KVC key path on an object to see when the value changes. For example, let’s write some code that watches to see if a person’s address changes. There are three methods of interest in the following code:

 

watchPersonForChangeOfAddress: begins the observing

observeValueForKeyPath:ofObject:change:context: is called every time there is a change in the value of the observed key path

dealloc stops the observing

static NSString* const KVO_CONTEXT_ADDRESS_CHANGED = @"KVO_CONTEXT_ADDRESS_CHANGED"

 

@implementation PersonWatcher

 

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

{

    //this begins the observing

    [p addObserver:self

        forKeyPath:@"address"

           options:0

           context:KVO_CONTEXT_ADDRESS_CHANGED];

 

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

    //because we need to stop observing them in dealloc

    [m_observedPeople addObject:p];

}

 

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

- (void)observeValueForKeyPath:(NSString *)keyPath

                      ofObject:(id)object

                        change:(NSDictionary *)change

                       context:(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 = [object valueForKey:@"name"];

        NSString* address = [object valueForKey:@"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* p in m_observedPeople){

        [p removeObserver:self forKeyPath:@"address"];

    }

    [m_observedPeople release]; m_observedPeople = nil;

    [super dealloc];

}

 

-(id) init;

{

    if(self = [super init]){

        m_observedPeople = [NSMutableArray new];

    }

    return self;

}

 

@end

This is all that KVO does. It allows you to observe a key path on an object to get notified whenever the value changes.

 

Cocoa Bindings

Now that you understand the concepts behind KVC and KVO, Cocoa bindings won’t be too mysterious.

 

Cocoa bindings allow you to synchronise two key paths[2] so they have the same value. When one key path is updated, so is the other one.

 

For example, let’s say you have a Person object and an NSTextField to edit the person’s address. We know that every Person object has an address key, and thanks to the Cocoa Bindings Reference, we also know that every NSTextField object has a value key that works with bindings. What we want is for those two key paths to be synchronised (i.e. bound). This means that if the user types in the NSTextField, it automatically updates the address on the Person object. Also, if we programmatically change the the address of the Person object, we want it to automatically appear in the NSTextField. This can be achieved like so:

 

void BindTextFieldToPersonsAddress(NSTextField* tf, Person* p)

{

    //This synchronises/binds these two together:

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

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

    [tf bind:@"value" toObject:p withKeyPath:@"address" options:nil];

}

What happens under the hood is that the NSTextField starts observing the address key on the Person object via KVO. If the address changes on the Person object, the NSTextField gets notified of this change, and it will update itself with the new value. In this situation, the NSTextField does something similar to this:

 

- (void)observeValueForKeyPath:(NSString *)keyPath

                      ofObject:(id)object

                        change:(NSDictionary *)change

                       context:(void *)context;

{

    if(context == KVO_CONTEXT_VALUE_BINDING_CHANGED){

        [self setStringValue:[object valueForKeyPath:keyPath]];

    }       

}

When the user starts typing into the NSTextField, the NSTextField uses KVC to update the Person object. In this situation, the NSTextField does something similar to this:

 

- (void)insertText:(id)aString;

{

    NSString* newValue = [[self stringValue] stringByAppendingString:aString];

    [self setStringValue:newValue];

 

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

    if([self infoForBinding:@"value"]){

        id boundObj = ...; //omitted for brevity

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

        [boundObj setValue:newValue forKeyPath:boundKeyPath];

    }

}

For a more complete look at how views propagate changes back to the bound object, see my article: Implementing Your Own Cocoa Bindings.

 

Conclusion

That’s that basics of how KVC, KVO and bindings work. The views use KVC to update the model, and they use KVO to watch for changes in the model. I have left out quite a bit of detail in order to keep the article short and simple, but hopefully it has given you a firm grasp of the concepts and principles.

 

Footnotes

[1] KVC values can also be primitives such as BOOL or int, because the KVC accessor and mutator methods will perform auto-boxing. For example, a BOOL value will be auto-boxed into an NSNumber*.

[2] When I say that bindings synchronise two key paths, that’s not technically correct. It actually synchronises a "binding" and a key path. A "binding" is a string just like a key path but it’s not guaranteed to be KVC compatible, although it can be. Notice that the example code uses @"address" as a key path but never uses @"value" as a key path. This is because @"value" is a binding, and it might not be a valid key path.

 

posted on 2012-07-16 16:27 鷹擊長空 閱讀(311) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一级播放| 久久亚洲精品欧美| 国产精品视频一二三| 亚洲欧美欧美一区二区三区| 亚洲女同同性videoxma| 国产欧美视频在线观看| 久久久久久有精品国产| 免费欧美电影| 亚洲欧美电影在线观看| 久久国产精品高清| 亚洲黄色免费网站| 中国女人久久久| 在线观看不卡av| 99视频热这里只有精品免费| 国产欧美另类| 亚洲国产一区视频| 国产精品私人影院| 欧美激情精品久久久久| 欧美性一区二区| 蜜桃av一区二区三区| 欧美日韩网址| 美女亚洲精品| 国产精品老女人精品视频| 免费欧美日韩| 国产目拍亚洲精品99久久精品| 欧美成人精品一区| 欧美午夜免费电影| 欧美电影免费观看| 国产欧美一级| 日韩一级黄色av| 1769国产精品| 欧美一级免费视频| 亚洲系列中文字幕| 麻豆成人在线观看| 久久久久久久久久码影片| 欧美三区免费完整视频在线观看| 久久性天堂网| 国产乱子伦一区二区三区国色天香| 欧美激情视频给我| 国产尤物精品| 亚洲一区二区三区四区中文| 日韩一区二区精品视频| 久久久久欧美| 久久视频在线免费观看| 国产欧美精品在线观看| 亚洲天堂免费观看| 亚洲深夜激情| 欧美日本一道本在线视频| 亚洲第一视频| 亚洲精品黄网在线观看| 久久天天躁夜夜躁狠狠躁2022| 欧美中文字幕精品| 国产女人水真多18毛片18精品视频| 99综合精品| 一区二区三区视频在线| 欧美精品一区视频| 亚洲精品色婷婷福利天堂| 日韩午夜一区| 欧美片第一页| aa级大片欧美三级| 亚洲欧美日韩国产中文在线| 国产精品igao视频网网址不卡日韩| 亚洲精品综合久久中文字幕| 亚洲精品一区二区三区在线观看| 麻豆91精品91久久久的内涵| 欧美激情第六页| 日韩系列在线| 国产精品xxx在线观看www| 亚洲午夜视频在线观看| 性色av香蕉一区二区| 国产亚洲网站| 久久香蕉国产线看观看av| 欧美激情精品久久久六区热门| 最新亚洲激情| 欧美三日本三级少妇三99| 一区二区三区色| 久久精品亚洲精品| 在线欧美视频| 欧美剧在线免费观看网站| 中文日韩在线视频| 久久三级视频| 亚洲精品乱码久久久久久按摩观| 欧美日韩国产123| 亚洲性xxxx| 免费久久99精品国产自在现线| 亚洲日本中文字幕| 国产精品第三页| 久久久九九九九| 亚洲片国产一区一级在线观看| 亚洲午夜久久久久久久久电影院| 国产精品日韩欧美一区二区| 久久精品视频在线看| 亚洲人www| 久久精品青青大伊人av| 亚洲精品美女在线| 国产亚洲精品成人av久久ww| 麻豆精品在线观看| 午夜天堂精品久久久久| 欧美国产综合| 香蕉尹人综合在线观看| 亚洲黄色在线| 久久婷婷丁香| 亚洲主播在线| 亚洲国产高清aⅴ视频| 欧美午夜精品一区二区三区| 久久亚洲美女| 亚洲在线日韩| 亚洲精选大片| 免费视频久久| 久久精品99无色码中文字幕 | 一区二区三区视频在线观看| 国产亚洲精品综合一区91| 欧美国产日韩精品免费观看| 久久国产福利| 亚洲一区精品视频| 亚洲精选在线观看| 欧美韩国日本一区| 久久久久国产免费免费| 亚洲主播在线| 一区二区三区日韩精品| 亚洲美洲欧洲综合国产一区| 韩国av一区二区| 国产视频在线观看一区二区| 国产精品久久久久av免费| 欧美国产视频在线观看| 女人香蕉久久**毛片精品| 久久精品国产清高在天天线| 先锋影音国产精品| 亚洲在线一区二区三区| 一区二区三区欧美在线| 日韩一级不卡| av不卡在线| 一区二区日本视频| 在线亚洲成人| 亚洲专区欧美专区| 亚洲主播在线播放| 亚洲男人天堂2024| 午夜视频久久久久久| 欧美亚洲综合在线| 久久精品99国产精品| 久久久91精品国产| 久久全球大尺度高清视频| 久久久国产一区二区| 久久黄色小说| 免费视频一区| 欧美精品手机在线| 欧美午夜一区| 国产精品永久免费视频| 国产欧美亚洲日本| 在线不卡中文字幕| 欧美在线视频导航| 久久久www成人免费毛片麻豆| 久久久久久穴| 欧美3dxxxxhd| 欧美三级乱码| 国产区精品视频| 伊人成年综合电影网| 亚洲欧洲另类国产综合| 一个色综合av| 久久精品欧美| 亚洲成人中文| 中文高清一区| 久久久青草婷婷精品综合日韩| 免费日本视频一区| 欧美亚州韩日在线看免费版国语版| 国产精品欧美久久| 136国产福利精品导航网址| 99综合在线| 久久精品九九| 亚洲国产综合在线| 午夜久久久久久| 欧美大胆a视频| 国产精品网站在线| 亚洲激情一区| 午夜精品久久| 亚洲第一区色| 欧美在线|欧美| 欧美日韩免费观看一区三区| 国产日韩在线播放| 久久综合中文色婷婷| 欧美日韩在线一区| 一区二区亚洲欧洲国产日韩| 亚洲小说欧美另类社区| 久久综合中文色婷婷| 亚洲午夜激情| 欧美激情一二区| 影音先锋日韩精品| 欧美亚洲综合网| 亚洲精品少妇网址| 久久天天狠狠| 国内精品久久久久影院薰衣草| 亚洲视频在线视频| 亚洲第一偷拍| 久久精品免费看| 国产精品日韩欧美| 亚洲视频在线二区| 亚洲激情校园春色| 蜜臀av一级做a爰片久久| 国内成+人亚洲| 午夜精品国产|