0

我想做一个简单的 TCP 客户端。但我遇到了一个错误。当我制作时 inputStream = (NSInputStream *)readStream;outputStream = (NSOutputStream *)writeStream;它建议我引入前缀 __bridge 或_bridge _transfer

首先,它是什么?其次,我都试过了,仍然无法发送消息。我按照本教程进行了操作,并且也发送了消息和流。我安装了 Wireshark 并调用了发送消息,但它没有向 IP 发送任何数据包。

我刚刚在这里发布了 initNetworkCommunication,因为这是我得到“桥”错误的地方。

- (void) initNetworkCommunication {

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"54.xxx.xxx.xxx", 1333, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];

}

服务器很好,因为我已经尝试了示例代码并且得到了响应。

你能帮助我吗?

4

1 回答 1

6

正如 H2CO3 提到的,这是一个 ARC 的东西。

如果您不知道 ARC 是什么,请阅读本文。总而言之,它是一种自动化内存管理工作(保留/释放语句等)的确定性方式,而 Objective-C 程序员以前必须手动完成。它非常值得使用,并且几乎没有缺点。但是,它确实有一些问题。

ARC 不适用于 Core Foundation 对象。它们仍然受制于旧规则,您必须自己进行内存管理。ARC 仅适用于 Objective-C 对象。然而,一些 Core Foundation 对象实际上是免费桥接到它们的 Cocoa 等价物。您在代码示例中使用免费桥接来创建一个CFReadStreamRef,然后将其作为NSInputStream.

所以你会怎么做?苹果的文档说如下:

如果您在 Objective-C 和 Core Foundation 风格的对象之间进行转换,您需要使用转换(在 objc/runtime.h 中定义)或 Core Foundation 风格的宏(在NSObject.h):

  • __bridge在没有所有权转移的情况下在 Objective-C 和 Core Foundation 之间转移一个指针。
  • __bridge_retainedCFBridgingRetain将 Objective-C 指针转换为 Core Foundation 指针,并将所有权转移给您。您负责调用 CFRelease 或相关函数来放弃对象的所有权。
  • __bridge_transferCFBridgingRelease将非 Objective-C 指针移动到 Objective-C 并将所有权转移给 ARC。ARC 负责放弃对象的所有权。

您正在从 Core Foundation 转移到 Objective-C,因此请忽略第二个要点(这是为了朝另一个方向发展)。问题是你想要发生什么——如果在传输之后你想将该对象交给 ARC,只从 Objective-C 端使用它,并让 ARC 处理内存管理,使用__bridge_transfer. 根据您的代码示例,这可能就是您想要的。

如果您只使用__bridge,或者如果您不使用 ARC,则需要自己清理对象,使用其中一个CFRelease()或向它们发送release消息(后者仅在您不使用 ARC 时才有效)。

于 2012-07-13T11:26:43.383 回答