//
// 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
runtime跳转界面以及动态添加属性
最新推荐文章于 2022-07-17 12:09:51 发布