int cfunction(id self, SEL _cmd, NSString *str) {
NSLog(@"%@", str);
return10;//随便返回个值
}
- (void) oneParam {
TestClass *instance = [[TestClassalloc]init];
// 方法添加
class_addMethod([TestClassclass],@selector(ocMethod:), (IMP)cfunction,"i@:@");
if ([instance respondsToSelector:@selector(ocMethod:)]) {
NSLog(@"Yes, instance respondsToSelector:@selector(ocMethod:)");
} else
{
NSLog(@"Sorry");
}
int a = (int)[instanceocMethod:@"我是一个OC的method,C函数实现"];
NSLog(@"a:%d", a);
}
int cfunctionA(id self, SEL _cmd, NSString *str, NSString *str1) {
NSLog(@"%@-%@", str, str1);
return20;//随便返回个值
}
- (void) twoParam {
TestClass *instance = [[TestClassalloc]init];
class_addMethod([TestClassclass],@selector(ocMethodA::), (IMP)cfunctionA,"i@:@@");
if ([instance respondsToSelector:@selector(ocMethodA::)]) {
NSLog(@"Yes, instance respondsToSelector:@selector(ocMethodA::)");
} else
{
NSLog(@"Sorry");
}
int a = (int)[instanceocMethodA:@"我是一个OC的method,C函数实现" :@"-----我是第二个参数"];
NSLog(@"a:%d", a);
}
相关文档及说明:
Obj-C的方法(method)就是一个至少需要两个参数(self,_cmd)的C函数
IMP有点类似函数指针,指向具体的Method实现。
向一个类动态添加方法
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
参数说明:
cls:被添加方法的类
name:可以理解为方法名
imp:实现这个方法的函数
types:一个定义该函数返回值类型和参数类型的字符串
class_addMethod([TestClass class], @selector(ocMethod:), (IMP)testFunc, "i@:@");
其中types参数为"i@:@“,按顺序分别表示:
i:返回值类型int,若是v则表示void
@:参数id(self)
::SEL(_cmd)
@:id(str)
官方文档:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
-----------------------------------------------------------------------------------------------------------------
IOS高级开发~Runtime(一)
IOS高级开发~Runtime(二)
IOS高级开发~Runtime(三)
IOS高级开发~Runtime(四)
一些公用类:
@interface ClassCustomClass :NSObject{
NSString *varTest1;
NSString *varTest2;
NSString *varTest3;
}
@PRoperty (nonatomic,assign)NSString *varTest1;
@property (nonatomic,assign)NSString *varTest2;
@property (nonatomic,assign)NSString *varTest3;
- (void) fun1;
@end
@implementation ClassCustomClass
@synthesize varTest1, varTest2, varTest3;
- (void) fun1 {
NSLog(@"fun1");
}
@end
@interface ClassCustomClassOther :NSObject {
int varTest2;
}
- (void) fun2;
@end
@implementation ClassCustomClassOther
- (void) fun2 {
NSLog(@"fun2");
}
@end
@interface ClassPropertyViewCtr () {
float myFloat;
ClassCustomClass *allobj;
}
myFloat = 2.34f;
6、获取一个类的所有方法:
- (void) getClassAllMethod
{
u_int count;
Method* methods= class_copyMethodList([UIViewController class], &count);
for (int i = 0; i < count ; i++)
{
SEL name = method_getName(methods[i]);
NSString *strName = [NSString stringWithCString:sel_getName(name)encoding:NSUTF8StringEncoding];
NSLog(@"%@",strName);
}
}
打印结果(部分):
2013-07-26 16:07:03.972 HighOC[7021:c07] _screen
2013-07-26 16:07:03.973 HighOC[7021:c07] applicationWillSuspend
2013-07-26 16:07:03.973 HighOC[7021:c07] _tryBecomeRootViewControllerInWindow:
2013-07-26 16:07:03.973 HighOC[7021:c07] isViewLoaded
2013-07-26 16:07:03.974 HighOC[7021:c07] view
......................
7、获取一个类的所有属性:
- (void) propertyNameList
{
u_int count;
objc_property_t *properties=class_copyPropertyList([UIViewControllerclass], &count);
for (int i = 0; i < count ; i++)
{
const char* propertyName =property_getName(properties[i]);
NSString *strName = [NSString stringWithCString:propertyNameencoding:NSUTF8StringEncoding];
NSLog(@"%@",strName);
}
}
打印结果(部分)
2013-07-26 16:09:42.182 HighOC[7041:c07] tabBarItem
2013-07-26 16:09:42.184 HighOC[7041:c07] tabBarController
2013-07-26 16:09:42.185 HighOC[7041:c07] splitViewController
2013-07-26 16:09:42.186 HighOC[7041:c07] navigationItem
2013-07-26 16:09:42.186 HighOC[7041:c07] hidesBottomBarWhenPushed
...............
8、获取/设置类的属性变量
//获取全局变量的值 (myFloat 为类的一个属性变量)
- (void) getInstanceVar {
float myFloatValue;
object_getInstanceVariable(self,"myFloat", (void*)&myFloatValue);
NSLog(@"%f", myFloatValue);
}
//设置全局变量的值
- (void) setInstanceVar {
float newValue = 10.00f;
unsigned int addr = (unsignedint)&newValue;
object_setInstanceVariable(self,"myFloat", *(float**)addr);
NSLog(@"%f", myFloat);
}
9、判断类的某个属性的类型
- (void) getVarType {
ClassCustomClass *obj = [ClassCustomClassnew];
Ivar var = class_getInstanceVariable(object_getClass(obj),"varTest1");
const char* typeEncoding =ivar_getTypeEncoding(var);
NSString *stringType = [NSStringstringWithCString:typeEncodingencoding:NSUTF8StringEncoding];
if ([stringType hasprefix:@"@"]) {
// handle class case
NSLog(@"handle class case");
} else if ([stringTypehasPrefix:@"i"]) {
// handle int case
NSLog(@"handle int case");
} else if ([stringTypehasPrefix:@"f"]) {
// handle float case
NSLog(@"handle float case");
} else
{
}
}
10、通过属性的值来获取其属性的名字(反射机制)
- (NSString *)nameOfInstance:(id)instance
{
unsigned int numIvars =0;
NSString *key=nil;
//Describes the instance variables declared by a class.
Ivar * ivars = class_copyIvarList([ClassCustomClassclass], &numIvars);
for(int i = 0; i < numIvars; i++) {
Ivar thisIvar = ivars[i];
const char *type =ivar_getTypeEncoding(thisIvar);
NSString *stringType = [NSStringstringWithCString:typeencoding:NSUTF8StringEncoding];
//不是class就跳过
if (![stringType hasPrefix:@"@"]) {
continue;
}
//Reads the value of an instance variable in an object. object_getIvar这个方法中,当遇到非objective-c对象时,并直接crash
if ((object_getIvar(allobj, thisIvar) == instance)) {
// Returns the name of an instance variable.
key = [NSStringstringWithUTF8String:ivar_getName(thisIvar)];
break;
}
}
free(ivars);
return key;
}
测试代码:
allobj = [ClassCustomClassnew];
allobj.varTest1 =@"varTest1String";
allobj.varTest2 =@"varTest2String";
allobj.varTest3 =@"varTest3String";
NSString *str = [selfnameOfInstance:@"varTest1String"];
NSLog(@"str:%@", str);
打印结果:
2013-07-26 16:26:26.271 HighOC[7081:c07] str:varTest1
------------------------------------------------------------------------------------------------------IOS高级开发~Runtime(一)
IOS高级开发~Runtime(二)
IOS高级开发~Runtime(三)
IOS高级开发~Runtime(四)
11、系统类的方法实现部分替换
- (void) methodExchange {
Method m1 = class_getInstanceMethod([NSStringclass],@selector(lowercaseString));
Method m2 = class_getInstanceMethod([NSStringclass],@selector(uppercaseString));
method_exchangeImplementations(m1, m2);
NSLog(@"%@", [@"sssAAAAss"lowercaseString]);
NSLog(@"%@", [@"sssAAAAss"uppercaseString]);
}
打印结果:(仔细看log)
2013-07-26 16:33:22.776 HighOC[7104:c07] SSSAAAASS
2013-07-26 16:33:22.778 HighOC[7104:c07] sssaaaass
12、自定义类的方法实现部分替换
- (void) justLog1 {
NSLog(@"justLog1");
}
- (void) justLog2 {
NSLog(@"justLog2");
}
- (void) methodSetImplementation {
Method method = class_getInstanceMethod([ClassMethodViewCtrclass],@selector(justLog1));
IMP originalImp = method_getImplementation(method);
Method m1 = class_getInstanceMethod([ClassMethodViewCtrclass],@selector(justLog2));
method_setImplementation(m1, originalImp);
}
//[self methodSetImplementation];
//[self justLog2];
13、覆盖系统方法
IMP cFuncPointer;
IMP cFuncPointer1;
IMP cFuncPointer2;
NSString* CustomUppercaseString(idself,SEL_cmd){
printf("真正起作用的是本函数CustomUppercaseString/r/n");
NSString *string = cFuncPointer(self,_cmd);
return string;
}
NSArray* CustomComponentsSeparatedByString(idself,SEL_cmd,NSString *str){
printf("真正起作用的是本函数CustomIsEqualToString/r/n");
return cFuncPointer1(self,_cmd, str);
}
//不起作用,求解释
bool CustomIsEqualToString(idself,SEL_cmd,NSString *str) {
printf("真正起作用的是本函数CustomIsEqualToString/r/n");
return cFuncPointer2(self,_cmd, str);
}
- (void) replaceMethod{
cFuncPointer = [NSStringinstanceMethodForSelector:@selector(uppercaseString)];
class_replaceMethod([NSStringclass],@selector(uppercaseString), (IMP)CustomUppercaseString,"@@:");
cFuncPointer1 = [NSStringinstanceMethodForSelector:@selector(componentsSeparatedByString:)];
class_replaceMethod([NSStringclass],@selector(componentsSeparatedByString:), (IMP)CustomComponentsSeparatedByString,"@@:@");
cFuncPointer2 = [NSStringinstanceMethodForSelector:@selector(isEqualToString:)];
class_replaceMethod([NSStringclass],@selector(isEqualToString:), (IMP)CustomIsEqualToString,"B@:@");
}
14、自动序列化(转)
#import "NSObject+AutoEncodeDecode.h"
@implementation NSObject (AutoEncodeDecode)
- (void)encodeWithCoder:(NSCoder *)encoder {
Class cls = [selfclass];
while (cls != [NSObjectclass]) {
unsigned int numberOfIvars =0;
Ivar* ivars = class_copyIvarList(cls, &numberOfIvars);
for(const Ivar* p = ivars; p < ivars+numberOfIvars; p++){
Ivar const ivar = *p;
const char *type =ivar_getTypeEncoding(ivar);
NSString *key = [NSStringstringWithUTF8String:ivar_getName(ivar)];
id value = [selfvalueForKey:key];
if (value) {
switch (type[0]) {
case _C_STRUCT_B: {
NSUInteger ivarSize =0;
NSUInteger ivarAlignment =0;
NSGetSizeAndAlignment(type, &ivarSize, &ivarAlignment);
NSData *data = [NSDatadataWithBytes:(constchar *)self + ivar_getOffset(ivar)
length:ivarSize];
[encoder encodeObject:dataforKey:key];
}
break;
default:
[encoder encodeObject:value
forKey:key];
break;
}
}
}
free(ivars);
cls = class_getSuperclass(cls);
}
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [self init];
if (self) {
Class cls = [selfclass];
while (cls != [NSObjectclass]) {
unsigned int numberOfIvars =0;
Ivar* ivars = class_copyIvarList(cls, &numberOfIvars);
for(constIvar* p = ivars; p < ivars+numberOfIvars; p++){
Ivar const ivar = *p;
const char *type =ivar_getTypeEncoding(ivar);
NSString *key = [NSStringstringWithUTF8String:ivar_getName(ivar)];
id value = [decoder decodeObjectForKey:key];
if (value) {
switch (type[0]) {
case _C_STRUCT_B: {
NSUInteger ivarSize =0;
NSUInteger ivarAlignment =0;
NSGetSizeAndAlignment(type, &ivarSize, &ivarAlignment);
NSData *data = [decoderdecodeObjectForKey:key];
char *sourceIvarLocation = (char*)self+ivar_getOffset(ivar);
[data getBytes:sourceIvarLocationlength:ivarSize];
}
break;
default:
[self setValue:[decoder decodeObjectForKey:key]
forKey:key];
break;
}
}
}
free(ivars);
cls = class_getSuperclass(cls);
}
}
return self;
}
---------------------------------------------------------------------------------------------------------------------------------
IOS高级开发~Runtime(一)
IOS高级开发~Runtime(二)
IOS高级开发~Runtime(三)
IOS高级开发~Runtime(四)
用C代替OC:
#import
#import
#import
extern int UIApplicationMain (int argc,char *argv[],void *principalClassName,void *delegateClassName);
struct Rect {
float x;
float y;
float width;
float height;
};
typedef struct Rect Rect;
void *navController;
static int numberOfRows =100;
int tableView_numberOfRowsInSection(void *receiver,structobjc_selector *selector, void *tblview,int section) {
returnnumberOfRows;
}
void *tableView_cellForRowAtIndexPath(void *receiver,structobjc_selector *selector, void *tblview,void *indexPath) {
Class TableViewCell = (Class)objc_getClass("UITableViewCell");
void *cell = class_createInstance(TableViewCell,0);
objc_msgSend(cell, sel_registerName("init"));
char buffer[7];
int row = (int) objc_msgSend(indexPath, sel_registerName("row"));
sprintf (buffer, "Row %d", row);
void *label =objc_msgSend(objc_getClass("NSString"),sel_registerName("stringWithUTF8String:"),buffer);
objc_msgSend(cell, sel_registerName("setText:"),label);
return cell;
}
void tableView_didSelectRowAtIndexPath(void *receiver,structobjc_selector *selector, void *tblview,void *indexPath) {
Class ViewController = (Class)objc_getClass("UIViewController");
void * vc = class_createInstance(ViewController,0);
objc_msgSend(vc, sel_registerName("init"));
char buffer[8];
int row = (int) objc_msgSend(indexPath, sel_registerName("row"));
sprintf (buffer, "Item %d", row);
void *label =objc_msgSend(objc_getClass("NSString"),sel_registerName("stringWithUTF8String:"),buffer);
objc_msgSend(vc, sel_registerName("setTitle:"),label);
objc_msgSend(navController,sel_registerName("pushViewController:animated:"),vc,1);
}
void *createDataSource() {
Class superclass = (Class)objc_getClass("NSObject");
Class DataSource = objc_allocateClassPair(superclass,"DataSource",0);
class_addMethod(DataSource,sel_registerName("tableView:numberOfRowsInSection:"), (void(*))tableView_numberOfRowsInSection,nil);
class_addMethod(DataSource,sel_registerName("tableView:cellForRowAtIndexPath:"), (void(*))tableView_cellForRowAtIndexPath,nil);
objc_registerClassPair(DataSource);
returnclass_createInstance(DataSource,0);
}
void * createDelegate() {
Class superclass = (Class)objc_getClass("NSObject");
Class DataSource = objc_allocateClassPair(superclass,"Delegate",0);
class_addMethod(DataSource,sel_registerName("tableView:didSelectRowAtIndexPath:"), (void(*))tableView_didSelectRowAtIndexPath,nil);
objc_registerClassPair(DataSource);
returnclass_createInstance(DataSource,0);
}
void applicationdidFinishLaunching(void *receiver,structobjc_selector *selector, void *application) {
Class windowClass = (Class)objc_getClass("UIWindow");
void * windowInstance = class_createInstance(windowClass, 0);
objc_msgSend(windowInstance, sel_registerName("initWithFrame:"),(Rect){0,0,320,480});
//Make Key and Visiable
objc_msgSend(windowInstance,sel_registerName("makeKeyAndVisible"));
//Create Table View
Class TableViewController = (Class)objc_getClass("UITableViewController");
void *tableViewController = class_createInstance(TableViewController, 0);
objc_msgSend(tableViewController, sel_registerName("init"));
void *tableView = objc_msgSend(tableViewController,sel_registerName("tableView"));
objc_msgSend(tableView, sel_registerName("setDataSource:"),createDataSource());
objc_msgSend(tableView, sel_registerName("setDelegate:"),createDelegate());
Class NavController = (Class)objc_getClass("UINavigationController");
navController = class_createInstance(NavController,0);
objc_msgSend(navController,sel_registerName("initWithRootViewController:"),tableViewController);
void *view =objc_msgSend(navController,sel_registerName("view"));
//Add Table View To Window
objc_msgSend(windowInstance, sel_registerName("addSubview:"),view);
}
//Create an class named "AppDelegate", and return it's name as an instance of class NSString
void *createAppDelegate() {
Class mySubclass = objc_allocateClassPair((Class)objc_getClass("NSObject"),"AppDelegate",0);
structobjc_selector *selName =sel_registerName("application:didFinishLaunchingWithOptions:");
class_addMethod(mySubclass, selName, (void(*))applicationdidFinishLaunching,nil);
objc_registerClassPair(mySubclass);
returnobjc_msgSend(objc_getClass("NSString"),sel_registerName("stringWithUTF8String:"),"AppDelegate");
}
int main(int argc, char *argv[]) {
returnUIApplicationMain(argc, argv,0,createAppDelegate());
}
运行效果: