1. 程式人生 > >iOS10 優化APP首次安裝網路許可權提示方案

iOS10 優化APP首次安裝網路許可權提示方案

我剛經歷了一場末日(停電),特別是在你想寫文件的時候。。。

言歸正傳,今天的問題是解決iOS10系統下首次按鈕APP彈出的網路許可權提示所帶來了問題以及優化。

起因

查了相關文章知道由於大陸工信部出臺的新規指出,應用在未經使用者允許的前提下,系統不能授予其使用聯網、獲取定位的功能。Apple在iOS10系統中加入了關於應用使用資料的授權彈窗提示,使用者在iOS系統及以上系統中第一次開啟應用時,會被要求對於是否授予應用聯網許可權進行選擇。

問題

Apple把自己的問題解決了, 但是Apple沒有給出官方的獲取選擇事件的回撥,這樣就是給開發者挖坑了。

對於很多開發者習慣於把預載入介面放到AppDelegate的同志就很苦惱了。

這樣會造成配置介面請求失敗,首頁資料為空的情況,第一次獲取DeviceToken失敗,新增推送通知失敗,第三方初始化失敗,以至於導致很多延伸的問題。

解決

1.根據CTCellularData類獲取網路許可權狀態以及監聽狀態改變回調(推薦)

我就在使用此方法。話不多說上程式碼,註釋很詳細;

新增CoreTelephony系統庫,在AppDelegate.m裡#import<CoreTelephony/CTCellularData.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    //1.獲取網路許可權 根絕許可權進行人機互動
    if (__IPHONE_10_0) {
        [self networkStatus:application didFinishLaunchingWithOptions:launchOptions];
    }else {
        //2.2已經開啟網路許可權 監聽網路狀態
        [self addReachabilityManager:application didFinishLaunchingWithOptions:launchOptions];
    }
    
    //初始化window
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self.window setBackgroundColor:[UIColor whiteColor]];
    
//    //建立UI
    [self createWindowRootWithType:2];
    
    [self.window makeKeyAndVisible];
    return YES;
}

/*
 CTCellularData在iOS9之前是私有類,許可權設定是iOS10開始的,所以App Store稽核沒有問題
 獲取網路許可權狀態
 */
- (void)networkStatus:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //2.根據許可權執行相應的互動
    CTCellularData *cellularData = [[CTCellularData alloc] init];
    
    /*
     此函式會在網路許可權改變時再次呼叫
     */
    cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state) {
        switch (state) {
            case kCTCellularDataRestricted:
                
                NSLog(@"Restricted");
                //2.1許可權關閉的情況下 再次請求網路資料會彈出設定網路提示
                [self getAppInfo];
                break;
            case kCTCellularDataNotRestricted:
                
                NSLog(@"NotRestricted");
                //2.2已經開啟網路許可權 監聽網路狀態
                [self addReachabilityManager:application didFinishLaunchingWithOptions:launchOptions];
//                [self getInfo_application:application didFinishLaunchingWithOptions:launchOptions];
                break;
            case kCTCellularDataRestrictedStateUnknown:
                
                NSLog(@"Unknown");
                //2.3未知情況 (還沒有遇到推測是有網路但是連線不正常的情況下)
                [self getAppInfo];
                break;
                
            default:
                break;
        }
    };
}

/**
 實時檢查當前網路狀態
 */
- (void)addReachabilityManager:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    AFNetworkReachabilityManager *afNetworkReachabilityManager = [AFNetworkReachabilityManager sharedManager];
    
    //這個可以放在需要偵聽的頁面
    //    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(afNetworkStatusChanged:) name:AFNetworkingReachabilityDidChangeNotification object:nil];
    [afNetworkReachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        switch (status) {
            case AFNetworkReachabilityStatusNotReachable:{
                NSLog(@"網路不通:%@",@(status) );
                break;
            }
            case AFNetworkReachabilityStatusReachableViaWiFi:{
                NSLog(@"網路通過WIFI連線:%@",@(status));
                if (self.mallConfigModel == nil) {
                   [self getInfo_application:application didFinishLaunchingWithOptions:launchOptions];
                }
                break;
            }
            case AFNetworkReachabilityStatusReachableViaWWAN:{
                NSLog(@"網路通過無線連線:%@",@(status) );
                if (self.mallConfigModel == nil) {
                    [self getInfo_application:application didFinishLaunchingWithOptions:launchOptions];
                }
                break;
            }
            default:
                break;
        }
    }];
    
    [afNetworkReachabilityManager startMonitoring];  //開啟網路監視器;
}

- (void)getInfo_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //第三方庫初始化
    [self initValueThirdParty:application didFinishLaunchingWithOptions:launchOptions];
    
//    //獲取初始資訊
    [self initData];
    
    //新增通知
    [self addNotification];
}

這樣也同時解決了使用者如果選擇不允許和限制兩種情況,在使用者沒有統一聯網的情況下,APP會顯示沒有網路的UI,重新進入APP會呼叫在不允許狀態下會呼叫一個測試介面,APP會自動彈出重新選擇網路許可權以及說明的彈窗,進入設定修改過APP聯網許可權以後選擇回到APP就會觸發cellularDataRestrictionDidUpdateNotifier,在回撥裡進行相應的人機互動就可以了。

2018年08月09日更新

這段時間一直出現微信沒有註冊的問題,不是必現而且只有線上存在,推薦大家第三方庫(特別是需要網路的庫)的初始化不需要放到判斷網路許可權裡面,直接初始化。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
        
    //預設更新
    self.appIsUpdate = YES;
    
    //1.獲取網路許可權 根絕許可權進行人機互動
    if (IS_IOS_(10)) {
        [self networkStatus:application didFinishLaunchingWithOptions:launchOptions];
    }else {
        //2.2已經開啟網路許可權 監聽網路狀態
        [self addReachabilityManager:application didFinishLaunchingWithOptions:launchOptions];
    }
    
    //初始化第三方庫
    [self initValueThirdParty:application didFinishLaunchingWithOptions:launchOptions];
    
    //啟動頁停留1秒鐘。
    [NSThread sleepForTimeInterval:1.0];
    
    //初始化window
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    [self.window setBackgroundColor:[UIColor whiteColor]];
    
    //建立主檢視
    if ([DataBase nowUser]) {
        
        [self createWindowRootWithType:2];
    }else {
        
        [self createWindowRootWithType:1];
    }
    
    [self.window makeKeyAndVisible];
    return YES;
}

2.延遲請求

就是把配置請求放到首頁VC裡,不要放到AppDelegate裡,同時監聽網路狀態(AF,其他第三方等)有個致命性的問題就是獲取網路狀態會有一定的延遲(親測),導致很多情況,還有就是要自己處理許可權彈框以及對原有程式碼邏輯要進行修改。

總結

這個問題遇到幾次了,原來都是用第二種方式進行了一定的優化,這次的APP有一個配置資訊介面導致出現問題,寫下來作為記錄,方法還有很多種,不足的地方還有很多,僅供大家參考。