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

隨筆 - 42  文章 - 3  trackbacks - 0
<2012年7月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

常用鏈接

留言簿(2)

隨筆檔案

文章檔案

網(wǎng)頁收藏

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

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 鷹擊長空 閱讀(311) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产欧美一区二区色老头| 免费成人av在线看| 亚洲精品欧美日韩| 欧美精品在线观看一区二区| 艳女tv在线观看国产一区| 亚洲国产成人av好男人在线观看| 欧美影院成年免费版| 国内精品久久久久影院优| 久久女同精品一区二区| 久久精品亚洲一区| 亚洲黄一区二区三区| 亚洲精品欧美极品| 国产精品一卡二卡| 免费在线成人| 欧美激情在线播放| 亚洲欧美日韩精品久久亚洲区 | 欧美一区二区三区男人的天堂| 亚洲在线免费| 国产一区二区三区在线观看网站| 久久综合国产精品| 欧美精品国产精品日韩精品| 新狼窝色av性久久久久久| 久久成人精品电影| 亚洲精品一区二| 亚洲女人天堂成人av在线| 在线不卡中文字幕| 99精品热6080yy久久 | 久久精品亚洲热| 一区二区三区久久| 久久久999成人| 一区二区激情视频| 久久久999精品| 中文欧美在线视频| 久久久亚洲精品一区二区三区| 亚洲精品久久久久久久久| 亚洲一区二区在线视频| 亚洲国产精品悠悠久久琪琪 | 欧美二区在线| 国产精品最新自拍| 亚洲精品视频在线观看网站| 国产精品夜夜嗨| 亚洲精品欧洲| 亚洲福利视频免费观看| 中文欧美在线视频| 一区二区三区在线视频免费观看| 一本到高清视频免费精品| 亚洲国产一区二区三区在线播| 亚洲一区二区av电影| 日韩视频在线一区二区| 久久久久国产精品麻豆ai换脸| 正在播放亚洲一区| 欧美成人精品在线播放| 久久午夜激情| 国产欧美精品| 亚洲影视在线| 亚洲欧美乱综合| 欧美日韩精品一区二区三区四区| 欧美va亚洲va日韩∨a综合色| 国产午夜久久| 亚洲欧美日韩国产精品| 亚洲先锋成人| 欧美视频在线观看一区| 亚洲精品人人| 在线亚洲美日韩| 欧美日韩国产大片| 亚洲美女网站| 亚洲神马久久| 国产精品二区在线| 亚洲网站在线观看| 欧美一区二区久久久| 国产精品视频内| 午夜天堂精品久久久久| 久久大综合网| 国内精品久久久久国产盗摄免费观看完整版 | 国产精品天天看| 亚洲欧美日韩在线一区| 久久精品30| 在线不卡中文字幕| 蘑菇福利视频一区播放| 亚洲区免费影片| 一区二区三区毛片| 国产精品欧美日韩| 欧美一区二区三区婷婷月色| 久久手机精品视频| 亚洲国产成人在线视频| 欧美另类99xxxxx| 亚洲视频欧美视频| 久久久久久久综合| 亚洲国产精品尤物yw在线观看| 欧美激情自拍| 亚洲一区二区免费| 久久在精品线影院精品国产| 亚洲卡通欧美制服中文| 亚洲免费视频成人| 狠狠入ady亚洲精品| 欧美极品在线播放| 亚洲免费中文字幕| 欧美xart系列高清| 亚洲男人第一网站| 亚洲福利视频专区| 国产精品videosex极品| 久久久噜久噜久久综合| 亚洲精品一区在线| 久久综合九色九九| 亚洲视频在线观看网站| 国内精品久久久久影院优| 欧美激情一区二区三区全黄| 亚洲欧美综合| 亚洲日本成人网| 欧美一区二视频| 日韩一级片网址| 一区二区三区在线视频观看| 欧美系列亚洲系列| 老司机凹凸av亚洲导航| 一区二区三区视频在线播放| 欧美va亚洲va香蕉在线| 欧美影院在线播放| 国产精品99久久久久久www| 黄色在线一区| 国产精品揄拍500视频| 欧美经典一区二区三区| 久久久久久久波多野高潮日日| 一区二区三区毛片| 亚洲精品乱码久久久久久按摩观| 久久亚洲综合网| 久久成人精品无人区| 亚洲一区二区免费看| 一本一本a久久| 亚洲黄色三级| 激情小说亚洲一区| 国产精品一区二区三区观看 | 久久久久久91香蕉国产| 香蕉亚洲视频| 亚洲一区视频在线| 一区二区欧美日韩| 亚洲精选国产| 亚洲伦理在线观看| 亚洲人成免费| 亚洲人成亚洲人成在线观看| 免费的成人av| 免播放器亚洲一区| 美女亚洲精品| 美女脱光内衣内裤视频久久影院| 噜噜噜91成人网| 另类图片国产| 亚洲第一中文字幕在线观看| 欧美大片免费久久精品三p| 免费一级欧美片在线观看| 开心色5月久久精品| 免费人成精品欧美精品| 免费成人av在线看| 欧美激情中文字幕乱码免费| 亚洲国产导航| 亚洲六月丁香色婷婷综合久久| 亚洲区一区二| 一区二区欧美视频| 午夜精品视频| 久久久综合香蕉尹人综合网| 久久影院午夜论| 欧美国产精品久久| 欧美日韩亚洲91| 国产色综合久久| 一区在线观看视频| 日韩亚洲精品视频| 亚洲影院色无极综合| 久久av一区二区三区漫画| 久久亚洲欧美国产精品乐播| 欧美激情性爽国产精品17p| 亚洲精品视频一区| 亚洲欧美在线视频观看| 久久久久久夜| 欧美精品自拍偷拍动漫精品| 国产精品久久久久久久久久尿 | 一本久久综合亚洲鲁鲁五月天| 亚洲欧美国产另类| 久久婷婷蜜乳一本欲蜜臀| 欧美国产精品v| 亚洲免费网站| 男人插女人欧美| 国产精品一区二区久久| 悠悠资源网亚洲青| 中日韩视频在线观看| 久久久久久久999| 亚洲三级色网| 欧美影院成年免费版| 欧美成人精品一区| 国产精品自拍网站| 亚洲精选大片| 久久在线精品| 亚洲视频图片小说| 奶水喷射视频一区| 国产亚洲欧美一区| 正在播放亚洲| 欧美韩日亚洲| 久久精品1区| 国产女人水真多18毛片18精品视频| 亚洲欧洲一区二区天堂久久 | 亚洲欧美另类久久久精品2019| 欧美mv日韩mv国产网站| 亚洲欧美日韩国产中文|