定位内存走漏的时分发现CNCopyCurrentNetworkInfo有内存走漏,而且只要返回值是空的时分才会有,这就很乖僻。这儿就有两个问题:获取SSID不成功?为什么有内存走漏?

为什么获取SSID不成功?

其实一开始我也是一顿查找,后面发现答案就在CNCopyCurrentNetworkInfo头文件里边,来看看头文件里边写了啥

/*!
@function CNCopyCurrentNetworkInfo
@discussion Returns the network information for the specified interface when the requesting application meets one of following 4 requirements -.
1. application is using CoreLocation API and has the user's authorization to access location.
2. application has used the NEHotspotConfiguration API to configure the current Wi-Fi network.
3. application has active VPN configurations installed.
4. application has active NEDNSSettingsManager configurations installed.
- An application that is linked against iOS 12.0 SDK and above must have the "com.apple.developer.networking.wifi-info" entitlement.
- An application will receive a pseudo network information if it is linked against an SDK before iOS 13.0, and if it fails to meet any of the
above requirements.
- An application will receive NULL if it is linked against iOS 13.0 SDK (or newer), and if it fails to meet any of the above requirements.
- On Mac Catalyst platform, to receive current Wi-Fi network information, an application must have "com.apple.developer.networking.wifi-info"
entitlement and user's authorization to access location.
Network Information dictionary will contain the following keys, and values:
<pre>
@textblock
Keys                      : Values
=======================================
kCNNetworkInfoKeySSIDData : CFDataRef
kCNNetworkInfoKeySSID     : CFStringRef
kCNNetworkInfoKeyBSSID    : CFStringRef
@/textblock
</pre>
Pseudo network information will contain "Wi-Fi" SSID and "00:00:00:00:00:00" BSSID. For China region, the SSID will be "WLAN".
@param interfaceName Name of the interface you are interested in
@result Network Information dictionary associated with the interface.
Returns NULL if an error was encountered.
You MUST release the returned value.
*/
CFDictionaryRef __nullable
CNCopyCurrentNetworkInfo	(CFStringRef	interfaceName)
API_DEPRECATED_WITH_REPLACEMENT("[NEHotspotNetwork fetchCurrentWithCompletionHandler:]", ios(4.1, API_TO_BE_DEPRECATED), macCatalyst(14.0, API_TO_BE_DEPRECATED))
API_UNAVAILABLE(macos, tvos, watchos);

获取wifi信息的必要条件:

  • 大于等于iOS12,有必要要在entitlement中配备com.apple.developer.networking.wifi-info,值为YES。等价于在Capability增加Access WiFi Infomation

  • 小于等于iOS13,有必要要满意四个条件其一。

    • 用户赞同获取地址权限
    • NEHotspotConfiguration API配备过的Wi-Fi (没试过)
    • 安装过VPN configurations(没试过)
    • 安装过NEDNSSettingsManager configurations(没试过)
  • 大于等于iOS14,能够使用新的API [NEHotspotNetwork fetchCurrentWithCompletionHandler:]

通过这些设置,Wifi信息应该能够获取到了,内存走漏也没有了。

为什么会有内存走漏?

先上获取SSID的代码

+ (NSString *_Nullable)getDeviceSSID
{
NSString *wifiName = nil;
CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();
if (!wifiInterfaces) {
return nil;
}
NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
for (NSString *interfaceName in interfaces) {
CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
if (dictRef) {
NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
CFRelease(dictRef);
break;
}
}
CFRelease(wifiInterfaces);
return wifiName;
}

假如wifiInterfaces为nil,那么就没有办法开释,而CNCopySupportedInterfaces的返回值是一定要开释的。