The correct way to swizzling in objective-C

We are currently experimenting with a method swizzlingin Objective-C, and I have a question. I am trying to figure out the correct way of the swizzle method and after learning online I came across this NSHipster entry: http://nshipster.com/method-swizzling/

In the post, the author has some swizzling sample code method. I am looking for someone to better explain to me what the author is doing. In particular, I got confused in logic didAddMethod. Why is the author not just directly implementing the methods swapping/exchanging? My only theory in this is, perhaps, there is some probability that it is viewWillAppear:not added to UIViewController method dispatch_table. In particular, if, perhaps, a category is loaded into memory earlier than UIViewController... Is this the reason? Seems pretty weird? Just look for even more insight / clarity, thanks :)

+4
source share
2 answers

, didAddMethod. / ?

, .

, UIViewController , - , TargetClass.

, existingMethod.

, TargetClass, swizzling, swizzlingMethod, TargetClass.

. , class_getInstanceMethod . class_addMethod class_replaceMethod / .

:

  • TargetClass existingMethod. , , , - existingMethod swizzlingMethod, method_exchangeImplementations. class_addMethod , existingMethod TargetClass, method_exchangeImplementations.

  • TargetClass , existingMethod, TargetClass. . existingMethod swizzlingMethod, () ( , - ). class_addMethod, , existingMethod in TargetClass, swizzlingMethod. swizzlingMethod existingMethod ( ).

? , !

, : , , ancestor existingMethod super... swizzlingMethod TargetClass super? , , , -, ?

+6

load , a class obj-c.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/#//apple_ref/occ/clm/NSObject/load

, , a UIViewController obj-c, viewWillAppear:, , . xxxWillAppear:. , xxxWillAppear: ViewController, .

:

, , , iOS

, , ViewController viewWillAppear:. , viewWillAppear: , .

, Objective C :

/**********************************************************************
* addMethod
* fixme
* Locking: runtimeLock must be held by the caller
**********************************************************************/
static IMP 
addMethod(Class cls, SEL name, IMP imp, const char *types, BOOL replace)
{
IMP result = nil;

rwlock_assert_writing(&runtimeLock);

assert(types);
assert(cls->isRealized());

method_t *m;
if ((m = getMethodNoSuper_nolock(cls, name))) {
    // already exists
    if (!replace) {
        result = _method_getImplementation(m);
    } else {
        result = _method_setImplementation(cls, m, imp);
    }
} else {
    // fixme optimize
    method_list_t *newlist;
    newlist = (method_list_t *)_calloc_internal(sizeof(*newlist), 1);
    newlist->entsize_NEVER_USE = (uint32_t)sizeof(method_t) | fixed_up_method_list;
    newlist->count = 1;
    newlist->first.name = name;
    newlist->first.types = strdup(types);
    if (!ignoreSelector(name)) {
        newlist->first.imp = imp;
    } else {
        newlist->first.imp = (IMP)&_objc_ignored_method;
    }

    attachMethodLists(cls, &newlist, 1, NO, NO, YES);

    result = nil;
}

return result;
}


BOOL 
class_addMethod(Class cls, SEL name, IMP imp, const char *types)
{
if (!cls) return NO;

rwlock_write(&runtimeLock);
IMP old = addMethod(cls, name, imp, types ?: "", NO);
rwlock_unlock_write(&runtimeLock);
return old ? NO : YES;
}


IMP 
class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
{
if (!cls) return nil;

rwlock_write(&runtimeLock);
IMP old = addMethod(cls, name, imp, types ?: "", YES);
rwlock_unlock_write(&runtimeLock);
return old;
}

, :

http://www.opensource.apple.com/source/objc4/objc4-437/

0

Source: https://habr.com/ru/post/1622027/


All Articles