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

隨筆 - 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 鷹擊長空 閱讀(315) 評論(0)  編輯 收藏 引用

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美日韩国内| 欧美护士18xxxxhd| 久久精品成人| 老色鬼久久亚洲一区二区 | 欧美精品久久久久久久| 国产精品99免视看9| 国产日韩欧美二区| 一色屋精品视频在线观看网站| 亚洲国产欧美日韩| 亚洲欧美经典视频| 欧美jizzhd精品欧美巨大免费| a91a精品视频在线观看| 久久动漫亚洲| 欧美日韩一区二区视频在线| 激情久久一区| 亚欧美中日韩视频| 亚洲欧洲精品一区二区三区波多野1战4 | 亚洲视频每日更新| 久久夜色精品| 国产精品视频久久久| 亚洲精品免费一二三区| 久久久综合精品| 亚洲午夜精品久久| 欧美日韩不卡合集视频| 欧美一级黄色网| 免费久久99精品国产自| 韩国三级电影一区二区| 久久精品亚洲精品| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产一区二区三区精品欧美日韩一区二区三区 | 久久久久久亚洲精品杨幂换脸| 欧美一区二区三区四区在线| 久久久另类综合| 国产精品亚洲综合色区韩国| 久久综合久色欧美综合狠狠 | 亚洲在线观看视频网站| 亚洲精品偷拍| 欧美激情综合| 久久激情综合| 欧美日韩另类国产亚洲欧美一级| 久久精品一区二区| 欧美一区二区三区播放老司机| 亚洲国内精品| 欧美在线观看日本一区| 在线精品视频免费观看| 欧美不卡在线| 国产酒店精品激情| 蜜桃久久精品一区二区| 免费看av成人| 久久免费99精品久久久久久| 欧美日韩综合不卡| 午夜视频久久久| 欧美一级免费视频| 亚洲欧美日韩一区二区在线| 欧美精品网站| 亚洲黑丝在线| 欧美三日本三级三级在线播放| 欧美成熟视频| 欧美日韩在线不卡一区| 亚洲国产老妈| 亚洲精品黄网在线观看| 麻豆精品视频在线观看| 一本综合久久| 亚洲一区二三| 在线观看91精品国产入口| 欧美一区二区黄色| 久久精品国产一区二区三| 国产精品资源| 西瓜成人精品人成网站| 亚洲激情六月丁香| 免费一级欧美片在线观看| 欧美国产日本高清在线| 91久久精品久久国产性色也91| 在线午夜精品| 性欧美暴力猛交69hd| 国产精品美女主播| 欧美国产在线视频| 日韩一区二区电影网| 欧美在线视频日韩| 蜜月aⅴ免费一区二区三区| 在线观看国产日韩| 欧美国产日韩在线| 一本色道久久综合| 亚洲国产精品一区制服丝袜 | 亚洲资源av| 亚洲免费成人av电影| 欧美一区二区| 免费91麻豆精品国产自产在线观看| 亚洲第一黄网| 欧美日韩国产系列| 午夜精品福利一区二区蜜股av| 日韩午夜视频在线观看| 欧美视频中文字幕| 欧美在线日韩| 亚洲精品123区| 久久aⅴ国产紧身牛仔裤| 欧美日韩午夜在线视频| 亚洲欧美国产77777| 美女视频黄 久久| a91a精品视频在线观看| 国产一区二区精品久久99| 久热精品视频在线| 老司机凹凸av亚洲导航| 99在线精品免费视频九九视| 国产欧美日韩免费看aⅴ视频| 亚洲欧洲另类| 欧美一区在线直播| 国产九九精品视频| 欧美精品二区三区四区免费看视频| 国产精品99久久久久久人| 美女福利精品视频| 午夜精品福利视频| 99视频日韩| 伊人男人综合视频网| 欧美性片在线观看| 欧美激情按摩在线| 久久精品国产一区二区三| 玖玖视频精品| 性刺激综合网| 中文在线资源观看网站视频免费不卡| 欧美美女操人视频| 洋洋av久久久久久久一区| 免费成人av在线看| 久久精品日产第一区二区三区| 日韩亚洲精品视频| 在线播放日韩专区| 国产又爽又黄的激情精品视频| 久久国产精品黑丝| 亚洲一区日韩| 99国产精品久久久久老师| 亚洲第一天堂av| 亚洲另类视频| 亚洲黄色一区二区三区| 黄色在线一区| 国产在线欧美| 国产亚洲精品7777| 国产一区二区0| 国产欧美一区二区三区在线看蜜臀| 国产精品video| 欧美日韩卡一卡二| 欧美色视频在线| 欧美色欧美亚洲另类七区| 欧美精品www| 欧美激情自拍| 欧美日韩国内自拍| 欧美日韩一区三区四区| 欧美日韩专区在线| 国产精品久久97| 久久男女视频| 蜜桃av综合| 欧美精品成人在线| 欧美日韩国产成人在线观看| 欧美日韩国产色综合一二三四| 欧美激情在线狂野欧美精品| 欧美老女人xx| 欧美吻胸吃奶大尺度电影| 国产精品成人播放| 国产精品乱码一区二三区小蝌蚪| 国产精品一香蕉国产线看观看 | 欧美精品亚洲二区| 欧美日韩伦理在线免费| 国产精品久久久亚洲一区| 国产精品午夜电影| 一区精品久久| 夜夜嗨av一区二区三区四区| 中文在线一区| 久久精品国产2020观看福利| 噜噜噜在线观看免费视频日韩| 欧美高清视频一区二区| 亚洲免费观看高清在线观看| 久久女同精品一区二区| 欧美黄色精品| 亚洲视频在线观看免费| 欧美在线不卡| 欧美黄色一区二区| 国产日韩精品综合网站| 亚洲日本无吗高清不卡| 亚洲一区二区视频在线| 日韩视频一区| 欧美在线精品免播放器视频| 欧美成人午夜激情在线| 一区二区三区你懂的| 久久久水蜜桃| 国产精品国产三级国产a| 精品成人国产在线观看男人呻吟| 亚洲乱码久久| 久久久久久久一区二区| 亚洲精品视频二区| 久久精品综合网| 国产精品久久久久久久久借妻 | 欧美一级久久| 亚洲国产另类久久精品| 性做久久久久久久免费看| 欧美高清视频一区二区| 国产日韩在线看| 亚洲视频导航| 欧美激情一区二区三区| 欧美一区视频| 国产精品久久久| 夜夜嗨一区二区|