我們都知道Object-C是一種是根據C語言所衍生出來的語言,因此我們的代碼在程序運行過程中都會被轉化成C代碼執行,而runtime就相當于這個橋梁,對于一個想要真正理解OC語言的人,學習runtime是必不可少的,好比想要深刻理解java,映射是必不可少一樣。
例如[objc logMyInfo];會被轉化成objc_msgSend(objc, @selector(logMyInfo));。
OC中一切都被設計成了對象,我們都知道一個類被初始化成一個實例,這個實例是一個對象。實際上一個類本質上也是一個對象,在runtime中用結構體表示。
例如導入#import <objc/runtime.h>我們可以從runtime中看到
/// An opaque type that rePResents a method in a class definition.描述類中的一個方法typedef struct objc_method *Method;/// An opaque type that represents an instance variable.實例變量typedef struct objc_ivar *Ivar;/// An opaque type that represents a category. 類別Categorytypedef struct objc_category *Category;/// An opaque type that represents an Objective-C declared property.類中聲明的屬性typedef struct objc_property *objc_property_t;//類在runtime中的表示struct objc_class { Class isa OBJC_ISA_AVAILABILITY; //指針,顧名思義,表示是一個什么, //實例的isa指向類對象,類對象的isa指向元類#if !__OBJC2__ //父類 Class super_class OBJC2_UNAVAILABLE; //類名 const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; //成員變量列表 struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; //方法列表 struct objc_method_list **methodLists OBJC2_UNAVAILABLE; //緩存 一種優化,調用過的方法存入緩存列表,下次調用先找緩存 struct objc_cache *cache OBJC2_UNAVAILABLE; //協議列表 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;#endif } OBJC2_UNAVAILABLE;實戰應用,獲取類屬性列表
1、首先我們先新建一個工程,然后創建一個測試類文件TestClass.h
2、然后新建一些測試類屬性,代碼如下
h文件
#import <Foundation/Foundation.h>@protocol TestDelegate <NSObject>- (void)testDelegateMethod;@end@interface TestClass : NSObject@property (nonatomic,weak) id<TestDelegate> delegate;@property (nonatomic,strong) NSString *outPrOne;- (void)thisTestMethod;@end/** 測試代理 */@protocol TestDelegateTwo <NSObject>- (void)testDelegateMethodTwo;@end@interface TestClassTwo : NSObject@property (nonatomic,weak) id<TestDelegateTwo> delegateTwo;- (void)thisTestMethodTwo;@endm文件#import "TestClass.h"@interface TestClass ()<TestDelegateTwo>@end@implementation TestClass{ NSString *instanceOne; TestClassTwo *testTwo;}- (instancetype)init{ self = [super init]; if (self) { testTwo.delegateTwo = self; } return self;}- (void)thisTestMethod{ if ([self.delegate respondsToSelector:@selector(testDelegateMethod)]) { [self.delegate testDelegateMethod]; } [testTwo thisTestMethodTwo];}- (void)testDelegateMethodTwo{ NSLog(@"thisTestMethodTwo");}@end@implementation TestClassTwo- (void)thisTestMethodTwo{ if ([self.delegateTwo respondsToSelector:@selector(testDelegateMethodTwo)]) { [self.delegateTwo testDelegateMethodTwo]; }}@end 3、然后在viewController新建此類,進行測試,代碼如下#import "ViewController.h"#import "TestClass.h"#import <objc/runtime.h>@interface ViewController ()<TestDelegate>@property (nonatomic,strong) TestClass *testClass;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; _testClass = [TestClass new]; _testClass.delegate = self; unsigned int count; //獲取屬性列表 objc_property_t *propertyList = class_copyPropertyList([_testClass class], &count); for (int i=0; i<count; i++) { const char *propertyName = property_getName(propertyList[i]); NSLog(@"property---->%@", [NSString stringWithUTF8String:propertyName]); } //獲取方法列表 Method *methodList = class_copyMethodList([_testClass class], &count); for (int i=0; i<count; i++) { Method method = methodList[i]; NSLog(@"method---->%@", NSStringFromSelector(method_getName(method))); } //獲取成員變量列表 Ivar *ivarList = class_copyIvarList([_testClass class], &count); for (int i=0; i<count; i++) { Ivar myIvar = ivarList[i]; const char *ivarName = ivar_getName(myIvar); NSLog(@"Ivar---->%@", [NSString stringWithUTF8String:ivarName]); } [_testClass thisTestMethod]; //獲取協議列表 __unsafe_unretained Protocol **protocolList = class_copyProtocolList([_testClass class], &count); for (int i=0; i<count; i++) { Protocol *myProtocal = protocolList[i]; const char *protocolName = protocol_getName(myProtocal); NSLog(@"protocol---->%@", [NSString stringWithUTF8String:protocolName]); }}- (void)testDelegateMethod{ NSLog(@"12111");}控制臺輸出如下2017-02-06 18:34:39.920 RuntimeDemo[10997:466991] property---->innerPrOne2017-02-06 18:34:39.921 RuntimeDemo[10997:466991] property---->delegate2017-02-06 18:34:39.921 RuntimeDemo[10997:466991] property---->outPrOne2017-02-06 18:34:39.922 RuntimeDemo[10997:466991] property---->hash2017-02-06 18:34:39.922 RuntimeDemo[10997:466991] property---->superclass2017-02-06 18:34:39.923 RuntimeDemo[10997:466991] property---->description2017-02-06 18:34:39.923 RuntimeDemo[10997:466991] property---->debugDescription2017-02-06 18:34:39.924 RuntimeDemo[10997:466991] method---->testDelegateMethodTwo2017-02-06 18:34:39.925 RuntimeDemo[10997:466991] method---->thisTestMethod2017-02-06 18:34:39.926 RuntimeDemo[10997:466991] method---->outPrOne2017-02-06 18:34:39.926 RuntimeDemo[10997:466991] method---->setOutPrOne:2017-02-06 18:34:39.927 RuntimeDemo[10997:466991] method---->innerPrOne2017-02-06 18:34:39.927 RuntimeDemo[10997:466991] method---->setInnerPrOne:2017-02-06 18:34:39.928 RuntimeDemo[10997:466991] method---->.cxx_destruct2017-02-06 18:34:39.928 RuntimeDemo[10997:466991] method---->setDelegate:2017-02-06 18:34:39.929 RuntimeDemo[10997:466991] method---->delegate2017-02-06 18:34:39.929 RuntimeDemo[10997:466991] method---->init2017-02-06 18:34:39.930 RuntimeDemo[10997:466991] Ivar---->instanceOne2017-02-06 18:34:39.931 RuntimeDemo[10997:466991] Ivar---->testTwo2017-02-06 18:34:39.931 RuntimeDemo[10997:466991] Ivar---->_delegate2017-02-06 18:34:39.932 RuntimeDemo[10997:466991] Ivar---->_outPrOne2017-02-06 18:34:39.932 RuntimeDemo[10997:466991] Ivar---->_innerPrOne2017-02-06 18:34:39.933 RuntimeDemo[10997:466991] 121112017-02-06 18:34:39.933 RuntimeDemo[10997:466991] protocol---->TestDelegateTwo由此可知此類所有屬性與方法,以及該類所遵守的協議在下一篇文章我們將介紹如何運用Runtime進行方法攔截
新聞熱點
疑難解答