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

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

只有注冊用戶登錄后才能發(fā)表評論。
網站導航: 博客園   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>
            久久中文字幕导航| 美女露胸一区二区三区| 亚洲国产高清一区二区三区| 99精品视频免费观看视频| 国内自拍一区| 亚洲香蕉网站| 中日韩在线视频| 欧美成人第一页| 久久久亚洲综合| 国产精品一区二区在线观看网站 | 永久91嫩草亚洲精品人人| 在线亚洲成人| 亚洲视频高清| 欧美全黄视频| 亚洲人成小说网站色在线| 精品51国产黑色丝袜高跟鞋| 午夜久久黄色| 欧美一区二区三区视频免费| 国产精品国产三级国产aⅴ入口| 亚洲人人精品| 一本久久综合亚洲鲁鲁五月天| 老牛国产精品一区的观看方式| 久久免费黄色| 国产一区二区三区高清在线观看| 午夜在线一区二区| 欧美一区国产在线| 国产亚洲激情在线| 久久国产主播| 美女爽到呻吟久久久久| 伊人春色精品| 美日韩丰满少妇在线观看| 欧美成人午夜视频| 亚洲精品在线二区| 欧美日韩国产不卡| 99riav国产精品| 亚洲欧美激情视频| 国产亚洲精品福利| 久久久天天操| 亚洲国产综合在线| 亚洲一区二区三区精品动漫| 国产精品推荐精品| 欧美怡红院视频一区二区三区| 久久―日本道色综合久久| 伊人春色精品| 欧美日韩国产在线播放| 在线视频你懂得一区二区三区| 欧美一级在线播放| 狠狠色狠色综合曰曰| 美国十次了思思久久精品导航| 亚洲激情视频在线| 欧美一区二区免费观在线| 国产自产2019最新不卡| 免费在线亚洲| 一本色道久久综合亚洲精品按摩| 午夜精品美女久久久久av福利| 国产亚洲午夜| 欧美极品影院| 欧美一级在线播放| 亚洲黄色视屏| 欧美一区国产在线| 亚洲精品女av网站| 国产欧美一区二区色老头| 噜噜噜久久亚洲精品国产品小说| 亚洲卡通欧美制服中文| 久久久精品性| 亚洲视频综合| 亚洲国产精品成人综合| 欧美性事在线| 欧美夫妇交换俱乐部在线观看| 亚洲午夜高清视频| 欧美不卡视频一区| 午夜在线视频观看日韩17c| 在线欧美福利| 国产美女在线精品免费观看| 欧美成人午夜免费视在线看片 | 亚洲日本va午夜在线影院| 亚洲一卡久久| 亚洲国产成人高清精品| 国产精品另类一区| 欧美黄色aaaa| 久久精品一区二区| 亚洲欧美网站| 一区电影在线观看| 亚洲第一级黄色片| 久久综合网络一区二区| 亚洲欧美日韩国产| 一本色道久久88综合亚洲精品ⅰ| 精品999在线播放| 国产精品亚洲视频| 国产精品高潮在线| 欧美日韩在线另类| 欧美激情第六页| 久久这里只有| 久久久久国色av免费看影院| 亚洲综合成人在线| 亚洲男女自偷自拍图片另类| 夜夜爽夜夜爽精品视频| 亚洲人成网站在线观看播放| 欧美成人在线免费观看| 可以免费看不卡的av网站| 欧美一区国产一区| 欧美一区二区在线看| 亚洲一区日韩在线| 宅男精品导航| 亚洲永久精品国产| 亚洲性图久久| 亚洲男人天堂2024| 性感少妇一区| 久久久久九九视频| 久久久在线视频| 久久一二三国产| 欧美成人精品影院| 欧美激情1区2区3区| 欧美国产一区视频在线观看 | 亚洲缚视频在线观看| 欧美国产综合视频| 亚洲电影免费观看高清完整版在线观看| 快she精品国产999| 欧美国产日本| 亚洲人成毛片在线播放| 亚洲麻豆国产自偷在线| 一区二区三区毛片| 午夜欧美视频| 理论片一区二区在线| 免费一区视频| 欧美日韩国产在线播放网站| 国产精品久久久久aaaa樱花| 国产日韩欧美精品在线| 狠狠色狠狠色综合日日五| 亚洲精品久久久久久下一站| 一区二区黄色| 久久精品国亚洲| 美女免费视频一区| 99re热这里只有精品视频| 一本久久综合| 久久爱另类一区二区小说| 久久久www成人免费毛片麻豆| 欧美xx视频| 国产精品久久看| 亚洲国产精品久久久久秋霞影院| 日韩午夜在线播放| 久久国产精品99国产精| 能在线观看的日韩av| 99av国产精品欲麻豆| 性欧美xxxx大乳国产app| 欧美成人xxx| 国产午夜精品久久久久久免费视 | 欧美一区二区三区四区视频| 久久综合综合久久综合| 欧美精品综合| 狠狠色伊人亚洲综合网站色| 日韩网站在线看片你懂的| 欧美一区二区三区视频在线观看 | 久久久青草婷婷精品综合日韩| 欧美日韩国产成人在线观看| 国模精品一区二区三区色天香| 亚洲精品裸体| 久热精品视频| 国产精品99久久久久久宅男| 美女福利精品视频| 国产伦一区二区三区色一情| 亚洲麻豆一区| 老**午夜毛片一区二区三区| 一区二区三区视频免费在线观看| 久久久福利视频| 国产精品久久一级| 亚洲六月丁香色婷婷综合久久| 久久三级视频| 亚洲男人天堂2024| 欧美日韩综合不卡| 亚洲乱码精品一二三四区日韩在线| 欧美在线视频播放| 99re6这里只有精品| 欧美va亚洲va国产综合| 韩国v欧美v日本v亚洲v| 亚洲欧美成人一区二区在线电影| 亚洲国产精品传媒在线观看| 欧美资源在线| 国产伦精品一区二区三区视频黑人| 亚洲视频免费观看| 亚洲国产精品久久久久婷婷老年 | 亚洲欧美日韩天堂| 欧美日韩91| 亚洲精品日日夜夜| 欧美电影美腿模特1979在线看| 久久国产视频网站| 国产一区二区三区四区在线观看 | 亚洲成人直播| 久久性色av| 久久本道综合色狠狠五月| 国产一区二区三区日韩欧美| 欧美一区亚洲| 欧美一区二区三区精品电影| 国产欧美日韩一区二区三区在线观看 | 久久女同精品一区二区| 欧美专区18| 影音欧美亚洲| 亚洲高清视频一区| 欧美激情亚洲自拍| 中文欧美字幕免费|