问题描述
我想创建一个NSInputStream的子类。简单来说,我试着编写代码如下:
@interface SeekableInputStream:NSInputStream
{
NSUInteger startOffset;
NSUInteger totalReadLen;
}
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
- (BOOL)hasBytesAvailable;
- (void)open:(NSUInteger)offset;
@end
,我使用类如下。 / p>
SeekableInputStream * stm = [[SeekableInputStream alloc] initWithURL:url];
然后,在运行时,我可以遇到以下错误信息。
- [SeekableInputStream initWithURL:]:无法识别的选择器发送到实例0x10018ff30
我没有覆盖initWithURL有意的父母的方法。
根据我的知识,派生类可以使用父类的方法,不是吗?
不能继承像initWithURL这样的扩展方法吗? p>
有没有人告诉我如何做NSInputStream的子类化?
从NSStream.h
// NSStream是一个抽象类,将通用API封装到NSInputStream和NSOutputStream。
// NSInputStream和NSOutputStream的子类必须也实现这些方法。
@interface NSStream:NSObject
- (void)open;
- (void)close;
- (id< NSStreamDelegate>)delegate;
- (void)setDelegate:(id< NSStreamDelegate>)delegate;
//默认情况下,流是其自己的委托,NSInputStream和NSOutputStream的子类必须保持此合同。 [someStream setDelegate:nil]必须恢复此行为。像往常一样,代表不保留。
- (id)propertyForKey:(NSString *)key;
- (BOOL)setProperty:(id)属性forKey:(NSString *)key;
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (NSStreamStatus)streamStatus;
- (NSError *)streamError;
@end
// NSInputStream是一个抽象类,表示读取流的基本功能。
//需要子类来实现这些方法。
@interface NSInputStream:NSStream
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
//将长度字节读入所提供的缓冲区,该缓冲区必须至少为大小len。返回读取的实际字节数。
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
//在O(1)中返回一个指向buffer中的缓冲区的指针,并通过在len中引用多少字节可用。此缓冲区只有在下一个流操作之前有效。如果不适合流类型,子类可能返回NO。如果缓冲区不可用,则可能返回NO。
- (BOOL)hasBytesAvailable;
//如果流有可用的字节或者如果不实际读取就不可能告诉它,则返回YES。
@end
正如你所看到的,没有initWithURL函数。所以,你的 super
不工作,因为它真的不存在。正如MrTJ所说,它是一个类别类。它定义在:
// NSInputStreamExtensions类别包含用于处理NSInputStreams的附加初始化程序和便利例程。
@interface NSInputStream(NSInputStreamExtensions)
- (id)initWithURL:(NSURL *)url NS_AVAILABLE(10_6,4_0);
所以,我想如果你在你的子类中使用它,它可以工作。
#import< Foundation / NSStream.h>
您需要导入类别。记住你不能子类化一个类别,只是覆盖它,不能调用(或如果可以,我不知道如何)
I'd like to make a subclass of NSInputStream. Simply, I tried to code just like the following,
@interface SeekableInputStream : NSInputStream
{
NSUInteger startOffset;
NSUInteger totalReadLen;
}
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
- (BOOL)hasBytesAvailable;
- (void)open:(NSUInteger)offset;
@end
and, I used the class like the following.
SeekableInputStream *stm = [[SeekableInputStream alloc] initWithURL:url];
Then, in runtime, I could meet the following error message.
-[SeekableInputStream initWithURL:]: unrecognized selector sent to instance 0x10018ff30
I didn't override initWithURL for using parent's method purposely.Based on my knowledge, derived class can uses method of parent class, isn't it?
Can not an extension method like initWithURL be inherited?
Is there anybody inform me how to do subclassing of NSInputStream?
From NSStream.h
// NSStream is an abstract class encapsulating the common API to NSInputStream and NSOutputStream.
// Subclassers of NSInputStream and NSOutputStream must also implement these methods.
@interface NSStream : NSObject
- (void)open;
- (void)close;
- (id <NSStreamDelegate>)delegate;
- (void)setDelegate:(id <NSStreamDelegate>)delegate;
// By default, a stream is its own delegate, and subclassers of NSInputStream and NSOutputStream must maintain this contract. [someStream setDelegate:nil] must restore this behavior. As usual, delegates are not retained.
- (id)propertyForKey:(NSString *)key;
- (BOOL)setProperty:(id)property forKey:(NSString *)key;
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (NSStreamStatus)streamStatus;
- (NSError *)streamError;
@end
// NSInputStream is an abstract class representing the base functionality of a read stream.
// Subclassers are required to implement these methods.
@interface NSInputStream : NSStream
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len;
// reads up to length bytes into the supplied buffer, which must be at least of size len. Returns the actual number of bytes read.
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len;
// returns in O(1) a pointer to the buffer in 'buffer' and by reference in 'len' how many bytes are available. This buffer is only valid until the next stream operation. Subclassers may return NO for this if it is not appropriate for the stream type. This may return NO if the buffer is not available.
- (BOOL)hasBytesAvailable;
// returns YES if the stream has bytes available or if it impossible to tell without actually doing the read.
@end
As you can see, there are no initWithURL function. So, your super
do not work, because it really don't exist. Like MrTJ says, it is a category class. It is defined in:
// The NSInputStreamExtensions category contains additional initializers and convenience routines for dealing with NSInputStreams.
@interface NSInputStream (NSInputStreamExtensions)
- (id)initWithURL:(NSURL *)url NS_AVAILABLE(10_6, 4_0);
So, I think if you use it in your subclass, it can work.
#import <Foundation/NSStream.h>
You need to import the category. Remember you CAN'T subclass a category, just overwrite it and can't call then (or if can, I don't know how)
这篇关于如何创建NSInputStream的子类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!