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

隨筆 - 42  文章 - 3  trackbacks - 0
<2025年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(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>
            亚洲私人影院| 免费在线欧美黄色| 亚洲视频第一页| 欧美日韩一区高清| 亚洲一区二区免费视频| 亚洲精品国久久99热| 美女久久一区| 日韩午夜激情av| 在线视频亚洲欧美| 国产模特精品视频久久久久| 欧美在线视频二区| 久久精品国语| 日韩天堂av| 亚洲视频导航| 在线观看日韩欧美| 亚洲激情视频| 国产精品国产三级国产| 欧美在线亚洲| 老色鬼久久亚洲一区二区| 夜夜夜久久久| 性娇小13――14欧美| 亚洲高清不卡在线| 99riav久久精品riav| 国模大胆一区二区三区| 亚洲精品久久久久久久久久久久久| 国产精品超碰97尤物18| 久久人人97超碰国产公开结果| 欧美电影免费观看大全| 欧美亚洲在线| 欧美搞黄网站| 久久久久免费视频| 欧美日韩系列| 美女网站在线免费欧美精品| 欧美日韩你懂的| 久久亚洲影音av资源网| 欧美日韩三区四区| 老司机精品视频网站| 国产精品h在线观看| 免费在线看成人av| 国产精品一区一区| 亚洲欧洲精品一区二区三区 | 欧美精品v日韩精品v国产精品| 亚洲综合清纯丝袜自拍| 欧美大片网址| 久久看片网站| 欧美小视频在线观看| 亚洲电影观看| 伊大人香蕉综合8在线视| 在线视频免费在线观看一区二区| 1024亚洲| 久久精品中文| 久久成人精品电影| 国产精品久久久久9999高清| 亚洲国产小视频在线观看| 国产一区二区精品久久99| 亚洲淫性视频| 亚洲欧美自拍偷拍| 欧美三日本三级三级在线播放| 亚洲经典一区| 亚洲精品国产视频| 媚黑女一区二区| 麻豆91精品| 国产综合一区二区| 欧美一区激情| 久久亚洲精品一区二区| 国产一区二区三区四区老人| 亚洲午夜免费福利视频| 亚洲欧美国产一区二区三区| 欧美三级小说| 亚洲一区在线免费| 久久国产成人| 激情成人亚洲| 另类av一区二区| 亚洲大片精品永久免费| 亚洲人被黑人高潮完整版| 美女露胸一区二区三区| 欧美激情影音先锋| 中文av字幕一区| 欧美午夜精品伦理| 亚洲综合国产| 美女视频网站黄色亚洲| 亚洲韩国日本中文字幕| 欧美韩国日本一区| 一本久久综合| 久久高清国产| 亚洲国产裸拍裸体视频在线观看乱了中文| 欧美+亚洲+精品+三区| 亚洲日本成人在线观看| 亚洲综合欧美| 一区二区三区在线高清| 欧美99在线视频观看| 99视频有精品| 久久精品国产免费观看| 在线观看欧美一区| 欧美激情一区二区三区全黄 | 亚洲欧美国产精品va在线观看| 国产精品色一区二区三区| 欧美一级二级三级蜜桃| 欧美激情视频网站| 亚洲一二区在线| 国产一区亚洲| 欧美无砖砖区免费| 久久精品女人| 99国产精品国产精品毛片| 久久av一区二区三区漫画| 91久久国产综合久久蜜月精品| 欧美日韩精品在线观看| 欧美一区二区三区免费观看| 亚洲盗摄视频| 久久精品中文字幕一区| 亚洲美女av网站| 国产亚洲一级高清| 欧美激情在线观看| 欧美一区二区三区久久精品| 亚洲国产一区二区三区a毛片| 欧美一级艳片视频免费观看| 亚洲精品免费看| 国内精品久久久久久影视8| 欧美精品国产| 久久在线视频在线| 亚洲一区二区三区高清不卡| 亚洲大片免费看| 久久久久久网| 欧美亚洲日本国产| 亚洲伦理自拍| 亚洲国产精品激情在线观看| 国产美女一区二区| 欧美日韩少妇| 欧美日韩a区| 欧美黄在线观看| 久久一区视频| 久久综合九色| 久久久久久九九九九| 午夜精品剧场| 亚洲伊人一本大道中文字幕| 99精品国产高清一区二区 | 久久久久9999亚洲精品| 亚洲图片欧洲图片av| 99riav1国产精品视频| 亚洲国产精品99久久久久久久久| 国外成人在线视频网站| 国产视频久久久久| 国产精品一区二区久久久久| 国产精品美女久久久浪潮软件| 欧美精品三级| 欧美视频一区二区| 欧美日韩一区国产| 国产精品高清在线| 国产精品福利网| 国产精品女主播| 国产精品社区| 海角社区69精品视频| 在线观看亚洲视频啊啊啊啊| 好吊妞这里只有精品| 国产一区久久| 伊人久久亚洲热| 亚洲国产乱码最新视频| 日韩视频免费观看高清在线视频| 亚洲欧洲精品一区二区| 日韩视频一区二区三区| 一卡二卡3卡四卡高清精品视频| 一本色道久久综合亚洲精品婷婷 | 久久蜜桃香蕉精品一区二区三区| 久久久久久久91| 久热国产精品视频| 欧美黄色小视频| 亚洲区一区二| 国产精品99久久久久久宅男| 欧美一区二区三区日韩| 久久精品网址| 欧美精品久久99久久在免费线| 欧美日韩一区二区欧美激情| 国产精品一区二区女厕厕| 黑人极品videos精品欧美裸| 亚洲欧洲另类国产综合| 亚洲一区二区三区在线播放| 久久精品三级| 亚洲国产欧美在线人成| 在线亚洲观看| 久久久精品日韩欧美| 欧美高清在线一区| 国产老肥熟一区二区三区| 亚洲高清视频中文字幕| 亚洲综合另类| 欧美电影在线播放| 中文在线资源观看网站视频免费不卡| 亚洲欧美在线网| 欧美国产精品| 国产午夜精品福利| 亚洲精品在线观| 久久久久国产一区二区三区| 亚洲精品老司机| 久久国产精品99精品国产| 欧美日韩精品免费| 国内外成人免费视频 | 狠狠色综合日日| 亚洲视频一起| 欧美凹凸一区二区三区视频| 午夜一区二区三区不卡视频| 欧美日韩免费观看中文|