runtime跳转界面以及动态添加属性

//
//  ViewController.m
//  Runtime处理界面跳转
//
//  Created by 陆巧怡 on 15/9/15.
//  Copyright (c) 2015年 Simon. All rights reserved.
//

#import "ViewController.h"
#import <objc/runtime.h>
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    for (int i = 0; i<5; i++) {
        
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
        btn.frame = CGRectMake(0, 20+50*(i+1), 100, 40);
        [btn setTitle:[NSString stringWithFormat:@"第%d个界面",i+1] forState:UIControlStateNormal];
        btn.tag = i+1;
        [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:btn];
    }


}
-(void)btnAction:(UIButton *)btn{
    
    NSString *viewcontrollerName = nil;
    
    switch (btn.tag) {
        case 1:
        {
            viewcontrollerName = @"FirstViewController";
        }
            break;
        case 2:
        {
            viewcontrollerName = @"SecondViewController";

        }
            break;
        case 3:
        {
            viewcontrollerName = @"ThreeViewController";

        }
            break;
        case 4:
        {
            viewcontrollerName = @"FourViewController";

        }
            break;
        case 5:
        {
            viewcontrollerName = @"FiveViewController";

        }
            break;
        default:
            break;
    }
    
    
    [self pushViewcontroller:viewcontrollerName];
}

-(void)pushViewcontroller:(NSString *)viewcontrollerName{
    
    
    
    //类名转换成char字符,用于下面创建类
    const char *className = [viewcontrollerName cStringUsingEncoding:NSASCIIStringEncoding];
    //获取目标类
    Class targetObject = objc_getClass(className);
    
    //如果这个类不存在===>动态创建类
    if (!targetObject) {
        /*
         运行时创建类只需要三步:
         1、为"class pair"分配空间(使用objc_allocateClassPair).
         2、为创建的类添加方法和成员(上例使用class_addMethod添加了一个方法)。
         3、注册你创建的这个类,使其可用(使用objc_registerClassPair)。
         */
        //创建一个类
        Class newClass = [NSObject class];
        targetObject = objc_allocateClassPair(newClass, className, 0);
        //注册这个类
        objc_registerClassPair(targetObject);
        
    }
    
    //创建对象
    id instanceObject = [[targetObject alloc]init];
    
    /*
        在这里,除了FirstViewController才有一个titleName的属性,其他ViewController都没有
        模拟动态增加属性以及对已有属性进行赋值
     */
    
    [self checkIsPropertyWithInstanceObject:instanceObject withPropertyName:@"titleName" withInstanceName:viewcontrollerName];
    
    [self.navigationController pushViewController:(UIViewController *)instanceObject animated:YES];

}

#pragma mark 检测该对象是否包含该属性。包含就赋值。不包含就增加该属性,然后赋值
-(void)checkIsPropertyWithInstanceObject:(id)instanceObject withPropertyName:(NSString *)propertyName withInstanceName:(NSString *)instanceName{

    u_int count;
    
    //获取该对象里面的所有属性
    objc_property_t *propertys = class_copyPropertyList(object_getClass(instanceObject), &count);
    
    //记录是否有目标属性
    BOOL targetPropertyBool = NO;
    
    //遍历属性
    for (int i =0; i<count; i++) {
        //获取属性名字
        const char *charName = property_getName(propertys[i]);
        //匹配目标属性(propertyName)名字
        if ([[NSString stringWithCString:charName encoding:NSUTF8StringEncoding] isEqualToString:propertyName]) {
            //kvc赋值
            [instanceObject setValue:instanceName forKey:propertyName];
            targetPropertyBool = YES;
        }
    }
    
    /*
     OBJC_ASSOCIATION_ASSIGN;            //assign策略
     OBJC_ASSOCIATION_COPY_NONATOMIC;    //copy策略
     OBJC_ASSOCIATION_RETAIN_NONATOMIC;  // retain策略
     
     OBJC_ASSOCIATION_RETAIN;
     OBJC_ASSOCIATION_COPY;
     */
    /*
     * 
     
     objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
     
     id object 给哪个对象的属性赋值
     const void *key 属性对应的key
     id value  设置属性值为value
     objc_AssociationPolicy policy  使用的策略,是一个枚举值,和copy,retain,assign是一样的,手机开发一般都选择NONATOMIC
     */
    
    //该对象里面没有这个属性(propertyName)则动态添加该属性(propertyName)
    if (!targetPropertyBool) {
        
        const char *charPropertyName = [propertyName cStringUsingEncoding:NSASCIIStringEncoding];
        objc_setAssociatedObject(instanceObject, charPropertyName, instanceName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    free(propertys);
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值