iOS高级面试题(一)内存管理篇--runtime(一)

runtime:运行时机制

  1. 是什么?

 -  1.1 runtime是一套比较底层的纯C语言的API,runtime就是一个库,一个C语言库,包含了许多底层的C语言API

  -  1.2平时我们编写的OC代码,在程序运行过程中,其实最终都是转成了runtime的C语言代码,runtime算是OC的幕后工作者,是整个OC的底层

   - 1.3举个例子
  oc中的代码:[Student alloc] init]经过runtime后,其实最终在底层生成C语言代码:
  objc_msgSend(objc_msgSend("Student","alloc"), "init")
  objc_msgSend其实就是想某个对象发送什么消息,这个函数第一个参数是类型或对象名,第二个参数是消息的名字,这些代码比较底层

  2. 用过吗?怎么用?
   - 2.1 runtime是属于OC的底层,可以进行一些非常底层的操作(用OC无法实现的,或者说不好实现)eg
   - *在程序运行过程中,动态创建一个类,(比如KVO和KVC的底层实现)
   - *在程序运行过程中,动态为某个类添加属性/方法,修改属性值,修改方法
   - *遍历一个类中所有的属性和实例变量和所有方法

  3. 
  -  3.1相关的头文件
  - #import //消息发送机制,可以直接用底层函数,进行消息发送
  -  3.2相关应用
  - *NSCoding(归档和解挡)
  -  *字典转模型(利用runtime遍历模型对象的所有属性,根据属性名从字典中取出对应的值,设置到模型的属性上)
  - *kvo(利用runtime动态产生一个类)

   - 3.3相关函数
  msg_send:给对象发送消息,来自
  class_copyMethodList,遍历某个类中所有的方法,来自
  class_copyIvarList,遍历某个类中所有的实例变量的方法,来自

  运行时必备常识:
  1.Ivar:成员变量的意思
  2.Method:成员方法的意思
  3.property:属性
  1. 你使用过Objective-C的运行时编程(Runtime Programming)么?如果使用过,你用它做了什么?你还能记得你所使用的相关的头文件或者某些方法的名称吗?

runtime 运行时的动态添加属性方法,
动态添加 set 方法

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

动态添加 get 方法

OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

具体方法使用如下

#import <UIKit/UIKit.h>

@interface UIControl (ReName)

@property (nonatomic, copy) NSString *reName;

@end

UIControl+ReName.m

#import "UIControl+ReName.h"
#import <objc/runtime.h>
static const char * RENAME_CONST = "RECONST";

@implementation UIControl (ReName)

-(void)setReName:(NSString *)reName
{
    objc_setAssociatedObject(self, RENAME_CONST, reName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

-(NSString *)reName
{
   return objc_getAssociatedObject(self, RENAME_CONST);
}
@end

使用方法如下

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.reName = @"my name is new button";
    NSLog(@"%@",button.reName);
}

常用的方法使用名称

// 1.获得类中的所有成员变量

Ivar*ivarList =class_copyIvarList([selfclass], &count);

//2.获得方法的名字的字符串

NSSelectorFromString(_cmd)

//3.发送消息函数

objc_msgSend()

runtim 运行时 动态归档方法代码如下
调用方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    Student *student = [[Student alloc] init];
    student.name1 = @"sunlin";
    student.age = 18;
    student.name2 = @"sunlin";
    student.name3 = @"sunlin";
    student.name4 = @"sunlin";
    student.name5 = @"sunlin";
    student.name6 = @"sunlin";
    student.name7 = @"sunlin";
    //  归档文件的路径
    NSString *filePath = [NSHomeDirectory()stringByAppendingPathComponent:@"person.archiver"];
    //  判断该文件是否存在
    if (![[NSFileManager defaultManager]fileExistsAtPath:filePath]) {
        //  不存在的时候,归档存储一个Student的对象
        NSMutableData *data = [NSMutableData data];
        NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
        [archiver encodeObject:student forKey:@"student"];
        [archiver finishEncoding];

        BOOL success = [data writeToFile:filePath atomically:YES];
        if (success) {
            NSLog(@"归档成功!");
        }
    } else{
        //  存在的时候,不再进行归档,而是解挡!
        NSData *data = [NSData dataWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unArchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        Student *studentFromSaving = [unArchiver decodeObjectForKey:@"student"];

        NSLog(@"%@, %lu", studentFromSaving.name7, studentFromSaving.age);
    }

    return YES;

}

Student.h

#import <Foundation/Foundation.h>

@interface Student : NSObject<NSCoding>
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *name1;
@property (nonatomic, copy) NSString *name2;
@property (nonatomic, copy) NSString *name3;
@property (nonatomic, copy) NSString *name4;
@property (nonatomic, copy) NSString *name5;
@property (nonatomic, copy) NSString *name6;
@property (nonatomic, copy) NSString *name7;


@end

Student.m

#import "Student.h"
#import <objc/runtime.h>

@implementation Student

-(void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        const char *name =ivar_getName(ivar);
        NSString *nameStr = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
        id value = [self valueForKey:nameStr];
        [aCoder encodeObject:value forKey:nameStr];
    }
    free(ivars);
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([self class], &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            NSString *key = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
            id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
        free(ivars);
    }
    return self;
}
@end
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值