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

隨筆 - 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 鷹擊長空 閱讀(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| 久久激情五月激情| 欧美黄色aaaa| 久久亚洲国产精品一区二区| 欧美精品色综合| 国产伦一区二区三区色一情| 久久综合久久综合九色| 欧美精品播放| 免费观看在线综合| 欧美午夜在线观看| 欧美激情中文字幕乱码免费| 国产日韩欧美成人| 一二三四社区欧美黄| 亚洲国产天堂久久综合| 亚洲一区二区在| 一区二区三区四区精品| 欧美成熟视频| 欧美激情在线狂野欧美精品| 在线精品福利| 久久只有精品| 最新国产拍偷乱拍精品| 亚洲大胆人体在线| 欧美国产专区| 亚洲午夜免费视频| 久久久国产亚洲精品| 国外成人在线| 蜜臀久久99精品久久久久久9 | 亚洲欧美另类国产| 国产婷婷色综合av蜜臀av| 午夜精品久久久久| 美乳少妇欧美精品| 亚洲三级观看| 国产精品男人爽免费视频1| 亚洲欧美日韩一区二区| 久久av免费一区| 亚洲国产精品视频| 久久久国产视频91| 亚洲一区不卡| 亚洲精品国偷自产在线99热| 国产精品久久久久av免费| 久久久噜噜噜久久中文字幕色伊伊 | 国产伦精品一区二区三区照片91| 亚洲综合电影| 亚洲高清毛片| 欧美一级久久| 一区二区激情视频| 亚洲国产三级网| 在线欧美日韩国产| 久久精品亚洲| 亚洲国产综合91精品麻豆| 国产精品成人一区二区三区夜夜夜| 欧美亚洲免费电影| 亚洲午夜激情| 亚洲精品自在久久| 亚洲国产精品va| 久久综合网色—综合色88| 欧美一二区视频| 亚洲午夜激情网页| 亚洲欧美日韩视频一区| 亚洲一区中文| 先锋影音网一区二区| 中日韩视频在线观看| 亚洲曰本av电影| 欧美在线视频二区| 亚洲国产精品成人va在线观看| 国产欧美日韩在线观看| 国产欧美一区二区白浆黑人| 国产精品影音先锋| 国产日韩精品在线| 国产综合在线视频| 亚洲二区视频| 一区二区三区成人| 欧美在线亚洲综合一区| 久久aⅴ国产欧美74aaa| 久久免费高清| 亚洲精品激情| 亚洲黄色有码视频| 久久久天天操| 怡红院精品视频| 国产精品一区视频| 红桃av永久久久| 亚洲视频免费在线| 久久亚洲精品网站| 久久免费精品视频| 亚洲婷婷综合久久一本伊一区| 亚洲一区二区免费看| 久久在线视频| 另类成人小视频在线| 亚洲高清不卡av| 夜夜嗨一区二区三区| 久久理论片午夜琪琪电影网| 久久久久久亚洲精品杨幂换脸| 欧美日韩精品一区| 国产一区二区三区四区五区美女| 伊人天天综合| 久久天天综合| 午夜久久福利| 国产一区二区精品久久91| 日韩图片一区| 亚洲国产1区| 另类亚洲自拍| 国产性天天综合网| 久久久国产91| 久久裸体艺术| 亚洲三级色网| 亚洲精品1区2区| 欧美视频你懂的| 亚洲人体1000| 亚洲精品一区二区三区四区高清| 欧美激情a∨在线视频播放| 日韩天堂av| 久久亚洲精品伦理| 亚洲欧美日韩成人| 免费欧美在线视频| 亚洲在线成人| 女人香蕉久久**毛片精品| 亚洲图片欧美一区| 卡一卡二国产精品| 欧美怡红院视频| 欧美日韩国产一区精品一区| 久久成人一区| 欧美日韩精品国产| 日韩亚洲欧美中文三级| 激情欧美国产欧美| 午夜精品亚洲一区二区三区嫩草| 亚洲天堂黄色| 男女激情久久| 一本大道久久a久久精二百| 亚洲国产导航| 牛夜精品久久久久久久99黑人 | 久久久久久一区二区三区| 久久精品国产2020观看福利| 国产欧美日韩综合精品二区| 先锋影音一区二区三区| 毛片基地黄久久久久久天堂| 在线观看欧美成人| 欧美日韩综合另类| 欧美一区二区三区成人| 亚洲国产日韩欧美综合久久| 亚洲人成在线播放网站岛国| 久久久久一区二区三区| 免费看亚洲片| 日韩小视频在线观看专区| 欧美黄色小视频| 亚洲永久在线观看| 久久久久久网| 亚洲精品一区二区网址| 欧美日韩一区二区三区在线| 一区二区欧美在线| 欧美一区二区三区久久精品茉莉花| 国产亚洲精品久久久久动| 久久男人资源视频| 一本一本久久a久久精品牛牛影视| 午夜精品久久久| 亚洲精品网站在线播放gif| 欧美日韩中文字幕在线| 久热精品视频在线| 亚洲一区二区三区四区五区黄| 欧美大成色www永久网站婷| 亚洲第一精品电影| 国产欧美一区二区三区另类精品| 久久中文字幕一区二区三区| 亚洲一区二区黄| 亚洲国产精品久久久久久女王| 欧美亚洲网站| 亚洲中午字幕| 亚洲一本大道在线| 亚洲欧洲精品一区二区三区波多野1战4 | 99riav国产精品| 亚洲国产婷婷| 在线观看欧美亚洲| 国产美女诱惑一区二区| 欧美日韩无遮挡| 欧美日韩999| 免费亚洲一区| 母乳一区在线观看| 欧美精品激情| 欧美日韩激情网| 欧美日韩精品一区二区天天拍小说| 免费久久久一本精品久久区| 免费在线看一区| 欧美日韩日日夜夜| 国产精品都在这里| 国产亚洲a∨片在线观看| 在线免费高清一区二区三区| 在线观看亚洲精品| 亚洲免费激情| 香蕉久久久久久久av网站| 久久一区二区精品| 亚洲精品色图| 欧美一区二区三区视频在线| 蜜桃av噜噜一区二区三区| 欧美日韩一二三区| 在线欧美不卡| 欧美一区中文字幕| 最新中文字幕亚洲| 欧美永久精品|