最近开发的一个项目,上线后,通过bugly看到有许多闪退的日志,其中有个闪退日志如下:
0 libsystem_kernel.dylib __pthread_kill + 8
1 libsystem_pthread.dylib pthread_kill + 112
2 libsystem_c.dylib abort + 112
3 libsystem_c.dylib basename + 0
4 SystemConfiguration ___cellular_fallback_monitor_block_invoke_2
5 libsystem_network.dylib ___network_path_notify_block_invoke + 40
6 libdispatch.dylib __dispatch_call_block_and_release + 24
7 libdispatch.dylib __dispatch_client_callout + 16
8 libdispatch.dylib __dispatch_queue_drain + 1216
9 libdispatch.dylib __dispatch_queue_invoke + 132
10 libdispatch.dylib __dispatch_root_queue_drain + 664
11 libdispatch.dylib __dispatch_worker_thread3 + 108
12 libsystem_pthread.dylib _pthread_wqthread + 816
光从堆栈上看,定位不到问题,只能说可能跟网络有关。
用户的设备是iPhone 6,iOS 8.1.2.
开发、测试的时候,一直用的是iOS 9以上的环境测试,没发现闪退的情况。然后找来一个iOS8的iTouch,一运行,果然闪退。
xcode中,可以直接定位到闪退的代码SCNetworkReachabilityGetFlags。定位到方法就好办了,就可以有针对性的找解决办法了。
解决方法:
判断当前iOS系统的版本,对iOS 9以上的系统,仍采用原来方法;对iOS 9以下的系统,采用另一种方法。具体代码如下:
+ (BOOL)hasConnectivity {
if (IOS_VERSION_9_OR_ABOVE)
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
if(reachability != NULL) {
//NetworkStatus retVal = NotReachable;
SCNetworkReachabilityFlags flags;
Boolean ret = SCNetworkReachabilityGetFlags(reachability, &flags);
free(reachability);
if (ret) {
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// if target host is not reachable
return NO;
}
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
// if target host is reachable and no connection is required
// then we'll assume (for now) that your on Wi-Fi
return YES;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionAutomatic) != 0))
{
// ... and the connection is on-demand (or on-traffic) if the
// calling application is using the CFSocketStream or higher APIs
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
// ... and no [user] intervention is needed
return YES;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
// is using the CFNetwork (CFSocketStream?) APIs.
return YES;
}
}
}
return NO;
}
else
{
return [[NetworkReachabilityManager sharedInstance] hasNetwork];
}
}
//NetworkReachabilityManager.mm
-(BOOL)hasNetwork
{
return _netStatus != NotReachable;
}
当然,iOS 9以上的系统,也可以采用这种方法,这样,代码更简洁,也更统一。
网友评论