【问题标题】:subclassing NSStream [duplicate]子类化 NSStream [重复]
【发布时间】:2012-12-02 02:58:19
【问题描述】:

我正在尝试继承 NSInputStream 和 NSOutputStream 以跟踪我传递给服务器的命令。这样,当我收到来自服务器的响应时,我知道它是对哪个命令的响应。当我尝试在子类中设置命令字符串时,出现无法识别的选择器错误。

子类:

PCFInputStream.h

#import <Foundation/Foundation.h>

@interface PCFInputStream : NSInputStream
@property (nonatomic, strong) NSString *command;
@end

PCFOutputStream.h

#import <Foundation/Foundation.h>

@interface PCFOutputStream : NSOutputStream
@property (nonatomic, strong) NSString *command;
@end

.m 文件只是合成了 command 属性,所以我可以调用 setCommand:

这是我在其中使用的类:

 //instance vars in my class
 PCFInputStream *inputStream;
 PCFOutputStream *outputStream;


-(void)followClass:(id)sender
{
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef) SERVER_ADDRESS, PORT,     &readStream, &writeStream);
    inputStream = (__bridge_transfer PCFInputStream *)readStream;
    outputStream = (__bridge_transfer PCFOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream setCommand:[NSString stringWithFormat:@"%d,%@",[sender tag], [class classTitle]]];
    [inputStream open];
    NSString *str = [NSString stringWithFormat:@"_ADD_CLASS*%@*%@*%@*%@;", [class CRN], deviceToken, [class classLink],[class courseNumber]];
    [outputStream setCommand:str];
    [outputStream open];
}

这是我在运行该行时遇到的错误

[inputStream setCommand:[NSString stringWithFormat:@"%d,%@",[sender tag], [class classTitle]]];

-[__NSCFInputStream setCommand:]: unrecognized selector sent to instance 0x1e691170
2012-12-01 21:56:20.777 PCF[15610:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFInputStream setCommand:]: unrecognized selector sent to instance 0x1e691170'
*** First throw call stack:
(0x3a1b73e7 0x39043963 0x3a1baf31 0x3a1b964d 0x3a111208 0xfa267 0x39585047 0x39584ffb 0x39584fd5 0x3958488b 0x39584d79 0x394a3441 0x3a18c941 0x3a18ac39 0x3a18af93 0x3a0fe23d 0x3a0fe0c9 0x3743733b 0x394ee291 0x100005 0xe7d48)
libc++abi.dylib: terminate called throwing an exception

有人可以为我推荐一个简单的解决方案吗?我尝试将 NSStreamInput 实例和我的 NSString* 命令包装到另一个类中,但这对我的目的不起作用。

谢谢!

【问题讨论】:

    标签: objective-c ios cocoa-touch


    【解决方案1】:

    您不能只将NSInputStream 转换为PCFInputStream。该对象必须创建为PCFInputStream,而CFStreamCReatePairWithSocketToHost 不会这样做。

    您可以使用associated objectcommand 属性附加到类别中的NSInputStream。分类界面如下:

    @interface NSInputStream (PCFCommand)
    @property (nonatomic) NSString *pcf_command;
    @end
    

    你可以这样实现它:

    #import <objc/runtime.h>
    
    @implementation NSInputStream (PCFCommand)
    
    static int kPCFCommandKey;
    
    - (NSString *)pcf_command {
        return objc_getAssociatedObject(self, &kPCFCommandKey);
    }
    
    - (void)setPcf_command:(NSString *)pcf_command {
        objc_setAssociatedObject(self, &kPCFCommandKey, [pcf_command copy],
            OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    @end
    

    【讨论】:

    • 嗨,你的例子很有帮助。我只是不知道该声明的确切位置..我以前从未使用过类别。
    • 从菜单栏中选择新建 > 文件。然后从 Cocoa Touch 模板中选择 Objective-C 类别。将类别命名为 PCFCommand 并使其成为 NSInputStream 上的类别。您需要在要访问该属性的任何文件中导入NSInputStream+PCFCommand.h。重复NSOutputStream
    • 完美。我刚刚在您输入时发现了这个。找不到方法“objc_getAssociatedObject”。常量 'OBJC_ASSOCIATION_RETAIN_NONATOMIC' 也不起作用。
    • 我已经编辑了我的答案。您需要导入&lt;objc/runtime.h&gt;
    • 哈哈,你的评论和我要说的完全一样,没关系。哈哈谢谢!
    【解决方案2】:

    CFStreamCreatePairWithSocketToHost 创建一个 CFWriteStream 和一个 CFReadStream。这些免费电话分别与NSOutputStreamNSInputStream 桥接。所以你得到的是一个NSOutputStream 和一个NSInputStream。无论您是否声明了这些子类都没有区别;这些是CFStreamCreatePairWithSocketToHost 创建的类。

    如果您出于某种原因确实不能使用包装,则需要重新实现 Core Foundation 函数来创建您的自定义子类。在实践中,我建议您只包装 NS[Output/Input]Stream 并使用 forwardingTargetForSelector:,这样您就可以在任何可以接受原始对象之一的地方提供包装器。

    【讨论】:

    • 我可能错误地包装了类。你介意给我看一个非常简单的例子吗?我最初将它们包裹在一个 NSObject 中
    • 我无法让包装器工作,但如果我确实包装了它们,在委托方法 handleEvent 中,我如何获取流发送的命令..因为 handleEvent 委托方法提供了 NSStream对象,而不是我的自定义对象,其中包含字符串命令。
    猜你喜欢
    • 2017-03-24
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    • 2018-06-30
    相关资源
    最近更新 更多