iOS开发 判断是否为刘海屏 以及网络状态
判断是否为刘海屏,不应该只判断iPhone上的情况还应该判断iPad上的情况。iPad在iOS12已经更改了状态栏,成为时间不居中的类型。这一类也属于刘海屏。
在适配界面的时候,可以不考虑这类iPad的情况。如果通过判断刘海屏来访问状态栏的私有变量的时候,会出现崩溃的情况。在这里笔者建议访问私有变量,应该使用异常。如果访问私有变量失败会触发异常,却不会引起App的崩溃。一旦线上的App崩溃将造成很不友好的体验。
- (BOOL)isLiuHaiScreen { if (@available(iOS 11.0, *)) { if (@available(iOS 12.0, *) && [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) { return YES; } UIEdgeInsets safeAreaInsets = [UIApplication sharedApplication].windows[0].safeAreaInsets; return safeAreaInsets.top == liuHaiHeight || safeAreaInsets.bottom == liuHaiHeight || safeAreaInsets.left == liuHaiHeight || safeAreaInsets.right == liuHaiHeight; }else { return NO; } }
在我的实际项目中,碰见访问状态栏的私有变量来判断网络状态的情况。笔者前期使用到了异常来控制私有变量
#pragma mark 获取当前网络类型+ (NSString *)getNetworkType{ UIApplication *app = [UIApplication sharedApplication]; id statusBar = nil; // 判断是否是iOS 13 NSString *network = @""; if (@available(iOS 13.0, *)) { UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager; #pragma clang diagnostic push#pragma clang diagnostic ignored "-Wundeclared-selector" if ([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]) { UIView *localStatusBar = [statusBarManager performSelector:@selector(createLocalStatusBar)]; if ([localStatusBar respondsToSelector:@selector(statusBar)]) { statusBar = [localStatusBar performSelector:@selector(statusBar)]; } }#pragma clang diagnostic pop if (statusBar) { // UIStatusBarDataCellularEntry id currentData = [[statusBar valueForKeyPath:@"_statusBar"] valueForKeyPath:@"currentData"]; id _wifiEntry = [currentData valueForKeyPath:@"wifiEntry"]; id _cellularEntry = [currentData valueForKeyPath:@"cellularEntry"]; if (_wifiEntry && [[_wifiEntry valueForKeyPath:@"isEnabled"] boolValue]) { // If wifiEntry is enabled, is WiFi. network = @"WIFI"; } else if (_cellularEntry && [[_cellularEntry valueForKeyPath:@"isEnabled"] boolValue]) { NSNumber *type = [_cellularEntry valueForKeyPath:@"type"]; if (type) { switch (type.integerValue) { case 0: // 无sim卡 network = @"NONE"; break; case 1: network = @"1G"; break; case 4: network = @"3G"; break; case 5: network = @"4G"; break; default: // 默认WWAN类型 network = @"WWAN"; break; } } } } }else { statusBar = [app valueForKeyPath:@"statusBar"]; if ([[[self alloc]init]isLiuHaiScreen]) { // 刘海屏 id statusBarView = [statusBar valueForKeyPath:@"statusBar"]; UIView *foregroundView = [statusBarView valueForKeyPath:@"foregroundView"]; NSArray *subviews = [[foregroundView subviews][2] subviews]; if (subviews.count == 0) { // iOS 12 id currentData = [statusBarView valueForKeyPath:@"currentData"]; id wifiEntry = [currentData valueForKey:@"wifiEntry"]; if ([[wifiEntry valueForKey:@"_enabled"] boolValue]) { network = @"WIFI"; }else { // 卡1: id cellularEntry = [currentData valueForKey:@"cellularEntry"]; // 卡2: id secondaryCellularEntry = [currentData valueForKey:@"secondaryCellularEntry"]; if (([[cellularEntry valueForKey:@"_enabled"] boolValue]|[[secondaryCellularEntry valueForKey:@"_enabled"] boolValue]) == NO) { // 无卡情况 network = @"NONE"; }else { // 判断卡1还是卡2 BOOL isCardOne = [[cellularEntry valueForKey:@"_enabled"] boolValue]; int networkType = isCardOne ? [[cellularEntry valueForKey:@"type"] intValue] : [[secondaryCellularEntry valueForKey:@"type"] intValue]; switch (networkType) { case 0://无服务 network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"NONE"]; break; case 3: network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"2G/E"]; break; case 4: network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"3G"]; break; case 5: network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"4G"]; break; default: break; } } } }else { for (id subview in subviews) { if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]) { network = @"WIFI"; }else if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")]) { network = [subview valueForKeyPath:@"originalText"]; } } } }else { // 非刘海屏 NSArray *subviews; @try { UIView *foregroundView = [statusBar valueForKeyPath:@"foregroundView"]; subviews = [foregroundView subviews]; } @catch (NSException *exception) { subviews = [[[[[UIApplication sharedApplication] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"foregroundView"] subviews]; } @finally { } for (id subview in subviews) { if ([subview isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { int networkType = [[subview valueForKeyPath:@"dataNetworkType"] intValue]; switch (networkType) { case 0: network = @"NONE"; break; case 1: network = @"2G"; break; case 2: network = @"3G"; break; case 3: network = @"4G"; break; case 5: network = @"WIFI"; break; default: break; } } } } } if ([network isEqualToString:@""]) { network = @"NO DISPLAY"; } return network;}
这里并没有判断iPhone12的5G网络状态,所以并不是很全面。
作者:我明白了我是一条鲶鱼
链接:https://www.jianshu.com/p/40041c7ba41f