1

我有一个MKPolyline我想实现的 subblas NSCoding,即

@interface RSRoutePolyline : MKPolyline <NSCoding>

我问了一个关于对 c 数组进行编码的最佳方法的问题,并得到了很好的答案。但是,在 上没有定义 init 方法MKPolyline,即除了它的类方法之外,没有其他方法可以给它提供数据polylineWithPoints:points

这段代码我的评论可以吗?

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    MKMapPoint *points = self.points;
    NSUInteger pointCount = self.pointCount;

    NSData *pointData = [NSData dataWithBytes:points length:pointCount * sizeof(MKMapPoint)];
    [aCoder encodeObject:pointData forKey:@"points"];
    [aCoder encodeInteger:pointCount forKey:@"pointCount"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    NSData* pointData = [aDecoder decodeObjectForKey:@"points"];
    NSUInteger pointCount = [aDecoder decodeIntegerForKey:@"pointCount"];

    // Edit here from @ughoavgfhw's comment
    MKMapPoint* points = (MKMapPoint*)[pointData bytes];

    // Is this line ok?
    self = (RSRoutePolyline*)[MKPolyline polylineWithPoints:points count:pointCount];

    return self;
}
4

3 回答 3

2

不打电话很脏[super init],而且这对我的良好编程理念来说不是好兆头。如果不自己调用 super ,它就不是真正的子类;只是依赖于调用便利构造函数的副作用的组合的混蛋。这么说,我相信你描述的方法可以正常工作,但它违背了良好的 Objective-C 编程及其约定。

我的建议是MKPolyLine作为一个MKPolyLine实例,并使用一个类别来添加你需要的额外的花里胡哨。至于添加额外的实例变量等,您可以使用关联对象。可以在这里找到对这个概念的介绍,这个 SO 问题解决了它们与类别的使用:如何在对象中使用 objc_setAssociatedObject/objc_getAssociatedObject?

于 2013-02-16T19:46:50.993 回答
2

您应该在 NSObject 的任何子类上调用 init 方法。由于 MKPolyline 是一个 NSObject,你应该初始化它。

但是 MKPolyline 没有方法,也没有 init。这是Objective C的意思是告诉你你不能继承它。

相反,正如 WDUK 建议的那样,定义您自己的类。它跟踪您的列表点,并管理 NSCoding 以根据需要保存和恢复它们。

 @interface RSPolyline: NSObject<NSCoding>

 - (id) initWithPoints: (NSArray*) points;
 - (id) initWithCoder:(NSCoder *)aDecoder;
 - (void) encodeWithCoder:(NSCoder *)aCoder;

 - (MKPolyline*) polyLine;

 @end

您的类可以根据请求生成折线,如果性能有问题,可能会缓存结果。

作为一项规则,不要先获得继承权。当你想扩展和改进一门课时,首先要考虑作文。

于 2013-02-16T20:01:56.997 回答
1

虽然通常允许在 init 方法中创建和返回不同的对象,但该行存在三个问题(如下所述)。相反,我建议重写pointsandpointCount属性,以便您可以返回存储在实例变量中的值,并在实例变量为空时调用超级实现。然后,您的初始化程序只需设置这些实例变量,以便使用它们。

- (MKMapPoint *)points {
    if(myPointsIvar == NULL) return [super points];
    else return myPointsIvar;
}
// similarly for pointCount

第一个问题是您正在创建一个新对象,但没有释放旧对象,这意味着您正在泄漏它。您应该将结果存储在不同的变量中,然后释放 self,然后返回结果(您不需要将其存储在 self 中)。

其次,polylineWithPoints:count:返回一个自动释放的对象,但initWithCoder:应该返回一个保留的对象。除非它上面有另一个保留,否则它可能会在您仍在使用它时被释放。

如果这些是唯一的问题,您可以像这样解决这两个问题:

MKPolyline *result = [MKPolyline polylineWithPoints:points count:pointCount];
[self release];
return [result retain];

但是,还有第三个问题不能这么容易解决。polylineWithPoints:count:不返回RSRoutePolyline对象,并且它返回的对象可能与您的子类的方法不兼容(例如,它可能不支持 NSCoding)。真的没有办法解决这个问题,所以你不能使用polylineWithPoints:count:.

于 2013-02-16T19:54:30.653 回答