我在非弧项目中使用了苹果的Reachabiliry课程。当我使用仪器运行以查找内存泄漏时,它会引用Reachability方法。这是问题所在:
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
WReachability* returnValue = NULL;
if (reachability != NULL)
{
returnValue = [[self alloc] init];
if (returnValue != NULL)
{
returnValue->reachabilityRef = reachability;
returnValue->localWiFiRef = NO;
}
}
return returnValue;
}
泄漏的对象是可达性和returnValue。 我知道SCNetworkReachabilityCreateWithAddress创建了一个新实例,我必须CFRelease它,但它发生在dealloc!
- (void)dealloc
{
[self stopNotifier];
if (reachabilityRef != NULL)
{
CFRelease(reachabilityRef);
}
[super dealloc];
}
那么我该怎样做才能避免内存泄漏?
UPD: 也许问题在于如何调用可达性?我用这个方法:
+ (instancetype)reachabilityForInternetConnection;
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress:&zeroAddress];
}
然后我这样打电话给Reachability:
[[Reachability reachabilityForInternetConnection] startNotifier];
不要将它分配给任何对象,只需使用此行即可。 我试图将此调用更改为:
Reachability *reachability = [[Reachability reachabilityForInternetConnection] autorelease];
[reachability startNotifier];
但是在这个分析仪告诉我“太多自动释放”之后。
答案 0 :(得分:9)
@Alexart回答对我有用,但如果你想要简化版,请使用
+(instancetype)reachabilityWithAddress:(void *)hostAddress
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:CFBridgingRetain((__bridge id)ref)];
CFRelease(ref);
return reachability;
}
return nil;
}
答案 1 :(得分:6)
我认为下一步做得更好:
+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
{
Reachability* retVal = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if(reachability!= NULL)
{
retVal= [[self alloc] init];
if(retVal!= NULL)
{
retVal->reachabilityRef = reachability;
retVal->localWiFiRef = NO;
}
else
{
CFRelease(reachability);
}
}
return retVal;
}
答案 2 :(得分:4)
如果returnValue等于NULL可达性对象泄露,则应在此情况下释放它。同样通过Cocoa命名约定(https://developer.apple.com/library/ios/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-SW1),您必须返回自动释放的对象:
+ (instancetype)reachabilityWithAddress:
{
...
returnValue = [[[self alloc] init] autorelease];
或者,如果您不想返回自动释放的对象,请将该方法重命名为例如来自new:newReachabilityWithAddress
或类似的内容。
尝试在Xcode中运行静态分析器,它可以帮助发现问题。
答案 3 :(得分:1)
最新的reachability.m似乎需要ARC,我的应用程序没有使用它。
我只是为它打开了它:
转到目标\构建阶段\编译源
找到可达性并双击它
add -fobjc-arc
内存泄漏现在已经消失
答案 4 :(得分:1)
启用ARC的解决方案readPicture
类。
Reachability
。CFAutorelease(ref)
CFRelease(self.reachabilityRef)
代码
醇>
更新了dealloc
dealloc
更新了- (void)dealloc {
[self stopNotifier];
self.reachableBlock = nil;
self.unreachableBlock = nil;
self.reachabilityBlock = nil;
self.reachabilitySerialQueue = nil;
}
reachabilityWithAddress
更新了+ (instancetype)reachabilityWithAddress:(void *)hostAddress {
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
if (ref) {
id reachability = [[self alloc] initWithReachabilityRef:ref];
CFAutorelease(ref);
return reachability;
}
return nil;
}
reachabilityWithHostname
答案 5 :(得分:0)
除了dealloc中的CFRelease之外,代码的正确修复如下。
查看下面代码的正文。类似的主体也需要进入reachabilityWithHostName代码。
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);
Reachability* returnValue = NULL;
if (reachability != NULL)
{
returnValue = [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = CFRetain(reachability);
returnValue->_alwaysReturnLocalWiFiStatus = NO;
}
CFRelease(reachability);
}
return returnValue;
}