zoukankan      html  css  js  c++  java
  • ios开发 Reflection(一)

    NSObject 方法

    除了个别例外,Cocoa 中大部分类都是 NSObject 的子类,因此大部分对象都继承了它所定义的方法。

    NSObject 提供了一些简单的查询运行时系统信息的方法:

    1 - (BOOL)isKindOfClass:(Class)aClass;
    2 - (BOOL)isMemberOfClass:(Class)aClass;
    3 - (BOOL)conformsToProtocol:(Protocol *)aProtocol;
    4 
    5 - (BOOL)respondsToSelector:(SEL)aSelector;

    第1行判断instance的class类型

    第2行判断Member是否属于类

    第3行判断委托是否属于类

    第4行判断方法是否属于类

    测试

     1     //test Member
     2     BOOL bMember=[@"sName" isMemberOfClass:[self class]];
     3     BOOL bMember1=[@"sName" isMemberOfClass:[self class]];
     4     NSLog(@"bMember:%d,bMember1:%d",bMember,bMember1);
     5     
     6     //test Method
     7     BOOL bMethod=[@"showBook" isMemberOfClass:[self class]];
     8     BOOL bMethod1=[@"showBook" isMemberOfClass:[self class]];
     9     NSLog(@"bMethod:%d,bMethod1:%d",bMethod,bMethod1);
    10     
    11     //test Protocol
    12     BOOL bProtocol=[self conformsToProtocol:@protocol(vcDelegate)];
    13     NSLog(@"bprotocol:%d",bProtocol);

    消息传递

    在 Objective-C,直到运行时消息才会绑定到方法实现。

    编译器把消息表达式(message expression)转换为调用 Objective-C 运行时函数 objc_msgSend

    [receiver message] -> objc_msgSend(receiver, selector)

    id objc_msgSend(id theReceiver, SEL theSelector, ...)

    Sends a message with a simple return value to an instance of a class.

     

    使用 objc_msgSend 函数,需要引入 Objective-C 运行时头文件:#import <objc/message.h>

    [self test];
    objc_msgSend(self, @selector(test));

    通过定义在 NSObject 类中的方法 methodForSelector: ,你可以请求一个方法实现过程(procedure)的指针。

    - (IMP)methodForSelector:(SEL)aSelector

    Locates and returns the address of the receiver’s implementation of a method so it can be called as a function.

    调用 IMP,头两个需要传递的参数,第一个是消息接收的对象,第二个是 selector。

    IMP test = [self methodForSelector:@selector(test)];
    test(self, @selector(test));

    动态方法 

    有些情况下,我们会想要提供动态的方法实现。

    Objective-C 通过使用 @dynamic 声明属性(property)来告诉编译器,属性(property)相关的方法将会动态地提供。

    你可以通过实现方法 resolveInstanceMethod: 和 resolveClassMetho: 为相应的一个实例和类方法来动态地提供一个 selector 实现。

    • + (BOOL)resolveInstanceMethod:(SEL)name
      Dynamically provides an implementation for a given selector for an instance method.

    • + (BOOL)resolveClassMethod:(SEL)name
      Dynamically provides an implementation for a given selector for a class method.

    定义一个 User 类

    在 .h 文件,定义属性 name

    以往,会在相应的 .m 文件,使用 @synthesize 声明属性 name,这样编译器会自动生成相应的 setter 和 getter 方法

    但是,当使用 @dynamic 声明属性 name 时,就必须自己提供相应的 setter 和 getter 方法

    Override + (BOOL)resolveInstanceMethod:(SEL)name 方法

    当类实例调用 - (void)setName:(NSString) aName 或  -(NSString *)name 方法时,就为其动态地提供方法实现

    1 #import <Foundation/Foundation.h>
    2 
    3 @interface User : NSObject {
    4     NSString *name;
    5 }
    6 
    7 @property (nonatomic, retain) NSString *name;
    8 
    9 @end
     1 #import "User.h"
     2 #import <objc/runtime.h>
     3 
     4 @implementation User
     5 
     6 @dynamic name;
     7 
     8 - (void)dynamicSetName:(NSString *) aName {
     9     if (name != nil) {
    10         [name release];
    11         name = nil;
    12     }
    13     [aName retain];
    14     name = aName;
    15 }
    16 
    17 - (NSString *)dynamicName {
    18     return name;
    19 }
    20 
    21 + (BOOL)resolveInstanceMethod:(SEL)sel {
    22     NSLog(@"Instance Method: %@", NSStringFromSelector(sel));
    23     if ([@"setName:" isEqualToString:NSStringFromSelector(sel)]) {
    24         class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicSetName:)], "v@:");
    25         return YES;
    26     } else if ([@"name" isEqualToString:NSStringFromSelector(sel)]) {
    27         class_addMethod([self class], sel, [self instanceMethodForSelector:@selector(dynamicName)], "@");
    28         return YES;
    29     }
    30     return [super resolveInstanceMethod:sel];
    31 }
    32 
    33 @end
  • 相关阅读:
    使用openssl实现ECDSA签名以及验证功能(附完整测试源码)
    【转载】浅谈Linux内存管理机制
    【转载】Abstract Factory Step by Step --- 抽象工厂
    【转载】动态规划:从新手到专家
    Windows Container 和 Docker:你需要知道的5件事
    十年
    Docker,容器,虚拟机和红烧肉
    新的用户故事待办列表就是一副地图
    MarkDown/reST 文档发布流水线
    docker4dotnet #5 使用VSTS/TFS搭建基于容器的持续交付管道
  • 原文地址:https://www.cnblogs.com/guchengfengyun/p/4065467.html
Copyright © 2011-2022 走看看