【问题标题】:Is it possible to override getters and setters for @dynamic properties in an NSManagedObject subclass?是否可以覆盖 NSManagedObject 子类中 @dynamic 属性的 getter 和 setter?
【发布时间】:2011-08-25 20:15:36
【问题描述】:

所以,我的情况是这样的:

我的 iOS 应用程序中有一个 NSManagedObject 子类,作为一个属性,我想存储一个 MKPolygon 对象的内容。我决定解决这个问题的方式(它是否有效可能是一个不同的问题)是将多边形属性声明为可转换对象,然后存储一个包含多边形点的 NSArray(作为 NSValue 对象)。

为此,我在我的模型对象上编写了几个便利类方法:

+ (NSArray *)coordsArrayFromMKPolygon:(MKPolygon *)polygon pointCount:(int)count
{
    CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * count);
    [polygon getCoordinates:coords range:NSMakeRange(0, count)];
    NSMutableArray *coordsArray = [NSMutableArray array];
    for (int i = 0; i < count; i++) {
        NSValue *coordVal = [NSValue valueWithBytes:&coords[i] objCType:@encode(CLLocationCoordinate2D)];
        [coordsArray addObject:coordVal];
    }
    free(coords);
    return [NSArray arrayWithArray:coordsArray];
}

+ (MKPolygon *)polygonFromCoordsArray:(NSArray *)coordsArray pointCount:(int)count
{
    CLLocationCoordinate2D *coords = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * count);
    for (int i = 0; i < count; i++) {
        CLLocationCoordinate2D coord;
        [[coordsArray objectAtIndex:i] getValue:&coord];
        coords[i] = coord;
    }
    free(coords);
    return [MKPolygon polygonWithCoordinates:coords count:count];
}

我可以在保存或加载模型实例之前在我的 MKPolygon 对象上调用这些方法,但我想覆盖模型本身中的动态 getter 和 setter,这样我就可以说类似 @987654322 的内容@(其中 polygon 是一个 MKPolygon 实例)。

我真正想要的是能够做这样的事情:

- (void)setTurf_bounds:(id)turf_bounds
{
    MKPolygon *poly = (MKPolygon *)turf_bounds;
    NSArray *coordsArray = [Turf coordsArrayFromMKPolygon:poly pointCount:[poly pointCount]];
    // Save the converted value into the @dynamic turf_bounds property
}

- (id)turf_bounds
{
    // grab the contents of the @dynamic turf_bounds property into say, NSArray *coordsArray
    return [Turf polygonFromCoordsArray:coordsArray pointCount:[coordsArray count]];
}

但到目前为止,我还没有快乐过。调用 [super setValue:coordsArray forKey:@"turf_bounds"] 或其对应的 getter 不起作用,尝试将其编写为 self.turf_bounds 也不起作用(它只是递归调用我重写的 setter)。

我是完全走错了路,还是只是遗漏了什么?

【问题讨论】:

    标签: ios core-data nsmanagedobject


    【解决方案1】:

    永远不要在 NSManagedObject 子类中调用 [super valueForKey:..]! (除非你自己在超类中实现它们) 而是使用原始访问器方法。

    来自ADC 的示例 getter/setter 实现:

    @interface Department : NSManagedObject
    @property(nonatomic, strong) NSString *name;
    @end
    
    @interface Department (PrimitiveAccessors)
    - (NSString *)primitiveName;
    - (void)setPrimitiveName:(NSString *)newName;
    @end
    
    
    @implementation Department
    
    @dynamic name;
    
    - (NSString *)name
    {
        [self willAccessValueForKey:@"name"];
        NSString *myName = [self primitiveName];
        [self didAccessValueForKey:@"name"];
        return myName;
    }
    
    - (void)setName:(NSString *)newName
    {
        [self willChangeValueForKey:@"name"];
        [self setPrimitiveName:newName];
        [self didChangeValueForKey:@"name"];
    }
    
    @end
    

    【讨论】:

    • 原始访问器 - 这就是我所缺少的,谢谢!另外,这种方法让我明确要求设置器使用 MKPolygon(或 MKMultiPoint 或 MKAnnotation),而不是作为 id 和强制转换传递。我认为我不应该调用 valueForKey,但我没有找到正确的替代方法。干杯:)
    • 这是否完全适用于覆盖超类中定义的动态属性?
    • 这个 will/didChangeValueForKey 约定早在引入@dynamic 属性之前就已经存在,并且是触发观察所必需的。如果您不观察属性,则无需使用这种实现。所以我会说这取决于用例。 (@Rivera 很抱歉一开始就恢复了您的更改,使用当前版本的 obj-c,声明 privimitive getter/setter 可能更清晰)
    • 你说:“永远不要在 NSManagedObject 子类中调用 [super valueForKey:..]!”。为什么是这样?出现了可怕的错误,我可以看到,但是为什么呢?
    • 它不能覆盖关系属性的设置器
    猜你喜欢
    • 2018-11-08
    • 1970-01-01
    • 2021-11-06
    • 2011-03-21
    • 2019-02-28
    • 1970-01-01
    • 2015-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多