如何创建NSOutputStream的子类

时间:2012-07-13 03:42:50

标签: objective-c subclassing nsoutputstream

我正在尝试编写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的类中添加一个显式构造函数,但它没有任何区别(因为它不应该)。

3 个答案:

答案 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属性键。