为什么readonly属性仍然允许用KVC编写 [英] Why does a readonly property still allow writing with KVC

查看:98
本文介绍了为什么readonly属性仍然允许用KVC编写的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究"Mac OS X编程"中的键值编码"一章.我建立了一个带有滑块和标签的接口,它们都绑定到一个int的fido上.如果我将fido的属性设置为readonly,则移动滑块仍然会导致标签更改其值.我以为我会为此出错.如果该属性是只读的,那么滑块如何仍可以写入该属性?我认为它不会创建setter,并且KVC无法正常工作.谢谢.

I'm working through the "Key Value Coding" chapter in "Programming for Mac OS X". I've built an interface with a slider and a label, both bound to fido, an int. If I set the property for fido to readonly, moving the slider still causes the label to change it's value. I had assumed that I'd get some sort of error for this. If the property is readonly, how come the slider can still write to the property? I thought that it would have no setters created, and KVC wouldn't work. Thanks.

这是我正在使用的代码:

Here's the code I'm using:

#import <Cocoa/Cocoa.h>

@interface AppController : NSObject
{
    int fido;
}

@property (readonly, assign) int fido;

@end

#import "AppController.h"

@implementation AppController

@synthesize fido;

- (id)init
{
    [super init];
    [self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
    NSNumber *n = [self valueForKey:@"fido"];
    NSLog(@"fido = %@", n);
    return self;
}
@end

替代文本http://idisk.me.com/nevan/Public /Pictures/Skitch/Window-20091001-174352.png

推荐答案

AppController.h:

AppController.h:

@interface AppController : NSObject
{
        int fido;
}

@property (readonly, assign) int fido;
@end

导入"AppController.h"

@implementation AppController
@synthesize fido;
...
@end

这时,您已经声明AppController具有-fido方法,并且已经合成了该方法.没有-setFido:方法.那么,为什么下面的工作"呢?

At this point, you have declared that AppController has a -fido method and you have synthesized that method. There is no -setFido: method. So, why does the following "work"?

- (id)init
{
        if (self=[super init]) {
            [self setValue:[NSNumber numberWithInt:5] forKey:@"fido"];
            NSNumber *n = [self valueForKey:@"fido"];
            NSLog(@"fido = %@", n);
        }
        return self;
}

(顺便说一句,我修复了-init来实现正确的模式)

(BTW: I fixed your -init to implement the correct pattern)

之所以可行,是因为KVC遵循启发式来设置或获取值.对-setValue:forKey:的调用首先查找-setFoo:.如果找不到,它将查找实例变量foo并直接对其进行设置.

This works because KVC follows a heuristic to set or get the value. The call to -setValue:forKey: first looks for -setFoo:. If not found, it then looks for the instance variable foo and sets it directly.

请注意,如果将实例变量fido更改为_fido,则该设置将起作用,但是valueForKey会在调用综合方法时返回0(因为我使用的是64位,所以@synthesize合成一个fido实例变量.令人困惑,我知道.)

Note that if you change the instance variable fido to _fido, the set will work, but the valueForKey will return 0 as it calls the synthesized method (since I'm on 64 bit, the @synthesize synthesizes a fido instance variable. Confusing, I know.).

如果要将ivar的名称更改为bar,然后使用@synthesize foo=bar;,则代码将在运行时失败.

If you were to change the name of your ivar to bar and then use @synthesize foo=bar;, the code would fail at runtime.

您会看到:

2009-10-01 08:59:58.081 dfkjdfkjfjkfd[24099:903] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppController 0x20000e700> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fido.'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00007fff85b055a4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff85c5a0f3 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff85b5caf9 -[NSException raise] + 9
    3   Foundation                          0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
(
    0   CoreFoundation                      0x00007fff85b055a4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x00007fff85c5a0f3 objc_exception_throw + 45
    2   CoreFoundation                      0x00007fff85b5caf9 -[NSException raise] + 9
    3   Foundation                          0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434
    4   dfkjdfkjfjkfd                       0x0000000100000d96 -[AppController init] + 130

这篇关于为什么readonly属性仍然允许用KVC编写的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆