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

隨筆 - 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>
            久久九九久精品国产免费直播| 亚洲网址在线| 久久一二三国产| 久久久噜噜噜久久| 亚洲激精日韩激精欧美精品| 亚洲第一黄色| 欧美福利视频网站| 亚洲自拍16p| 欧美亚洲一区二区三区| 精品动漫3d一区二区三区免费版 | 亚洲视频在线视频| 99精品国产在热久久| 欧美三区美女| 欧美与黑人午夜性猛交久久久| 性欧美1819sex性高清| 亚洲娇小video精品| 欧美日韩色综合| 久久国产精品久久w女人spa| 久久爱另类一区二区小说| 亚洲国产一区二区在线| 99亚洲视频| 狠狠综合久久| 99成人精品| 黄色小说综合网站| 亚洲理论在线观看| 国产日韩专区| 亚洲人成在线播放| 国产欧美日韩精品丝袜高跟鞋| 蜜桃av综合| 国产精品国产三级国产专播精品人 | 久久天天躁狠狠躁夜夜av| 欧美成人一品| 欧美在线免费| 欧美精品一区二区三区视频| 欧美影视一区| 欧美日韩精品三区| 老色鬼精品视频在线观看播放 | 99精品国产福利在线观看免费| 国产色综合久久| 日韩视频免费在线观看| 伊人久久亚洲热| 亚洲一区二区三区高清| 亚洲精品美女在线| 久久精品久久综合| 欧美一级理论片| 欧美日韩免费网站| 亚洲国产1区| 尤物九九久久国产精品的特点| 亚洲神马久久| 日韩视频在线一区二区三区| 久久久91精品| 久久精品人人做人人爽电影蜜月| 欧美日韩三区四区| 亚洲国产精品一区二区三区| 激情久久久久久| 先锋影音一区二区三区| 亚洲一区国产| 欧美三级乱码| 日韩视频免费| 亚洲深夜福利网站| 欧美日韩精品免费观看视一区二区| 欧美成人免费小视频| 一区视频在线看| 久久久精品国产99久久精品芒果| 久久不射中文字幕| 国产亚洲欧美一级| 欧美一区二视频在线免费观看| 欧美一区二区三区视频| 国产精品久久一区主播| 亚洲午夜精品在线| 欧美一级日韩一级| 国产视频精品xxxx| 欧美亚洲在线| 久久免费视频网站| 伊人精品在线| 亚洲伊人网站| 国产精品激情电影| 亚洲永久字幕| 久久这里只有| 亚洲人屁股眼子交8| 欧美精品久久一区| 99国产精品视频免费观看一公开| 亚洲视频在线观看网站| 国产精品一区2区| 久久国产视频网| 免费成人av资源网| 日韩视频一区二区三区在线播放免费观看| 牛人盗摄一区二区三区视频| 亚洲国产精品一区二区第一页 | 国产精品素人视频| 欧美一区二区精品| 欧美国产日韩视频| 亚洲综合日韩在线| 经典三级久久| 欧美日韩日日夜夜| 性欧美大战久久久久久久久| 男同欧美伦乱| 亚洲一区综合| 亚洲国产mv| 国产精品高潮呻吟| 久久中文字幕导航| av成人毛片| 美女精品国产| 亚洲欧美日韩在线观看a三区| 国产专区一区| 欧美日韩成人在线| 久久精品99国产精品日本| 亚洲精品网址在线观看| 久久精品国产亚洲高清剧情介绍| 亚洲欧洲一区二区三区在线观看| 国产精品户外野外| 欧美成人精品三级在线观看| 亚洲综合色网站| 亚洲全部视频| 欧美成人tv| 欧美在线不卡视频| 一本色道久久综合精品竹菊 | 亚洲免费观看高清在线观看| 国产精品一区二区黑丝| 欧美国产在线观看| 欧美一区二区视频免费观看| 亚洲精品一品区二品区三品区| 久久在精品线影院精品国产| 亚洲伊人网站| 99精品国产福利在线观看免费| 国产亚洲精品美女| 国产精品a久久久久久| 女女同性精品视频| 久久亚洲捆绑美女| 欧美影视一区| 欧美一区二区三区另类| 亚洲一卡二卡三卡四卡五卡| 亚洲国产日韩欧美一区二区三区| 久久综合久久综合这里只有精品| 亚洲在线网站| 亚洲亚洲精品三区日韩精品在线视频 | 欧美日韩国产在线看| 玖玖玖免费嫩草在线影院一区| 欧美亚洲日本网站| 午夜精品国产更新| 亚洲欧美综合精品久久成人| 亚洲深夜福利在线| 一区二区三区久久久| 亚洲精品在线三区| 亚洲国产综合视频在线观看| 欧美电影免费观看高清| 美玉足脚交一区二区三区图片| 久久久久亚洲综合| 久久嫩草精品久久久久| 久久免费99精品久久久久久| 久久精品一区蜜桃臀影院 | 亚洲精品你懂的| 亚洲欧洲综合另类| 亚洲伦理中文字幕| 一区二区三区欧美亚洲| 亚洲一区二区三区中文字幕在线| 亚洲一区中文| 欧美亚洲综合久久| 久久亚洲一区二区三区四区| 久久综合久久综合九色| 女女同性精品视频| 亚洲国产天堂久久综合| 日韩视频一区| 亚洲欧美日韩一区二区| 欧美中文字幕第一页| 久久夜色精品国产欧美乱| 男人的天堂成人在线| 欧美日韩亚洲一区二区三区在线| 国产精品福利影院| 国内揄拍国内精品久久| 亚洲国产福利在线| 亚洲视频免费看| 久久久精品午夜少妇| 欧美电影免费观看大全| 亚洲九九九在线观看| 亚洲欧美激情在线视频| 久久综合狠狠综合久久激情| 欧美看片网站| 国产亚洲高清视频| 亚洲美女av网站| 久久9热精品视频| 亚洲国产高清高潮精品美女| 亚洲一区二区三区久久| 裸体歌舞表演一区二区| 国产精品九色蝌蚪自拍| 亚洲国产精品一区二区www| 亚洲性av在线| 欧美成人精品高清在线播放| 一区二区三区免费网站| 开心色5月久久精品| 国产精品久久久爽爽爽麻豆色哟哟| 狠狠色狠狠色综合系列| 亚洲一区二区久久| 欧美黄色日本| 久久av资源网| 国产精品美女一区二区在线观看| 亚洲欧洲精品一区二区| 久久国产精彩视频| 一区二区三区四区蜜桃| 欧美成人精品一区二区三区|