13

有一个 MFI 设备通过蓝牙 (2.1 + EDR) 连接到 iPhone 4S (6.0 GM) 或 iPad (6.0 GM)。该项目基于 Xcode 4.5 GM 构建。当应用程序获取EAAccessoryDidDisconnectNotification时,它将发送消息[_eaSessionController closeSession];。所有这些都在 iOS 5.1.1 或更早版本中运行良好。但是在带有此消息的 iOS6 上,我得到的日志如下:

-[NSCondition dealloc]: condition (<NSCondition: 0x2e5640> '(null)') deallocated while still in use
Break on _NSLockError() to debug.

有任何想法吗?

4

3 回答 3

4

我遇到了同样的问题。在收到 EAAccessoryDidDisconnectNotification 时调用 [NSStream close] 时会引发此警告。在断开之前,两个设备之间还应该有一些数据交换。

中断 _NSLockError 将表明在对象被释放的那一刻,外部附件框架产生的一些线程正在等待条件。其中之一肯定会等待被释放的条件,这解释了控制台上引发的警告。

我还注意到,每次附件断开连接然后连接时,外部附件框架创建的线程数量都在不断增加,而且它们似乎只是在泄漏。

在我看来,不知何故,外部附件框架没有正确释放它分配的资源,这导致了很多混乱。其后续影响之一是在调用 OSAtomicCompareAndSwap64 期间发生在其中一个泄漏线程内的崩溃。

我设法使用基本示例重现了该问题,其中流被安排在主线程上以避免应用程序内部的任何线程管理。我相信这是 Apple 应该注意的 iOS 6 上的附件管理错误。我会报告它并等待他们要说的。

同时,我想知道你们中是否有人在这方面取得了任何进展。

谢谢,

于 2012-10-05T13:20:08.207 回答
4

iOS 6.1+ 就没有这个问题了。要为 iOS 6.0 和 iOS 6.0.1 解决此问题,请使用下一个解决方案:

请注意:这只是临时解决方案,允许使用 iOS 6.0 和 6.0.1 的用户继续使用您的应用程序。

有一个简单的技巧可以避免应用程序崩溃:只需为 iOS 6.0 和 iOS 6.0.1 创建新类别并覆盖 dealloc 方法 (NSCondition):

#import "NSCondition+LeakDealloc.h"
#import <objc/runtime.h>

@implementation NSCondition (LeakDealloc)

- (void) safeDealloc
{
    float sVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (sVersion < 6.0 || sVersion >= 6.1)
    {
        [self safeDealloc];
    }
}

+ (void) load 
{
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(dealloc)), class_getInstanceMethod(self, @selector(safeDealloc)));
}

@end

该解决方案产生新的泄漏,经过 20 分钟的测试和大约 50 个 BG/FG 开关仪器显示 10 个 NSCondition 泄漏(960 字节),但没有一个崩溃!

于 2012-11-16T09:50:54.180 回答
1

该问题已在 iOS 6.1 中得到修复。没有更多泄漏的 NSCondition 或外部附件线程。苹果似乎已经正确解决了这个问题。

于 2013-01-29T11:16:15.150 回答