6

好吧,我正在从事一个非 ARC 项目,但使用Philipp Kyeck 的使用 ARC 编写的 socketio 库。我正在使用教程中解释的方法合并非 ARC 项目和 ARC 库。

在我的 ViewController 文件中,我正在使用初始化套接字

 SockIO *chatSockIO = [[SocketIO alloc] initWithDelegate:self];

当我需要断开连接时,我会打电话

[chatSockIO disconnect];

这导致 socketIODidDisconnect 委托方法被触发。

- (void) socketIODidDisconnect:(SocketIO *)socket{
   [chatSockIO release]; ==> is this call needed?
}

现在我的问题是关于线的[chatSockIO release]我们是否需要释放一个本身在 ARC 模式下定义但在非 ARC 项目中使用的对象?

现在当我尝试发布时,我得到了一个例外说

-[SocketIO retain]: message sent to deallocated instance 0x6fec370

但是当我注释掉那一行时,我的库对象中出现内存泄漏和dealloc,根本没有被调用

赏金时间!!

忘记我提到的库,在我的代码中崩溃和泄漏..在非 ARC 项目中使用使用 ARC 方法定义的对象时,通常的做法是什么。我应该只分配它,还是应该在使用后分配并释放它?

编辑:更多信息。

我在崩溃时运行了僵尸仪器,这就是它不得不说的......它显示了对分配和释放函数的调用。

#   Address     Category    Event Type  RefCt   Timestamp       Size    Responsible Library     Responsible Caller
0   0x72d5da0   SocketIO    Malloc      1       00:09.700.274   64      MyProject           -[MyViewController sendRequestForSocketIOPush]
1   0x72d5da0   SocketIO    Retain      2       00:09.700.317   0       MyProject           -[SocketIO initWithDelegate:]
2   0x72d5da0   SocketIO    Release     1       00:09.700.320   0       MyProject           -[SocketIO initWithDelegate:]
3   0x72d5da0   SocketIO    Retain      2       00:09.700.440   0       Foundation          -[NSURLConnectionInternal initWithInfo:]
4   0x72d5da0   SocketIO    Retain      3       00:10.413.717   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
5   0x72d5da0   SocketIO    Release     2       00:10.413.761   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
6   0x72d5da0   SocketIO    Retain      3       00:10.413.797   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
7   0x72d5da0   SocketIO    Release     2       00:10.413.811   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
8   0x72d5da0   SocketIO    Retain      3       00:10.413.816   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
9   0x72d5da0   SocketIO    Release     2       00:10.415.087   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
10  0x72d5da0   SocketIO    Retain      3       00:10.415.214   0       Foundation          -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:]
11  0x72d5da0   SocketIO    Release     2       00:10.415.216   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
12  0x72d5da0   SocketIO    Release     1       00:10.415.275   0       Foundation          -[NSURLConnectionInternalConnection invokeForDelegate:]
13  0x72d5da0   SocketIO    Retain      2       00:10.969.432   0       GraphicsServices    GSEventRunModal
14  0x72d5da0   SocketIO    Release     1       00:10.969.433   0       GraphicsServices    GSEventRunModal
15  0x72d5da0   SocketIO    Retain      2       00:10.969.434   0       GraphicsServices    GSEventRunModal
16  0x72d5da0   SocketIO    Release     1       00:10.969.456   0       GraphicsServices    GSEventRunModal
17  0x72d5da0   SocketIO    Retain      2       00:10.969.459   0       GraphicsServices    GSEventRunModal
18  0x72d5da0   SocketIO    Retain      3       00:10.969.488   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
19  0x72d5da0   SocketIO    Release     2       00:10.976.115   0       MyProject           -[SocketIO setTimeout]
20  0x72d5da0   SocketIO    Retain      3       00:10.976.125   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
21  0x72d5da0   SocketIO    Release     2       00:10.976.161   0       GraphicsServices    GSEventRunModal
22  0x72d5da0   SocketIO    Retain      3       00:13.935.328   0       GraphicsServices    GSEventRunModal
23  0x72d5da0   SocketIO    Release     2       00:13.935.373   0       MyProject           -[SocketIO setTimeout]
24  0x72d5da0   SocketIO    Retain      3       00:13.935.399   0       Foundation          -[NSCFTimer initWithFireDate:interval:target:selector:userInfo:repeats:]
25  0x72d5da0   SocketIO    Release     2       00:13.935.685   0       MyProject           -[SocketIO onDisconnect]
26  0x72d5da0   SocketIO    Release     1       00:13.935.705   0       MyProject           -[MyViewController socketIODidDisconnect:]
27  0x72d5da0   SocketIO    Release     0       00:13.935.716   0       GraphicsServices    GSEventRunModal
28  0x72d5da0   SocketIO    Zombie      -1      00:13.936.298   0       GraphicsServices    GSEventRunModal
4

6 回答 6

3

要回答您的问题:

如果你从非 ARC 代码中使用 ARC 管理的对象,你可以像使用非 ARC 对象一样使用它:如果你创建或保留它,你必须释放或自动释放它。

关于你的问题:

在您的评论中,您提到您尝试通过这样的初始化来解决问题

self.chatSockIO = [[[SocketIO alloc] initWithDelegate:self] autorelease];

并且在socketIODidDisconnect

self.chatSockIO = nil;

这应该可以正常工作,前提是该chatSockIO属性具有retain语义,并且一次只SocketIO使用一个对象。

Zombie 输出提示出了什么问题:

  • 在倒数第二行中,您释放对象,保留计数降至 0,并且对象被释放。这就是你所期望的。
  • 然而,在最后一行中,它试图从运行循环中保留对象。您知道这是一个保留,因为没有NSZombie.
  • 这意味着尽管您已经完成了该对象,但它仍会收到来自某个地方的调用。这是出乎意料的。

它可能是您的代码中的某些内容,也可能是您正在使用的某个库中的错误。只是一个预感:在SocketIO.m替换这些行-onDisconnect

if (_webSocket != nil) {
    [_webSocket close];
}

if (_webSocket != nil) {
    [_webSocket close];
    _webSocket.delegate = nil;
}
于 2012-07-19T10:35:24.220 回答
1

这可能无法解决您的问题,但无论如何,在委托调用中释放对象通常是一个可怕的想法 - 它可能会在仍在工作时被释放,特别是如果对象在 ARC 下,可能没有释放方法。

因此,将您的关闭委托调用转换为:

- (void) socketIODidDisconnect:(SocketIO *)socket
{
   chatSockIO.delegate = nil; // don't want any more messages
   dispatch_async(dispatch_get_main_gueue(), ^{ self.chatSockIO = nil; }); // typed in text editor
   // your question - is the release needed? Well, under virtually every scenario yes, but I don't know this framework
}

无论这是否解决了您的问题,您都应该以这种方式进行发布 - 在委托返回后的主线程上。如果您查看您的代码,您应该完全使用这个 ARC 类,就像使用普通类一样。互操作性非常好,我在我的 ARC 应用程序中使用了几个 NON-ARC 项目,其他人成功地完成了相反的操作。

于 2012-07-19T21:37:03.427 回答
0

我也曾感受到类似的问题。我通过设置@property(nonatomic, retain) 班级解决了这个问题。在你的情况下,它应该是,

在.h

  @property(nonatomic, retain) SockIO *socketIO;

   @synthesize socketIO;
   chatSockIO = [[SocketIO alloc] initWithDelegate:self];

而且您不会再次崩溃您的应用程序!

于 2012-07-16T08:02:51.827 回答
0

ARC and non ARC objects mix fine. Classes that are implemented using ARC can safely be used from non-ARC code. Whenever there's an ownership error the problem is probably in your code.

Without seeing code it's not possible to find the error but it's probably some simple over-release.

Look at all the places in MyProject where the Instruments trace shows a Release event, like -[SocketIO setTimeout], -[SocketIO onDisconnect] and -[MyViewController socketIODidDisconnect:]. Check if there are improper ownership transfers, like assigning an instance variable handled by a retain property or similar.

于 2012-07-16T08:39:17.087 回答
0

我目前正在做一个类似的项目,我解决它的方法是将非 ARC 项目切换到 ARC。Xcode 为您传输所有内容,为我解决了所有内存泄漏和其他问题。

要切换到 ARC,您需要:

1.点击编辑->重构->转换为Objective-C ARC

2.单击您的项目目标,然后在下拉列表中选择要转换为 ARC 的文件

3.选择正确的文件后单击检查

4.单击下一步,等待转换完成。

5.单击“更新”按钮更新您的代码。

6.检查你的代码

希望有帮助。它帮助了我

于 2012-07-16T19:22:10.800 回答
0

以我的经验,我不会将 ARC 和非 ARC 混合在一起,期望一小段代码。我浪费了很多时间来尝试查找泄漏和崩溃错误。

如果您无法将程序转换为 ARC,请考虑使用非 ARC 版本的 sockIO:https ://github.com/pkyeck/socket.IO-objc/tree/non-arc

这可能会为您省去很多麻烦。

于 2012-07-11T08:51:50.387 回答