你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> iOS開發之runtime的運用

iOS開發之runtime的運用

編輯:關於IOS

之前寫過runtime的一些東西,這次通過runtime獲取一些蘋果官方不想讓你拿到的東西,比如,狀態欄內部的控件屬性。本文將通過runtime帶你一步步拿到狀態欄中顯示網絡狀態的控件,然後通過監測該控件的屬性來獲取當前精確網絡狀態,比如2G/3G/4G/WIFI。

  首先,我們需要拿到狀態欄,然後通過runtime去探討狀態欄內部的組成結構。   1、導入運行時頭文件   #import <objc/message.h> 2、編寫運行時代碼,獲取到當前應用程序的所有成員變量   復制代碼  1 #import "ViewController.h"  2 #import <objc/message.h>  3   4 @interface ViewController ()  5   6 @end  7   8 @implementation ViewController  9  10 - (void)viewDidAppear:(BOOL)animated 11 { 12     // 狀態欄是由當前app控制的,首先獲取當前app 13     UIApplication *app = [UIApplication sharedApplication]; 14      15     // 遍歷當前app的所有屬性,找到關於狀態欄的 16     unsigned int outCount = 0; 17      18     Ivar *ivars = class_copyIvarList(app.class, &outCount); 19      20     for (int i = 0; i < outCount; i++) { 21         Ivar ivar = ivars[i]; 22         printf("|%s", ivar_getName(ivar)); 23     } 24 } 25  26 @end 復制代碼 直接運行,可以看到打印結果為:   3、可以看app裡確實有個關於狀態欄的成員變量,我們通過KVC取出它   復制代碼  1 - (void)viewDidAppear:(BOOL)animated  2 {  3     // 狀態欄是由當前app控制的,首先獲取當前app  4     UIApplication *app = [UIApplication sharedApplication];  5       6     id statusBar = [app valueForKeyPath:@"statusBar"];  7       8     // 遍歷狀態欄的所有成員  9     unsigned int outCount = 0; 10     Ivar *ivars = class_copyIvarList([statusBar class], &outCount); 11      12     for (int i = 0; i < outCount; i++) { 13         Ivar ivar = ivars[i]; 14         printf("|%s", ivar_getName(ivar)); 15     } 16 } 復制代碼 運行後可以看到打印結果為   4、狀態欄裡有foregroundView這個成員,應該代表著所有當前顯示的視圖,通過KVC取出它裡面的所有子視圖   復制代碼 1 // 狀態欄是由當前app控制的,首先獲取當前app 2     UIApplication *app = [UIApplication sharedApplication]; 3      4     NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews]; 5      6     for (id child in children) { 7         NSLog(@"--%@", [child class]); 8     } 復制代碼 打印結果為   5、遍歷數組,取出用於顯示網絡狀態的視圖,並遍歷其內部的所有成員變量   復制代碼  1 // 狀態欄是由當前app控制的,首先獲取當前app  2     UIApplication *app = [UIApplication sharedApplication];  3       4     NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];  5       6     for (id child in children) {  7         if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {  8             // 遍歷當前狀態欄的所有屬性,找到關於狀態欄的  9             unsigned int outCount = 0; 10             Ivar *ivars = class_copyIvarList([child class], &outCount); 11              12             for (int i = 0; i < outCount; i++) { 13                 Ivar ivar = ivars[i]; 14                 printf("|%s", ivar_getName(ivar)); 15             } 16         } 17     } 復制代碼 打印結果為   6、下面通過KVC,取出dataNetworkType   1 if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { 2             id type = [child valueForKeyPath:@"dataNetworkType"]; 3             NSLog(@"_dataNetworkType class is %@, value is %@", [type class], type); 4         } 打印結果為:    可見,dataNetworkType類型是NSNumber,值是5。【以上均為模擬器測試】   經過測試,發現,可能的值為 1,2,3,5 分別對應的網絡狀態是2G、3G、4G及WIFI。 當沒有網絡時,隱藏UIStatusBarDataNetworkItemView,無法獲取dataNetworkType值       總結:   以下是完整的代碼,並經過真機測試:   復制代碼  1 - (void)viewDidAppear:(BOOL)animated  2 {  3     // 狀態欄是由當前app控制的,首先獲取當前app  4     UIApplication *app = [UIApplication sharedApplication];  5       6     NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];  7       8     int type = 0;  9     for (id child in children) { 10         if ([child isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) { 11             type = [[child valueForKeyPath:@"dataNetworkType"] intValue]; 12         } 13     } 14     NSLog(@"----%d", type);  15 } 復制代碼 打印出的type數字對應的網絡狀態依次是:0 - 無網絡; 1 - 2G; 2 - 3G; 3 - 4G; 5 - WIFI
  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved