我如何通用地使用KVC更新字段?

时间:2022-06-08 07:24:01

Say I have the following Objective-C class:

假设我有以下Objective-C类:

@interface Foo {
     int someNumber;
     NSString *someString;
}

and for reasons I won't get into here, I want to use KVC to update, in a generic fashion, the values for those variables:

由于我不会讲到这里的原因,我想用KVC来更新这些变量的值。

[f setValue:object forKey:@"someNumber"];

or

[f setValue:object forKey:@"someString"];`

If object is a string and I'm updating the someNumber variable, it seems that I need to know to use an NSNumberFormatter to get an NSNumber and then Cocoa automatically converts that to an int inside setValue:forKey:.

如果对象是字符串,而我正在更新someNumber变量,那么我似乎需要知道如何使用NSNumberFormatter来获取NSNumber,然后Cocoa会自动将其转换为setValue:forKey:中的int类型。

Is there any way to avoid this custom code and have Cocoa infer the conversion to an int from a string, or do I need to catch this situation each time and handle it myself?

有什么方法可以避免这种自定义代码并让Cocoa从字符串推断到int的转换,或者我需要每次捕获这种情况并自己处理它吗?

3 个解决方案

#1


1  

You should do the conversion yourself with a number formatter, it gives you finer control than anything that the framework might consider to be appropriate. It is also, probably, not a good idea to use a single instance of an object to update the values for your ivars. More appropriately, you could perform your update based on the class of the object (providing you are not storing in an id by querying the runtime as to the class of the object by means of object_getClassName. More information is available in the Objective-C 2.0 Runtime Reference. But in general, you will likely find bugs in your code as a result of doing things that way.

您应该自己使用数字格式化程序进行转换,它提供了比框架认为合适的任何东西更好的控制。使用对象的单个实例更新ivars的值也可能不是一个好主意。更合适的是,您可以基于对象的类执行更新(提供您没有通过使用object_getClassName查询对象的运行时来存储id)。更多信息可以在Objective-C 2.0运行时引用中获得。但是通常,您可能会在代码中发现bug,因为这样做的结果。

#2


2  

The following code should handle the conversion automatically, as long as the object parameter is a member of a class that implements integerValue.

以下代码应该自动处理转换,只要对象参数是实现integerValue的类的成员。

Note that both NSNumber and NSString implement this method.

注意,NSNumber和NSString都实现了这个方法。

- (void)setValue:(id)object forKey:(NSString *)key
{
    if ([key isEqual:@"someNumber"])
    {
        someNumber = [object integerValue];
    }
    //...
}

edit: (side note): You can avoid writing the method yourself by using objective-c properties. The default implementation of setValue:forKey: will do the work for you, as long as you create properties for someNumber and someString.

编辑:(附注):您可以通过使用objective-c属性避免自己编写方法。setValue的默认实现:forKey:只要您为someNumber和someString创建属性,就可以为您完成工作。

#3


1  

I'm with wisequark on this one. I think of setValue:forKey: as equivalent to calling the setter directly. If you had a method:

我同意维舍夸克的观点。我认为setValue:forKey:等同于直接调用setter。如果你有一个方法:

- (void)setSomeValue:(NSInteger)aValue

You wouldn't expect to be able to pass in an NSString and hope the method can figure it out.

您不会期望能够传入NSString并希望该方法能够解决它。

Put another way, a key value gives you access to a property, and that property has a type. When using KVC, numbers just get wrapped in an NSNumber object so that there's only one setValue:forKey: method. Therefore, I say it's always the calling code's responsibility to package up the string in an NSNumber object.

换句话说,键值提供对属性的访问,该属性有一个类型。当使用KVC时,数字会被封装在一个NSNumber对象中,这样就只有一个setValue:forKey:方法。因此,我说在NSNumber对象中打包字符串始终是调用代码的责任。

It's times like these I lament that Cocoa Touch doesn't support bindings. Bindings would allow you to add a value transformer that could handle the transformation from string to number automatically for you. Maybe in the next version!

像这样的时候,我哀叹Cocoa Touch不支持绑定。绑定允许您添加一个值转换器,该转换器可以自动处理从字符串到数字的转换。也许在下一个版本中!

#1


1  

You should do the conversion yourself with a number formatter, it gives you finer control than anything that the framework might consider to be appropriate. It is also, probably, not a good idea to use a single instance of an object to update the values for your ivars. More appropriately, you could perform your update based on the class of the object (providing you are not storing in an id by querying the runtime as to the class of the object by means of object_getClassName. More information is available in the Objective-C 2.0 Runtime Reference. But in general, you will likely find bugs in your code as a result of doing things that way.

您应该自己使用数字格式化程序进行转换,它提供了比框架认为合适的任何东西更好的控制。使用对象的单个实例更新ivars的值也可能不是一个好主意。更合适的是,您可以基于对象的类执行更新(提供您没有通过使用object_getClassName查询对象的运行时来存储id)。更多信息可以在Objective-C 2.0运行时引用中获得。但是通常,您可能会在代码中发现bug,因为这样做的结果。

#2


2  

The following code should handle the conversion automatically, as long as the object parameter is a member of a class that implements integerValue.

以下代码应该自动处理转换,只要对象参数是实现integerValue的类的成员。

Note that both NSNumber and NSString implement this method.

注意,NSNumber和NSString都实现了这个方法。

- (void)setValue:(id)object forKey:(NSString *)key
{
    if ([key isEqual:@"someNumber"])
    {
        someNumber = [object integerValue];
    }
    //...
}

edit: (side note): You can avoid writing the method yourself by using objective-c properties. The default implementation of setValue:forKey: will do the work for you, as long as you create properties for someNumber and someString.

编辑:(附注):您可以通过使用objective-c属性避免自己编写方法。setValue的默认实现:forKey:只要您为someNumber和someString创建属性,就可以为您完成工作。

#3


1  

I'm with wisequark on this one. I think of setValue:forKey: as equivalent to calling the setter directly. If you had a method:

我同意维舍夸克的观点。我认为setValue:forKey:等同于直接调用setter。如果你有一个方法:

- (void)setSomeValue:(NSInteger)aValue

You wouldn't expect to be able to pass in an NSString and hope the method can figure it out.

您不会期望能够传入NSString并希望该方法能够解决它。

Put another way, a key value gives you access to a property, and that property has a type. When using KVC, numbers just get wrapped in an NSNumber object so that there's only one setValue:forKey: method. Therefore, I say it's always the calling code's responsibility to package up the string in an NSNumber object.

换句话说,键值提供对属性的访问,该属性有一个类型。当使用KVC时,数字会被封装在一个NSNumber对象中,这样就只有一个setValue:forKey:方法。因此,我说在NSNumber对象中打包字符串始终是调用代码的责任。

It's times like these I lament that Cocoa Touch doesn't support bindings. Bindings would allow you to add a value transformer that could handle the transformation from string to number automatically for you. Maybe in the next version!

像这样的时候,我哀叹Cocoa Touch不支持绑定。绑定允许您添加一个值转换器,该转换器可以自动处理从字符串到数字的转换。也许在下一个版本中!