我正在尝试编写NSOutputStream的子类来执行一个非常简单的函数 - 跟踪发送到流的总字节数。但是,我遇到了初始化函数实例的意外问题。这是代码:
#import <Foundation/Foundation.h>
@interface TrackingOutputStream : NSOutputStream {
unsigned long long bytesWritten;
}
@property (readonly) unsigned long long bytesWritten;
@end
---------------------------
#import "TrackingOutputStream.h"
@implementation TrackingOutputStream
@synthesize bytesWritten;
- (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)length {
NSInteger written = [super write:buffer maxLength:length];
bytesWritten += written;
return written;
}
@end
但是,当我尝试初始化这个类时:
TrackingOutputStream *os = [[[TrackingOutputStream alloc] initToFileAtPath:@"/tmp/test" append:NO] autorelease];
我收到以下错误:
-[TrackingOutputStream initToFileAtPath:append:]: unrecognized selector sent to instance 0x101a187e0
我尝试在调用super的类中添加一个显式构造函数,但它没有任何区别(因为它不应该)。
答案 0 :(得分:2)
如果您正在使用需要NSOutputStream实例的API,那么实现NSOutputStream的所有方法以将它们转发到包装(委托)实例可能很麻烦。您可以使用方法转发方法,允许您在不编写所有包装器方法的情况下添加行为。这涉及编写forwardingTargetForSelector:
和respondsToSelector:
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (class_respondsToSelector([self class], aSelector)) { return self; }
if ([self.delegate respondsToSelector:aSelector]) { return self.delegate; }
return [super forwardingTargetForSelector:aSelector];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
if (class_respondsToSelector([self class], aSelector)) { return YES; }
if ([self.delegate respondsToSelector:aSelector]) { return YES; }
return [super respondsToSelector:aSelector];
}
有关详细说明,请参阅有关使用Objective-C duck-typing to more easily subclass NSOutputStream的博客文章。或者查看https://github.com/jwb/ObjC-DuckType
上的示例答案 1 :(得分:1)
NSOutputStream
具有非常具体的子类化要求,这些要求记录在class's documentation中。
请注意,文档明确指出您必须完全实现适当的初始化程序。即你不能按照你的描述来改变行为。至少,不容易。
相反,创建一个类,其实例包装NSOutputStream
的实例并添加您想要的行为。
答案 2 :(得分:0)
作为补充说明,应该可以使用- propertyForKey:
的{{1}}检索有关书面数据的信息。看看
NSStream
属性键。