1. 程式人生 > >iPhone X (XS XR XSMAX)如何根據狀態列上的圖示 獲取裝置的聯網狀態(不是單個應用的)

iPhone X (XS XR XSMAX)如何根據狀態列上的圖示 獲取裝置的聯網狀態(不是單個應用的)

在iPhone X 上通過狀態列獲取聯網狀態使用下面的程式碼直接閃退

- (BOOL)networkingStatesFromStatebar {
    UIApplication *app = [UIApplication sharedApplication];
    NSArray *children = nil;
    children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
    int type = 0;
    for (id child in children) {
        if ([child isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
            type = [[child valueForKeyPath:@"dataNetworkType"] intValue];
        }
    }

    if (type == 0) {
        return NO;
    }else{
        return YES;
    }
}


網上其他的方法

        children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];


不崩潰,但是不能獲取正確的狀態。

因此列印一下,看看能發現什麼

        UIApplication *app = [UIApplication sharedApplication] ;

        id _statusBar =  [app valueForKeyPath:@"_statusBar"];//UIStatusBar_Modern
        
        id _statusBar2 = [_statusBar valueForKeyPath:@"_statusBar"];

列印_statusBar2得到

<_UIStatusBar: 0x102e07e40: regions={
            bottomLeading = <_UIStatusBarRegion: 0x1d412b220: identifier=bottomLeading, enabled=1, displayItems={(
                )}>,
            systemUpdates = <_UIStatusBarRegion: 0x1d012c6c0: identifier=systemUpdates, enabled=1, displayItems={(
                )}>,
            expandedTrailing = <_UIStatusBarRegion: 0x1d412b2c0: identifier=expandedTrailing, enabled=0, displayItems={(
                )}>,
            leading = <_UIStatusBarRegion: 0x1d012c1c0: identifier=leading, enabled=1, displayItems={(
                                                                                                      <_UIStatusBarDisplayItem: 0x1d418d8f0: identifier=_UIStatusBarTimeItem.shortTimeDisplayIdentifier, item=<_UIStatusBarTimeItem: 0x1d027ff00: identifier=_UIStatusBarTimeItem>, view=<_UIStatusBarStringView: 0x102e0fd20; frame = (10 3.66667; 33.3333 18); text = '3:42'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1d4288430>>>,
                                                                                                      <_UIStatusBarDisplayItem: 0x1d018d340: identifier=_UIStatusBarIndicatorLocationItem, item=<_UIStatusBarIndicatorLocationItem: 0x1d445a370: identifier=_UIStatusBarIndicatorLocationItem>, view=<_UIStatusBarImageView: 0x102f22530; frame = (46 8.33333; 10.6667 10.6667); opaque = NO; userInteractionEnabled = NO; tintColor = UIExtendedGrayColorSpace 0 1; layer = <CALayer: 0x1d422a720>>>
                                                                                                      )}>,
            pill = <_UIStatusBarRegion: 0x1d012c260: identifier=pill, enabled=0, displayItems={(
                )}>,
            expandedLeading = <_UIStatusBarRegion: 0x1d412b360: identifier=expandedLeading, enabled=0, displayItems={(
                )}>,
            trailing = <_UIStatusBarRegion: 0x1d012c580: identifier=trailing, enabled=1, displayItems={(
                                                                                                        <_UIStatusBarDisplayItem: 0x1d418e380: identifier=_UIStatusBarCellularItem.signalStrengthDisplayIdentifier, item=<_UIStatusBarCellularItem: 0x1d4670e00: identifier=_UIStatusBarCellularItem>, view=<_UIStatusBarCellularSignalView: 0x102f21580; frame = (0 7.33333; 17 10.6667); userInteractionEnabled = NO; layer = <CALayer: 0x1d003fc20>>>,
                                                                                                        <_UIStatusBarDisplayItem: 0x1d418ead0: identifier=_UIStatusBarCellularItem.typeDisplayIdentifier, item=<_UIStatusBarCellularItem: 0x1d4670e00: identifier=_UIStatusBarCellularItem>, view=<_UIStatusBarStringView: 0x102f217a0; frame = (21.3333 6; 17 14.3333); text = '4G'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x1d009ebe0>>>,
                                                                                                        <_UIStatusBarDisplayItem: 0x1d418e5f0: identifier=_UIStatusBarBatteryItem.iconDisplayIdentifier, item=<_UIStatusBarBatteryItem: 0x1d46759c0: identifier=_UIStatusBarBatteryItem>, view=<_UIBatteryView: 0x102e13c50; frame = (42.3333 7; 24.3333 11.3333); userInteractionEnabled = NO; layer = <CALayer: 0x1d422c7a0>>>
                                                                                                        )}>,
            topTrailing = <_UIStatusBarRegion: 0x1d412b180: identifier=topTrailing, enabled=1, displayItems={(
                )}>
        }, items={
            _UIStatusBarActivityItem_Split = <_UIStatusBarActivityItem_Split: 0x1d466f840: identifier=_UIStatusBarActivityItem_Split>,
            _UIStatusBarCellularItem = <_UIStatusBarCellularItem: 0x1d4670e00: identifier=_UIStatusBarCellularItem>,
            _UIStatusBarIndicatorAlarmItem = <_UIStatusBarIndicatorAlarmItem: 0x1d0444320: identifier=_UIStatusBarIndicatorAlarmItem>,
            _UIStatusBarIndicatorCallForwardingItem = <_UIStatusBarIndicatorCallForwardingItem: 0x1d0444560: identifier=_UIStatusBarIndicatorCallForwardingItem>,
            _UIStatusBarBackgroundActivityItem = <_UIStatusBarBackgroundActivityItem: 0x1d4670c00: identifier=_UIStatusBarBackgroundActivityItem>,
            _UIStatusBarBluetoothItem = <_UIStatusBarBluetoothItem: 0x1d027eb00: identifier=_UIStatusBarBluetoothItem>,
            _UIStatusBarIndicatorRotationLockItem = <_UIStatusBarIndicatorRotationLockItem: 0x1d0444440: identifier=_UIStatusBarIndicatorRotationLockItem>,
            _UIStatusBarIndicatorQuietModeItem = <_UIStatusBarIndicatorQuietModeItem: 0x1d04445c0: identifier=_UIStatusBarIndicatorQuietModeItem>,
            _UIStatusBarIndicatorTTYItem = <_UIStatusBarIndicatorTTYItem: 0x1d0442f40: identifier=_UIStatusBarIndicatorTTYItem>,
            _UIStatusBarCellularExpandedItem = <_UIStatusBarCellularExpandedItem: 0x1d466fc40: identifier=_UIStatusBarCellularExpandedItem>,
            _UIStatusBarIndicatorLocationItem = <_UIStatusBarIndicatorLocationItem: 0x1d445a370: identifier=_UIStatusBarIndicatorLocationItem>,
            _UIStatusBarThermalItem = <_UIStatusBarThermalItem: 0x1d0443060: identifier=_UIStatusBarThermalItem>,
            _UIStatusBarNavigationItem = <_UIStatusBarNavigationItem: 0x1d445d1c0: identifier=_UIStatusBarNavigationItem>,
            _UIStatusBarIndicatorAirplaneModeItem = <_UIStatusBarIndicatorAirplaneModeItem: 0x1d0443ea0: identifier=_UIStatusBarIndicatorAirplaneModeItem>,
            _UIStatusBarBatteryItem = <_UIStatusBarBatteryItem: 0x1d46759c0: identifier=_UIStatusBarBatteryItem>,
            _UIStatusBarWifiItem = <_UIStatusBarWifiItem: 0x1d44588d0: identifier=_UIStatusBarWifiItem>,
            _UIStatusBarIndicatorVPNItem = <_UIStatusBarIndicatorVPNItem: 0x1d4458c90: identifier=_UIStatusBarIndicatorVPNItem>,
            _UIStatusBarIndicatorAirPlayItem = <_UIStatusBarIndicatorAirPlayItem: 0x1d445db50: identifier=_UIStatusBarIndicatorAirPlayItem>,
            _UIStatusBarIndicatorLiquidDetectionItem = <_UIStatusBarIndicatorLiquidDetectionItem: 0x1d4640a80: identifier=_UIStatusBarIndicatorLiquidDetectionItem>,
            _UIStatusBarTimeItem = <_UIStatusBarTimeItem: 0x1d027ff00: identifier=_UIStatusBarTimeItem>
        }>


發現了幾個關於蜂窩資料與wifi的item

_UIStatusBarCellularItem

_UIStatusBarWifiItem

然後看看如何獲取這些Items。

通過xcode設定斷點直接檢視,得到items裡面沒有什麼可用資訊,但是在_displayItemStates有

列印_displayItemStates得到

裡面包括狀態列的所有元素,列印一個

_dataEnabled就是資料可用的狀態

下面就是判斷的程式碼,

- (BOOL)networkingStatesFromStatebar {
    if(IsIphoneX){
    //適配iPhoneX

        UIApplication *app = [UIApplication sharedApplication] ;

        NSDictionary *_displayItemStates = [[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_displayItemStates"];
        //
        //wifi
        //
        id value = _displayItemStates[@"_UIStatusBarWifiItem.signalStrengthDisplayIdentifier"];
        NSLog(@"%@",[value class]);//_UIStatusBarDisplayItemState
        bool _dataEnabled =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
        if (_dataEnabled == YES) {
            return YES;
        }
        //
        //移動資料
        //
        value = _displayItemStates[@"_UIStatusBarCellularItem.typeDisplayIdentifier"];
        bool _dataEnabledCell =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
        if (_dataEnabledCell == YES) {
            return YES;
        }
        
        return NO;
    }else{
    
        UIApplication *app = [UIApplication sharedApplication];
        NSArray *children = nil;
        children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
        int type = 0;
        for (id child in children) {
            if ([child isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
                type = [[child valueForKeyPath:@"dataNetworkType"] intValue];
            }
        }
        
        if (type == 0) {
            return NO;
        }else{
            return YES;
        }
    }

iOS12的狀態列結構有變化需要更改一下(20180818更新):

- (BOOL)networkingStatesFromStatebar {
    if(IsIphoneX){
    //適配iPhoneX

        UIApplication *app = [UIApplication sharedApplication] ;

        NSDictionary *_displayItemStates = [[[app valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_statusBar"] valueForKeyPath:@"_displayItemStates"];
        //
        //wifi
        //
        id value = _displayItemStates[@"_UIStatusBarWifiItem.signalStrengthDisplayIdentifier"];
        NSLog(@"%@",[value class]);//_UIStatusBarDisplayItemState
        bool _dataEnabled =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
        if (IOS12_OR_LATER) {
            for (id ieentifi in _displayItemStates.allKeys) {
                NSString *identifier = [NSString stringWithFormat:@"%@",ieentifi];
                if ([identifier isEqualToString:@"_UIStatusBarWifiItem.signalStrengthDisplayIdentifier"]) {
                    value = _displayItemStates[ieentifi];
                    _dataEnabled =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
                }
            }
        }
        
        if (_dataEnabled == YES) {
            return YES;
        }
        //
        //移動資料
        //
        value = _displayItemStates[@"_UIStatusBarCellularItem.typeDisplayIdentifier"];
        bool _dataEnabledCell =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
        if (IOS12_OR_LATER) {
            bool _dataEnabledCell111111 = false;
            bool _dataEnabledCell222222 = false;
            
            for (id ieentifi in _displayItemStates.allKeys) {
                NSString *identifier = [NSString stringWithFormat:@"%@",ieentifi];
//

                if ([identifier isEqualToString:@"_UIStatusBarCellularCondensedItem.typeDisplayIdentifier"]) {
                    value = _displayItemStates[ieentifi];
                    _dataEnabledCell111111 =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
                }
                if ([identifier isEqualToString:@"_UIStatusBarSecondaryCellularExpandedItem.typeDisplayIdentifier"]) {
                    value = _displayItemStates[ieentifi];
                    _dataEnabledCell222222 =[[value valueForKeyPath:@"_dataEnabled"]boolValue];
                }
                
            }
            _dataEnabledCell = _dataEnabledCell111111 || _dataEnabledCell222222;
        }
        if (_dataEnabledCell == YES) {
            return YES;
        }
        
        return NO;
    }else{
    
        NSLog(@"%@",GlobalVariablesSingle.name);
        NSLog(@"%d",[[[UIDevice currentDevice] systemVersion] intValue]);
        //ios12測試版系統崩潰ipadpro 只要ios12的ipad系統都不判斷
        if (([GlobalVariablesSingle.name rangeOfString:@"iPad"].length > 0)
            && [[[UIDevice currentDevice] systemVersion] intValue] == 12) {
            return YES;
        }
        
        UIApplication *app = [UIApplication sharedApplication];
        NSArray *children = nil;
        children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
        int type = 0;
        for (id child in children) {
            if ([child isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) {
                type = [[child valueForKeyPath:@"dataNetworkType"] intValue];
            }
        }
        
        if (type == 0) {
            return NO;
        }else{
            return YES;
        }
    }
}