【问题标题】:Cocoa, toll-free bridging and ARCCocoa、免费桥接和 ARC
【发布时间】:2023-03-17 01:29:01
【问题描述】:

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

首先,它是什么?其次,我都试过了,仍然无法发送消息。我关注了这个tutorial,我也发送消息和流。我安装了 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];

}

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

你能帮帮我吗?

【问题讨论】:

  • 1.这些关键字是愚蠢的与 ARC 相关的东西;你最好关闭这个项目的 ARC。 2. 我围绕 BSD 套接字 API 创建了一个 Objective-C TCP 包装器,它非常易于使用:github.com/H2CO3/TCPHelper

标签: objective-c cocoa stream inputstream tcpclient


【解决方案1】:

正如 H2CO3 所说,这是一个 ARC。

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

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

那你是做什么的? Apple 的文档是这样说的:

如果您在 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)。

【讨论】:

  • 非常感谢 Amy Worrall。好吧,我来自简单的 Javascript 和 HTML 前端。我在IOS大约2个月,是时候买书了。非常感谢您的解释。
  • 不用担心。 ARC 绝对是未来,所以值得使用——但我们正处于过渡时期,它仍然是新的,很多教程还没有更新。确保当你拿到一本书时,你知道它是教你旧的(手动保留/释放)内存管理规则还是它是否使用 ARC。至少了解手动的做事方式是值得的,因为它可以让您更好地了解 ARC 正在自动化什么。
  • 我明白了。那么添加 __bridge_transfer 将不起作用。我的 - (void) sendMessage:(NSString *)message { NSLog(@"message %@",message); NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]]; [输出流写入:[数据字节] maxLength:[数据长度]]; NSLog(@"outputStream %@",outputStream); } 不工作 :S 我认为输出流有问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2012-04-16
  • 2012-11-17
相关资源
最近更新 更多