繁体   English   中英

Objective-C Custom Getter / Setter

[英]Objective-C Custom Getter / Setter

我正在使用由Xcode自动生成的以下NSManagedObject:

@interface Portion :  NSManagedObject  
{
}

@property (nonatomic, retain) NSNumber * volume;

我想创建一个自定义getter / setter,根据用户设置的内容在ml / oz之间进行转换,数据库始终存储相同的值,并自动转换为首选单位。 我最近的尝试看起来像这样:

#import "Portion.h"
#import "SettingHandler.h"

#define MILLILITERS_PER_OUNCE 29.5735296

@implementation Portion 

@dynamic volume;

- (void) setVolume:(NSNumber *) number {
    if ([SettingHandler getUnitsTypeShort] == @"oz") {
        [self setValue:number forKey:@"volume"];
    } else {
        [self setValue:[NSNumber numberWithFloat:[number floatValue] * MILLILITERS_PER_OUNCE] forKey:@"volume"];
    }
}

- (NSNumber *) volume {
    if ([SettingHandler getUnitsTypeShort] == @"oz") {
        return [self valueForKey:@"volume"];
    } else {
        return [NSNumber numberWithDouble: [[self valueForKey:@"volume"] floatValue] * MILLILITERS_PER_OUNCE];
    }
}

setVolume调用最终调用自身导致无限循环。 我猜有一种方法可以做到这一点,但我不知道它是什么,有什么想法吗?

很抱歉玩魔鬼的拥护者,但IMO,似乎你正在尝试解决一个值如何以低于某个级别的方式向用户显示(在模型对象本身中;请参阅模型 - 视图 - 控制器设计模式 )。 为什么不使用在视图级别工作更多的格式化程序来帮助将原始NSNumber值格式化为将呈现给用户的字符串?

然后,您将拥有一个可重复使用的类,您可以在任何使用表示卷的数字值的地方使用该类。 格式化程序将存储“unitsType”值,以便它知道如何正确格式化传入的数字。

我使用我现有的格式化程序MDFileSizeFormatter做了一个快速版本作为起点:

#import <Foundation/Foundation.h>

enum {
    MDVolumeFormatterMetricUnitsType            = 1,
    MDVolumeFormatterOurStupidAmericanUnitsType = 2,
    MDVolumeFormatterDefaultUnitsType = MDVolumeFormatterMetricUnitsType
};

typedef NSUInteger MDVolumeFormatterUnitsType;


@interface MDVolumeFormatter : NSFormatter {
    MDVolumeFormatterUnitsType    unitsType;
    NSNumberFormatter            *numberFormatter;
}
- (id)initWithUnitsType:(MDVolumeFormatterUnitsType)aUnitsType;

@property (assign) MDVolumeFormatterUnitsType unitsType;

@end

然后是.m文件:

#import "MDVolumeFormatter.h"

#define MILLILITERS_PER_OUNCE 29.5735296

@implementation MDVolumeFormatter

@synthesize unitsType;

- (id)init {
    return [self initWithUnitsType:MDVolumeFormatterDefaultUnitsType];
}

- (id)initWithUnitsType:(MDVolumeFormatterUnitsType)aUnitsType {
    if (self = [super init]) {
        numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setFormat:@"#,###.#"];
        [self setUnitsType:aUnitsType];
    }
    return self;
}

- (void)dealloc {
    [numberFormatter release];
    [super dealloc];
}

- (NSString *)stringForObjectValue:(id)anObject {
    if ([anObject isKindOfClass:[NSNumber class]]) {
        NSString *string = nil;
        if (unitsType == MDVolumeFormatterMetricUnitsType) {
            string = [[numberFormatter stringForObjectValue:
                       [NSNumber numberWithFloat:
                        [(NSNumber *)anObject floatValue] * MILLILITERS_PER_OUNCE]]
                      stringByAppendingString:@" mL"];

        } else {
            string = [[numberFormatter stringForObjectValue:anObject] stringByAppendingString:@" oz"];
        }
        return string;
    }
    return nil;
}

@end

这可能会扩展为对传入值进行测试并自动确定适当的音量单位。 例如,如果floatValue为16.0,则可以使用if then逻辑返回“2.0杯”而不是16盎司的字符串。

查看核心数据编程指南中的“自定义属性和一对一关系访问器方法” 基本上,您应该使用原始getter / setter方法来访问/更改值并使用KVO通知包装这些调用。

您需要为原始访问器添加声明:

@interface Portion (PrimitiveAccessors)
- (NSNumber *)primitiveVolume;
- (void)setPrimitiveVolume:(NSNumber *)number; 
@end

然后你需要替换每次出现的:

[self setValue:number forKey:@"volume"];

有:

[self willChangeValueForKey:@"volume"];
[self setPrimitiveVolume:number];
[self didChangeValueForKey:@"volume"];

并在getter中进行相应的更改。

尝试使用[self setPrimitiveValue:number forKey:@"volume"]; 代替。

我建议另一种方法。 决定规范表示 - 盎司或毫升。 这就是实际存储的卷。 然后声明以下getter / setter:

- (void) setOunces:(double)ounces;
- (double) ounces;

- (void) setMilliliters:(double)milliliters;
- (double*) milliliters;

如果规范体积是毫升,那么:

- (void) setOunces:(double)ounces
{
[self setVolume:[NSNumber numberWithDouble:(ounces* MILLILITERS_PER_OUNCE)]];
}

- (double) ounces
{
return [[self volume] doubleValue]/MILLILITERS_PER_OUNCE;
}

- (void) setMilliliters:(double)milliliters
{
[self setVolume:[NSNumber numberWithDouble:milliliters]];
}

- (double) milliliters
{
return [[self volume] doubleValue];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM