Objective c 方法调度中缺少哨兵
我想创建Objective c 方法调度中缺少哨兵,objective-c,cocoa,nsarray,subclass,Objective C,Cocoa,Nsarray,Subclass,我想创建NSMutableArray的子类,需要重写-initWithObjects:方法 但是如何称呼[超级xxx] - (id) initWithObjects:(id)firstObj, ... { [super initWithObjects:firstObj]; // Error: Missing sentinel in method dispatch // Error: The result of a delegate init call must be immedi
NSMutableArray
的子类,需要重写-initWithObjects:
方法
但是如何称呼[超级xxx]
- (id) initWithObjects:(id)firstObj, ... {
[super initWithObjects:firstObj]; // Error: Missing sentinel in method dispatch
// Error: The result of a delegate init call must be immediately returned or assigned to "self"
}
谢谢。试试看
self = [super initWithObjects:firstObj,nil];
你不能。如中所述: 您可能希望为您的子类实现一个初始值设定项,即 适用于子类正在管理的备份存储。安萨里酒店 类没有指定的初始值设定项,因此您的初始值设定项需要 仅调用
super
的init
方法。NSArray类采用
NSCopying、NSMutableCopying和NSCoding协议;如果你愿意
通过复制或编码创建的自定义子类的实例,
重写这些协议中的方法
因此您可以分配self=[super init]
并将初始化器中的对象添加到结果对象中。实际上,由于NSArray
的实现方式,调用任何-initWith…
方法都可能返回不同NSArray
子类的实例
请注意,本文档还讨论了子类化
NSArray
的替代方法,这些方法可能更简单、更可靠或在其他方面更好。子类化NSArray
/NSMutableArray
与子类化大多数类不同NSArray
是一个类群集,请参阅NSArray
文档
现在,对于您的特定问题,子类化va_list
方法有点棘手,有很多方法可以处理这个问题。最安全的方法是将你的va_列表
处理成一个NSArray
并将其传递到另一个方法中,该方法可以处理你想要的任何事情。另一种稍微不那么便携、稍显粗糙的方法是在堆栈上创建一个新的va_列表
list来传递
id __unsafe_unretained * stack = (typeof(stack))calloc(numOfObjects, sizeof(id));
//filloutStack
[super initWithObjects:*stack, nil];
free(stack);
对Apple集合类进行子类化并不困难——如果您使用一个小技巧(另请参见:) 在面向对象的设计中,子类是一种“is-A”关系。但也有“has-a”关系,即包装器 如果您试图通过使用纯is-a关系来创建NSArray的子类,我想,这会有点困难,因为您必须进行C级内存管理 但是,如果同时添加has-a关系或:创建包装器,则可以非常轻松地进行子封装:只需使自定义数组类具有常规NSArray的成员即可。现在,通过将调用转发到成员对象来覆盖其方法。我展示了这个 但是您将看到,我没有正确地实现您提到的方法,但是我提出了一个错误。原因是:这个方法是一个可变的方法,它有一个可变数量的对象,你可以传入-要处理这个问题,你需要做一些工作 对你来说,如果使用它有一个技巧,它可能看起来像
- (id) initWithObjects:(id)firstObj, ... {
if (self = [super init]) {
_realArray = [[NSMutableArray alloc] initWithCapacity:1];
}
va_list args;
va_start(args, firstObj);
for (id obj = firstObj; obj != nil; obj = va_arg(args, id))
{
[self.realArray addObject:obj];
}
va_end(args);
return self;
}
然后,“missing sentinel”消息指的是丢失的nil终止。事实上,根据维基百科所有知识的字体:
在Objective-C中终止可变长度参数列表的nil的名称
另外:Sentinel节点,表示数据结构结尾的对象
另外:Sentinel值,用于终止循环的值
另外:在网络协议(如Bisync)中,sentinel值指示帧的开始和结束位置您解决了委托问题,但仍然存在缺少sentinel的警告…我尝试了
self=[super initWithObjects:firstObj,nil]代码>和警告消失,但调用此子类时数组中的对象是否会丢失?是的,很抱歉,您必须在末尾添加nil。对不起,我不明白你的问题…@BenLu:请看jlehr的答案和我对它的评论。这会起作用,但它只会(尝试)用第一个对象初始化数组,而不会初始化任何其他对象。不管传递了多少个对象,充其量只能得到一个包含不超过一个对象的数组。