void rb_define_object_special_methods(VALUE klass) { RCLASS_SET_VERSION(*(VALUE *)klass, (RCLASS_VERSION(*(VALUE *)klass) | RCLASS_HAS_ROBJECT_ALLOC)); rb_objc_define_method(*(VALUE *)klass, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(klass, "dup", rb_obj_dup, 0); rb_objc_define_private_method(klass, "initialize", rb_objc_init, -1); rb_objc_define_private_method(klass, "initialize_copy", rb_obj_init_copy, 1); rb_objc_define_method(klass, "hash", rb_obj_id, 0); // To make sure singleton classes will be filtered. rb_objc_define_method(*(VALUE *)klass, "superclass", rb_obj_superclass, 0); rb_objc_define_method(klass, "class", rb_obj_class, 0); rb_objc_install_method(*(Class *)klass, selAllocWithZone, (IMP)rb_obj_imp_allocWithZone); rb_objc_install_method((Class)klass, selIsEqual, (IMP)rb_obj_imp_isEqual); rb_objc_install_method((Class)klass, selInit, (IMP)rb_obj_imp_init); rb_objc_install_method((Class)klass, selDescription, (IMP)rb_obj_imp_description); // Create -copyWithZone:, since the method doesn't exist yet we need to // find the type encoding somewhere, here we check Symbol since it's // created very early. Method m = class_getInstanceMethod((Class)rb_cSymbol, selCopyWithZone); assert(m != NULL); class_replaceMethod((Class)klass, selCopyWithZone, (IMP)rb_obj_imp_copyWithZone, method_getTypeEncoding(m)); }
void SwizzInstanceMethod(Class origClass, Class replaceClass, SEL origSel, SEL replaceSel) { Method origMethod = class_getInstanceMethod(origClass, origSel); Method newMethod = class_getInstanceMethod(replaceClass, replaceSel); if(class_addMethod(origClass, origSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) class_replaceMethod(origClass, replaceSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); else method_exchangeImplementations(origMethod, newMethod); }
static bool reinstall_method_maybe(Class klass, SEL sel, const char *types) { Method m = class_getInstanceMethod(klass, sel); if (m == NULL) { return false; } rb_vm_method_node_t *node = GET_CORE()->method_node_get(m); if (node == NULL) { // We only do that for pure Ruby methods. return false; } GET_CORE()->retype_method(klass, node, method_getTypeEncoding(m), types); return true; }
bool OBJC_EXCHANGE_NEWCLASS_METHOD_TEMPLATE(const char* orgClassStr,const char* orgSelector, const char* newClassStr,const char* newSelector) { Class orgClass = objc_getClass(orgClassStr); Class newClass = objc_getClass(newClassStr); if(!orgClass || !newClass) { return false; } SEL orgMethod = sel_registerName(orgSelector); SEL newMethod = sel_registerName(newSelector); Method newMethodIns = class_getInstanceMethod(newClass, newMethod); /*在旧的类添加类新方法后,那么只需要交换原有的方法即可*/ Method orgMethodIns = class_getInstanceMethod(orgClass, orgMethod); /*防止方法不存在*/ if(!orgMethodIns || !newMethodIns) { return false; } IMP newMethodIMP = method_getImplementation(newMethodIns); const char *newMethodStr = method_getTypeEncoding(newMethodIns); class_addMethod(orgClass, newMethod, newMethodIMP, newMethodStr); newMethodIns = class_getInstanceMethod(orgClass, newMethod); method_exchangeImplementations(orgMethodIns, newMethodIns); return true; }