iOS-萬能跳轉界面方法 (runtime實用篇一) 字數733 閱讀1080 評論28 喜歡51

在開發項目中,會有這樣變態的需求:

  • 推送:根據服務端推送過來的數據規則,跳轉到對應的控制器
  • feeds列表:不同類似的cell,可能跳轉不同的控制器(噓!產品經理是這樣要求:我也不確定會跳轉哪個界面哦,可能是這個又可能是那個,能給我做靈活嗎?根據後臺返回規則任意跳轉?)

思考:wocao!這變態的需求,要拒絕他嗎?
switch判斷唄,考慮所有跳轉的因素?這不得寫死我...

switch () {
    case :
        break;
    default:
        break;
}

我是這麼個實現的(runtime是個好東西)

利用runtime動態生成對象、屬性、方法這特性,我們可以先跟服務端商量好,定義跳轉規則,比如要跳轉到A控制器,需要傳屬性id、type,那麼服務端返回字典給我,裏面有控制器名,兩個屬性名跟屬性值,客戶端就可以根據控制器名生成對象,再用kvc給對象賦值,這樣就搞定了 ---O(∩_∩)O哈哈哈

比如:根據推送規則跳轉對應界面HSFeedsViewController

HSFeedsViewController.h

  • 進入該界面需要傳的屬性
@interface HSFeedsViewController : UIViewController

// 注:根據下面的兩個屬性,可以從服務器獲取對應的頻道列表數據

/** 頻道ID */
@property (nonatomic, copy) NSString *ID;

/** 頻道type */
@property (nonatomic, copy) NSString *type;

@end

AppDelegate.m

  • 推送過來的消息規則
// 這個規則肯定事先跟服務端溝通好,跳轉對應的界面需要對應的參數
NSDictionary *userInfo = @{
                           @"class": @"HSFeedsViewController",
                           @"property": @{
                                        @"ID": @"123",
                                        @"type": @"12"
                                   }
                           };
  • 接收推送消息
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [self push:userInfo];
}
  • 跳轉界面
- (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];
}
  • 檢測對象是否存在該屬性
- (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;
}

具體使用和代碼: https://github.com/HHuiHao/Universal-Jump-ViewController

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章