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

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

常用鏈接

留言簿(2)

隨筆檔案

文章檔案

網頁收藏

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

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>
            欧美午夜不卡影院在线观看完整版免费| 久久国产一区| 欧美日韩一区二区在线视频| 99视频+国产日韩欧美| 亚洲精品在线视频观看| 欧美日韩在线观看视频| 亚洲综合日韩| 欧美中文在线字幕| 最新国产乱人伦偷精品免费网站| 亚洲国产精品va在线看黑人| 欧美精品情趣视频| 亚洲欧美综合v| 久久综合狠狠综合久久综合88| 亚洲九九精品| 亚洲一区在线观看视频| 在线欧美小视频| 99riav1国产精品视频| 国产免费亚洲高清| 亚洲电影在线| 国产精品视频yy9299一区| 久久午夜激情| 欧美日韩免费观看一区三区| 久久久不卡网国产精品一区| 欧美国产日韩一区| 欧美在线网站| 欧美全黄视频| 美女主播视频一区| 国产精品激情电影| 免费不卡中文字幕视频| 欧美日韩在线三区| 欧美.www| 国产一区二区三区四区三区四| 亚洲精品久久嫩草网站秘色| 国产亚洲精品久久久久婷婷瑜伽| 亚洲国产精品成人综合| 国产偷国产偷亚洲高清97cao| 亚洲精品黄色| 亚洲夫妻自拍| 欧美伊人精品成人久久综合97| 中日韩美女免费视频网站在线观看| 久久久精品国产99久久精品芒果| 亚洲免费在线看| 欧美精品乱人伦久久久久久| 欧美69wwwcom| 激情综合亚洲| 欧美在线不卡视频| 欧美在线关看| 国产乱码精品| 亚洲一区二区欧美| 一区二区三区国产在线观看| 欧美mv日韩mv国产网站| 欧美成人首页| 亚洲国产合集| 欧美 日韩 国产 一区| 久久精品av麻豆的观看方式| 国产精品高清网站| 一区二区久久久久久| 99热免费精品| 欧美日韩999| 亚洲精品老司机| 一区二区电影免费观看| 欧美精品成人一区二区在线观看| 欧美成人综合网站| 亚洲国产视频a| 麻豆精品在线播放| 亚洲国产日韩欧美| 亚洲免费电影在线观看| 欧美精品性视频| 999亚洲国产精| 欧美亚洲三区| 国产一区二区三区久久精品| 欧美一进一出视频| 久热精品视频在线观看| 亚洲国产福利在线| 欧美搞黄网站| 一区二区三区欧美在线| 亚洲男女毛片无遮挡| 国产精品一区二区三区久久| 亚洲尤物影院| 久久在线精品| 亚洲欧洲日本国产| 欧美日本亚洲视频| 亚洲视屏一区| 另类av一区二区| 日韩午夜免费视频| 国产精品乱码一区二三区小蝌蚪| 亚洲欧美激情在线视频| 老色批av在线精品| 一区二区三区精品在线| 国产日韩欧美另类| 女人天堂亚洲aⅴ在线观看| 亚洲精品在线观看免费| 欧美91视频| 在线一区观看| 老司机免费视频一区二区| 99精品视频免费观看| 国产欧美一区二区精品仙草咪| 久久嫩草精品久久久精品一| 一区二区不卡在线视频 午夜欧美不卡'| 亚洲女同在线| 亚洲区在线播放| 国产麻豆91精品| 欧美精品999| 久久日韩精品| 亚洲欧美日韩在线不卡| 亚洲国产精品电影在线观看| 欧美伊人影院| 在线午夜精品自拍| 亚洲高清中文字幕| 国产日韩欧美三级| 欧美精品在线观看播放| 久久精品亚洲精品| 亚洲一二三级电影| 亚洲精品男同| 欧美国产一区二区在线观看| 久久9热精品视频| 亚洲午夜在线观看| 亚洲精品乱码久久久久久| 国内精品视频在线播放| 国产精品推荐精品| 欧美日韩国产三区| 媚黑女一区二区| 久久久久久黄| 久久成人国产| 午夜久久电影网| 亚洲一区二区日本| 亚洲天堂免费观看| 夜夜嗨av一区二区三区网站四季av| 欧美大胆人体视频| 欧美+日本+国产+在线a∨观看| 久久成人一区| 久久爱另类一区二区小说| 亚洲在线视频免费观看| 在线一区二区三区做爰视频网站| 亚洲国产日韩一区| 亚洲激情在线| 亚洲人在线视频| 91久久精品美女| 亚洲日本视频| 日韩视频在线播放| 99视频一区二区| 一区二区三区欧美成人| 一区二区三区日韩精品视频| 一本色道久久综合亚洲精品高清| 一本大道久久a久久综合婷婷 | 老司机一区二区| 久久免费观看视频| 老司机免费视频一区二区| 久久久久久久999精品视频| 久久久久亚洲综合| 欧美成年人视频| 欧美日韩国产免费| 欧美日韩在线高清| 国产欧美精品一区二区色综合 | 伊大人香蕉综合8在线视| 狠狠色狠狠色综合系列| 在线日韩电影| 99国产精品一区| 亚洲男人的天堂在线观看| 欧美在线免费观看亚洲| 老司机免费视频一区二区三区 | 久久精品成人一区二区三区| 久久精品一二三| 亚洲福利免费| 亚洲香蕉在线观看| 亚洲麻豆国产自偷在线| 亚洲网站在线看| 久久久久久亚洲精品不卡4k岛国| 免费日韩精品中文字幕视频在线| 亚洲国产成人不卡| 亚洲一区二区四区| 久久一区二区视频| 国产精品成人免费| 在线日韩av| 欧美一级播放| 亚洲国产精品成人| 西西裸体人体做爰大胆久久久| 久久免费少妇高潮久久精品99| 欧美日韩国产精品一区| 国模套图日韩精品一区二区| 亚洲精品国产精品久久清纯直播| 亚洲欧美日韩国产成人| 欧美风情在线| 亚洲欧美一区二区精品久久久| 免费欧美视频| 国产亚洲美州欧州综合国| 亚洲免费久久| 可以看av的网站久久看| 亚洲在线视频观看| 欧美顶级艳妇交换群宴| 国产一区二区日韩精品欧美精品| 夜夜爽夜夜爽精品视频| 久热精品视频在线免费观看| 亚洲午夜激情在线| 欧美激情视频一区二区三区在线播放 | 亚洲欧美国产高清| 91久久一区二区| 久热成人在线视频| 国产一区二区三区黄视频| 亚洲综合精品自拍|