可以在自定义init方法中调用吗?

我有一个MKPolyline子类,我想实现NSCoding ,即

 @interface RSRoutePolyline : MKPolyline <NSCoding> 

我问了一个关于编码c数组的最佳方法,并得到了一个很好的答案 。 但是,在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; } 

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

但MKPolyline没有方法,也没有init。 Objective C是告诉你,你不能inheritance它。

相反,如WDUKbuild议,定义你自己的class级。 它跟踪你的列表点的点,并pipe理NSCoding保存和恢复它们的需要。

  @interface RSPolyline: NSObject<NSCoding> - (id) initWithPoints: (NSArray*) points; - (id) initWithCoder:(NSCoder *)aDecoder; - (void) encodeWithCoder:(NSCoder *)aCoder; - (MKPolyline*) polyLine; @end 

您的类可以根据请求生成多段线,如果性能问题可能会caching结果。

一般来说,先不要inheritance。 当你想扩大和提高一个class级,首先考虑作文。

不要打电话给[super init] ,这对于我的编程思路并不好。 如果不是自己调用超级,那不是一个真正的子类; 只是一个依赖于调用便利构造函数的副作用的组合的混蛋。 说到这一点,我相信你描述的方法是行得通的,但是这与Objective-C的良好编程及其惯例背道而驰。

我build议使用MKPolyLine作为MKPolyLine实例,并使用一个类别添加所需的额外铃声和哨子。 至于添加额外的实例variables等,你可以使用关联的对象。 这个概念的介绍可以在这里find ,这个SO问题解决了他们与类别的使用: 如何在对象内使用objc_setAssociatedObject / objc_getAssociatedObject?

虽然通常允许在init方法中创build和返回不同的对象,但是该行有三个问题(如下所述)。 相反,我build议覆盖pointspointCount属性,以便返回存储在实例variables中的值,如果实例variables为空,则在那里调用超级实现。 然后,您的初始化程序只是设置这些实例variables,以便它们将被使用。

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

第一个问题是你正在创build一个新的对象,但不能释放旧的对象,这意味着你正在泄漏它。 你应该把结果存储在一个不同的variables中,然后释放self,然后返回结果(你不需要自己存储它)。

其次, polylineWithPoints:count:返回一个自动释放的对象,但是initWithCoder:应该返回一个保留的对象。 除非有另外的保留,否则可以在你使用的时候释放它。

如果这是唯一的问题,你可以这样解决:

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

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