我有一个MKPolyline
子类,我想实现NSCoding
,即
@interface RSRoutePolyline : MKPolyline <NSCoding>
I asked a question on the best way to encode the c-array and got an excellent answer。但是,MKPolyline
上没有定义init方法,即除了类方法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;
}
答案 0 :(得分:2)
如果不打电话给[super init]
那就太脏了,而且我对好的编程想法并不好。没有自己超级称呼,它不是一个真正的子类;只是组合的混合,依赖于调用方便构造函数的副作用。说这个,我相信你描述的方法会运行正常,但它违背了良好的Objective-C编程及其惯例。
我建议将MKPolyLine
用作MKPolyLine
个实例,并使用类别添加您需要的额外铃声和口哨声。至于添加额外的实例变量等,您可以使用关联的对象。这个概念的介绍可以是found here,这个SO问题解决了它们与类别的使用:How do I use objc_setAssociatedObject/objc_getAssociatedObject inside an object?
答案 1 :(得分: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
您的类可以根据请求生成折线,如果性能有问题,可能会缓存结果。
通常,不要先进行继承。当你想扩展和改进一个类时,首先考虑组合。
答案 2 :(得分:1)
虽然通常允许在init方法中创建和返回不同的对象,但该行有三个问题(如下所述)。而不是这样,我建议覆盖points
和pointCount
属性,以便您可以返回存储在实例变量中的值,并在实例变量为空时调用那里的超级实现。然后,您的初始化程序只是设置这些实例变量,以便它们将被使用。
- (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:
。