在開發項目中,會有這樣變態的需求:
-
推送:根據服務端推送過來的數據規則,跳轉到對應的控制器
-
feeds列表:不同類似的cell,可能跳轉不同的控制器(噓!產品經理是這樣要求:我也不確定會跳轉哪個界面哦,可能是這個又可能是那個,能給我做靈活嗎?根據後臺返回規則任意跳轉?)
思考:wocao!這變態的需求,要拒絕他嗎?
switch判斷唄,考慮所有跳轉的因素?這不得寫死我...
1
2
3
4
5
6
|
switch () { case : break ; default : break ; } |
我是這麼個實現的(runtime是個好東西)
利用runtime動態生成對象、屬性、方法這特性,我們可以先跟服務端商量好,定義跳轉規則,比如要跳轉到A控制器,需要傳屬性id、type,那麼服務端返回字典給我,裏面有控制器名,兩個屬性名跟屬性值,客戶端就可以根據控制器名生成對象,再用kvc給對象賦值,這樣就搞定了 ---O(∩_∩)O哈哈哈
比如:根據推送規則跳轉對應界面HSFeedsViewController
HSFeedsViewController.h:
-
進入該界面需要傳的屬性
1
2
3
4
5
6
7
|
@interface HSFeedsViewController : UIViewController // 注:根據下面的兩個屬性,可以從服務器獲取對應的頻道列表數據 /** 頻道ID */ @property (nonatomic, copy) NSString *ID; /** 頻道type */ @property (nonatomic, copy) NSString *type; @end |
AppDelegate.m:
-
推送過來的消息規則
1
2
3
4
5
6
7
8
|
// 這個規則肯定事先跟服務端溝通好,跳轉對應的界面需要對應的參數 NSDictionary *userInfo = @{ @ "class" : @ "HSFeedsViewController" , @ "property" : @{ @ "ID" : @ "123" , @ "type" : @ "12" } }; |
-
接收推送消息
1
2
3
4
|
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { [self push:userInfo]; } |
-
跳轉界面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
- (void)push:(NSDictionary *)params { // 類名 NSString *class =[NSString stringWithFormat:@ "%@" , params[@ "class" ]]; const char *className = [class cStringUsingEncoding:NSASCIIStringEncoding]; // 從一個字串返回一個類 Class newClass = objc_getClass(className); if (!newClass) { // 創建一個類 Class superClass = [NSObject class]; newClass = objc_allocateClassPair(superClass, className, 0); // 註冊你創建的這個類 objc_registerClassPair(newClass); } // 創建對象 id instance = [[newClass alloc] init]; // 對該對象賦值屬性 NSDictionary * propertys = params[@ "property" ]; [propertys enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { // 檢測這個對象是否存在該屬性 if ([self checkIsExistPropertyWithInstance:instance verifyPropertyName:key]) { // 利用kvc賦值 [instance setValue:obj forKey:key]; } }]; // 獲取導航控制器 UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController; UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex]; // 跳轉到對應的控制器 [pushClassStance pushViewController:instance animated:YES]; } |
-
檢測對象是否存在該屬性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
- (BOOL)checkIsExistPropertyWithInstance:(id)instance verifyPropertyName:(NSString *)verifyPropertyName { unsigned int outCount, i; // 獲取對象裏的屬性列表 objc_property_t * properties = class_copyPropertyList([instance class], &outCount); for (i = 0; i < outCount; i++) { objc_property_t property =properties[i]; // 屬性名轉成字符串 NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding]; // 判斷該屬性是否存在 if ([propertyName isEqualToString:verifyPropertyName]) { free(properties); return YES; } } free(properties); return NO; } |