2011-04-24 50 views
3

我在创建自己的子类NSData时遇到问题,我想要自定义description方法。即使是创建一个虚拟NSData子类:创建和使用虚拟NSData子类不起作用

@interface MyData : NSData {} 
@end 

@implementation MyData 
@end 

,并使用它会导致莫名其妙的错误(使用它永远不会退出,并控制某种方式返回到运行循环的功能)。我认为也许我有责任重写指定的初始化程序NSData(称为super实现),但是文档中没有提及。所以:

  • 什么是NSData的指定初始值设定项?
  • 我需要为NSData的一个虚拟子类写最小的最小值是多少?

回答

10

制作NSData的子类很困难,因为(如drewag noted)它是class cluster的成员。从Binary Data Programming Guide

...数据对象不是NSData的或NSMutableData类的实际情况下,反而是他们的私人的一个子类的实例。

当你做[[NSData alloc] initWith...]你不回NSData;你可能会回到NSConcreteData。非凡的可可爱有一个discussion and demonstration子类的集群。

最好的(也是最习惯的)选项可能是composition:你的自定义类应该只包含一个NSData ivar,并实现一个对该封闭对象进行操作的描述方法。

虽然drewag的回答在技术上是正确的,但这是一种在Cocoa类上使用的危险技术;它会覆盖description方法每NSData对象在程序中,无论是否直接创建它。

description方法的具体情况下,这可能没问题,但对于框架中其他对象更可能依赖的另一种方法,它可能会导致大量难以跟踪的问题。如果你确信没有其他办法,你应该只做这个。

这将是更好地创建带有前缀的类和方法:

@interface NSData (FX_Description) 
- (NSString *)FX_description; 
@end 

苹果文档specifically mention这一类重写的技术和建议反对:

因为在类别中声明的方法被添加到现有的类中,你需要非常小心方法名称。

如果在类别中声明的方法的名称与原始类中的方法相同,或者在同一类(甚至是超类)上的另一类中的方法相同,则行为未定义为哪种方法实现在运行时使用。

较早的文档版本接着说:

的一些类方法的存在很可能会导致在所有框架行为的变化。例如,如果在NSObject,的类别中覆盖windowWillClose:委托方法,则程序中的所有窗口委托会使用类别方法响应;所有NSWindow实例的行为可能会发生变化。您添加到框架类上的类别可能会导致行为中的神秘变化并导致崩溃。 [Emphasis mine。]

2

如果你想要的是覆盖单功能“描述”可以考虑使用“类别”来代替:

@interface NSData (MyData) 
-(NSString*)description; 
@end 

@implimentation NSData (MyData) 
-(NSString*)description 
{ 
    return @"something"; 
} 
@end 

然后,您可以在NSData的任何情况下使用该功能。

因为它是一个“类集群”,所以NSData的子类很困难。公共API将其视为一个类,但实际上它是隐藏子类的集合。您可以研究覆盖类集群,但几乎不需要它。另一种选择是使用NSData创建“MyData”类作为成员变量,而不是使用子类。