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

隨筆 - 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>
            欧美视频亚洲视频| 欧美日韩国产高清视频| 国产亚洲精品aa午夜观看| 亚洲欧美视频在线| 亚洲一二三区精品| 国内视频精品| 欧美激情一区二区三区在线视频| 美女免费视频一区| 亚洲精品无人区| 亚洲私人影院在线观看| 国产亚洲精品久久久| 美日韩精品视频免费看| 欧美精品激情| 欧美一级片在线播放| 久久久亚洲精品一区二区三区 | 亚洲图片激情小说| 国产日韩欧美高清免费| 免费观看成人www动漫视频| 欧美成人一区二区三区在线观看| 一本色道久久综合精品竹菊| 亚洲综合99| 91久久精品国产91久久| 亚洲私人黄色宅男| 黄色在线一区| 日韩午夜一区| 一区免费在线| 一区二区三区**美女毛片| 国产一区二区三区丝袜| 亚洲精品午夜| 激情综合在线| 亚洲永久精品国产| 亚洲精品中文字幕女同| 亚洲欧美日本精品| 99精品国产高清一区二区| 性做久久久久久| aa日韩免费精品视频一| 久久国产免费| 欧美一级理论片| 欧美猛交免费看| 免费成人av资源网| 国产日韩视频一区二区三区| 亚洲国产另类久久久精品极度| 国产精品永久免费观看| 亚洲精品日韩在线| 亚洲狠狠婷婷| 久久久午夜精品| 久久岛国电影| 国产精品区免费视频| 最新国产の精品合集bt伙计| 在线免费观看一区二区三区| 午夜精品影院| 欧美一区二区三区日韩视频| 欧美日韩精品免费观看| 亚洲国产精品成人久久综合一区| 狠狠操狠狠色综合网| 午夜久久电影网| 欧美亚洲自偷自偷| 国产精品久久久久婷婷| 一区二区不卡在线视频 午夜欧美不卡在 | 男女视频一区二区| 国产欧美va欧美不卡在线| 日韩午夜激情av| 在线视频免费在线观看一区二区| 免费欧美电影| 欧美激情va永久在线播放| 在线成人激情视频| 久久久综合精品| 欧美不卡福利| 亚洲日本成人女熟在线观看| 久久亚洲精选| 欧美国产日韩在线| 亚洲黄色有码视频| 欧美sm视频| 日韩视频一区二区| 亚洲欧美国产日韩中文字幕| 国产精品网站在线播放| 亚洲在线视频免费观看| 欧美专区在线观看| 在线观看三级视频欧美| 男人天堂欧美日韩| 日韩小视频在线观看| 亚洲欧美激情精品一区二区| 国产精品私拍pans大尺度在线 | 亚洲免费观看在线视频| 亚洲视频一区二区在线观看 | 欧美激情久久久久久| 亚洲乱码久久| 香蕉久久夜色精品国产| 国产一区二区三区视频在线观看| 久久久久久精| 亚洲日本一区二区| 亚洲欧美怡红院| 国内精品嫩模av私拍在线观看 | 亚洲欧美激情视频| 久久在线免费观看| 亚洲最黄网站| 国产一本一道久久香蕉| 久久亚洲精品欧美| 99天天综合性| 久久久久久网址| 日韩视频一区二区| 国产精品一区二区三区久久| 久久精品国产第一区二区三区最新章节 | 国产夜色精品一区二区av| 久久人人爽人人爽| 99精品视频免费观看视频| 久久精品日韩一区二区三区| 亚洲激情中文1区| 国产伦精品一区二区三区免费| 久久久久久午夜| 国产精品99久久久久久久久| 美女诱惑一区| 欧美亚洲一区二区在线| 亚洲精品日韩综合观看成人91| 国产精品美女久久久免费| 欧美 日韩 国产 一区| 亚洲欧美视频一区二区三区| 亚洲高清资源| 久久九九99| 亚洲女同性videos| 亚洲三级免费| 一区二区三区自拍| 国产日韩欧美亚洲| 欧美亚州在线观看| 欧美激情一区二区三区高清视频| 久久精品国产免费| 亚洲一区二区三区乱码aⅴ| 91久久精品网| 亚洲高清123| 欧美福利电影网| 久久午夜激情| 久久久久国产成人精品亚洲午夜| 亚洲一级网站| 亚洲一二三区在线观看| 亚洲美女在线视频| 亚洲人成毛片在线播放| 在线观看日韩精品| 精品99一区二区| 一区二区三区在线视频播放| 国产一区三区三区| 国产午夜精品美女视频明星a级| 国产精品久久久久99| 国产精品hd| 国产精品视频区| 国产欧美亚洲视频| 国产香蕉97碰碰久久人人| 国产色爱av资源综合区| 国产一区二区三区免费在线观看| 国产午夜精品一区二区三区视频 | 国产精品扒开腿做爽爽爽软件| 欧美久久视频| 欧美日韩中文精品| 国产精品视频久久| 国产一区二区中文字幕免费看| 国产在线视频欧美| 在线日韩欧美视频| 亚洲美女啪啪| 亚洲欧美日韩成人| 久久久久久久久久久久久9999| 久久九九免费视频| 欧美高清视频一区二区| 亚洲国产欧美在线| 国产精品99久久久久久www| 亚洲免费影院| 久久久综合网站| 欧美精品在线观看91| 国产精品豆花视频| 精品88久久久久88久久久| 91久久精品美女| 亚洲欧美日韩一区二区三区在线| 久久成人一区二区| 欧美激情麻豆| 亚洲一区二区在线观看视频| 久久精品视频99| 欧美日韩国内自拍| 国产曰批免费观看久久久| 亚洲区一区二区三区| 午夜精品久久久久| 欧美国产精品久久| 亚洲一二三级电影| 卡一卡二国产精品| 国产精品嫩草99av在线| 亚洲高清不卡在线观看| 亚洲欧美国产高清va在线播| 免费亚洲一区二区| 亚洲一区二区三区涩| 欧美aⅴ99久久黑人专区| 国产精品日日做人人爱| 亚洲日本乱码在线观看| 久久成人精品电影| 亚洲精品在线电影| 久久精品国产91精品亚洲| 欧美性色aⅴ视频一区日韩精品| 在线日本成人| 久久se精品一区精品二区| 9色精品在线| 欧美va天堂va视频va在线| 国产综合视频| 午夜精品区一区二区三| 亚洲毛片av|