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

隨筆 - 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>
            男女激情久久| 韩日精品在线| 国产精品九九| 国产精品日韩欧美一区二区| 国产欧美在线| 亚洲高清毛片| 一区二区三区欧美视频| 亚洲视频狠狠| 免费看精品久久片| 亚洲精品在线视频| 欧美一区二区三区免费观看| 美日韩丰满少妇在线观看| 国产精品成人国产乱一区| 亚洲欧美一区二区原创| 欧美成人蜜桃| 亚洲影院免费观看| 美女诱惑一区| 亚洲无限av看| 亚洲国产日韩精品| 久久成人精品视频| 亚洲国产欧美国产综合一区| 欧美激情一区二区三区高清视频| 国产情人综合久久777777| 久久视频一区| 亚洲影院色无极综合| 国产一区二区三区在线观看精品| 一区二区三区回区在观看免费视频| 一区二区免费在线视频| 免费观看成人网| 亚洲视频久久| 久久一区二区三区四区五区| 国产精品羞羞答答| 欧美电影免费观看高清完整版| 欧美乱在线观看| 在线国产精品播放| 久久视频这里只有精品| 欧美日本网站| 另类春色校园亚洲| 久久婷婷国产综合尤物精品| 一区二区免费在线视频| 久久久久免费观看| 国内成人自拍视频| 免费影视亚洲| 国产精品夜夜夜| 亚洲国产影院| 在线观看亚洲视频| 欧美激情亚洲另类| 欧美成年人在线观看| 亚洲国产另类久久久精品极度| 麻豆精品91| 国产日韩一区欧美| 久久伊人精品天天| 国产精品亚洲视频| 一区二区黄色| 日韩性生活视频| 夜夜精品视频| 国产精品免费区二区三区观看| 性做久久久久久免费观看欧美| 亚洲曰本av电影| 一区二区欧美在线观看| 猫咪成人在线观看| 嫩草成人www欧美| 欧美日韩精品免费观看视一区二区| 中日韩高清电影网| 欧美激情精品久久久久久大尺度 | 久久久精品动漫| 在线欧美日韩| 久久久久久久综合日本| 久久久久五月天| 欧美成人r级一区二区三区| 噜噜噜91成人网| 狠狠88综合久久久久综合网| 久久av红桃一区二区小说| 91久久精品国产| 亚洲线精品一区二区三区八戒| 韩日欧美一区二区三区| 欧美伊人久久久久久午夜久久久久 | 亚洲免费在线精品一区| 国产一区二区中文| 欧美一区二区三区男人的天堂| 欧美伊人精品成人久久综合97| 老司机成人在线视频| 亚洲性av在线| 国产精品视频xxx| 欧美一区二区三区四区夜夜大片| 久久久91精品| 欧美性猛交xxxx乱大交蜜桃| 久久久精品一区| 影音欧美亚洲| 欧美国产先锋| 亚洲一区二区视频| 久久免费国产精品| 亚洲人成亚洲人成在线观看| 欧美日韩亚洲一区二区三区四区| 欧美~级网站不卡| 99国产精品一区| 国产免费一区二区三区香蕉精| 亚洲精品九九| 亚洲国内欧美| 国产精品国产a| 久久精品亚洲精品| 91久久综合亚洲鲁鲁五月天| 亚洲第一天堂无码专区| 欧美另类99xxxxx| 欧美一级免费视频| 亚洲国产精品一区二区三区| 亚洲中午字幕| 国产精品99一区| 久久天天躁夜夜躁狠狠躁2022| 日韩视频一区| 亚洲一区亚洲| 亚洲国产老妈| 国产欧美日韩一区二区三区在线观看 | 欧美在线啊v一区| 亚洲人成毛片在线播放| 国产日本欧美一区二区三区在线| 欧美二区视频| 久久国产福利国产秒拍| 欧美中文字幕久久| 日韩一级在线| 在线精品亚洲| 国产精品一区二区你懂的| 欧美成人精品1314www| 午夜久久影院| 老司机成人网| 久久国产精彩视频| 中国成人在线视频| 亚洲高清视频的网址| 国产亚洲精品成人av久久ww| 欧美日韩国内| 欧美精品一区二区三区久久久竹菊| 久久国内精品视频| 欧美伊人影院| 销魂美女一区二区三区视频在线| 亚洲最新视频在线| 亚洲品质自拍| 亚洲精品国产精品乱码不99| 欧美成人午夜激情在线| 久久一区二区三区四区| 久久九九免费| 久久久国产精品一区| 性伦欧美刺激片在线观看| 亚洲女人av| 国产一区二区三区久久| 国产视频亚洲| 国产性天天综合网| 国产日本欧美视频| 国产一区二区三区自拍| 国模吧视频一区| 国产综合久久久久久| 国产在线高清精品| 一区免费视频| 欧美日韩视频免费播放| 欧美日韩国产限制| 欧美日韩免费观看一区| 欧美日韩视频一区二区| 国产精品成人一区二区| 国产精品日韩欧美一区| 国产欧美韩日| 精品成人a区在线观看| 在线观看一区视频| 亚洲日本va午夜在线影院| 亚洲精品欧洲精品| 国产小视频国产精品| 精品不卡视频| 亚洲精品国产系列| 中日韩在线视频| 亚洲欧美日产图| 久久精品视频在线看| 一区二区电影免费在线观看| 亚洲一二区在线| 久久国产视频网| 欧美成人午夜激情| 一区二区激情视频| 欧美一区二区三区免费观看| 蜜臀久久99精品久久久画质超高清| 欧美a级一区| 国产精品久久77777| 尤物九九久久国产精品的分类| 亚洲欧洲日产国产网站| 亚洲欧美资源在线| 蜜臀久久99精品久久久久久9| 亚洲欧洲一区二区三区| 亚洲欧美日韩人成在线播放| 99视频超级精品| 久久精品欧美日韩精品| 欧美日韩国产亚洲一区| 国产自产精品| 一本久道久久综合中文字幕| 亚洲精一区二区三区| 亚洲大片在线观看| 亚洲欧美日韩一区| 欧美成人资源网| 亚洲免费在线视频一区 二区| 你懂的亚洲视频| 国产又爽又黄的激情精品视频 | 欧美午夜不卡影院在线观看完整版免费| 国产日韩1区| 亚洲视频精选| 欧美激情精品久久久久久蜜臀|