Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method Swizzling for protocols

I want to be able to Swizzle protocol methods like textFieldDidBeginEditing: and tableView:didSelectRowAtIndexPath:. How can this be done?

like image 647
YogevSitton Avatar asked Dec 19 '22 04:12

YogevSitton


1 Answers

First of all: You need very good reasons to swizzle methods.

There is no "method swizzing for protocols". Method swizzling means that you exchange the method implementation pointer for a selector. Protocols does not have implementations.

You can swizzle methods declared in a protocol. But you do it in the class that conforms to the protocol, not in the protocol itself.

Here is a sample to find the classes implementing a method:

SEL selector = …;      // The selector for the method you want to swizzle
IMP code = …;          // The implementation you want to set
Protocol *protocol = …; // The protocol containing the method

// Get the class list
int classesCount = objc_getClassList ( NULL, 0 );
Class *classes = malloc( classCount * sizeof(Class));
objc_getClassList( classes, classesCount );

// For every class 
for( int classIndex = 0; classIndex < classesCount; classIndex++ )
{
    Class class = classes[classIndex];

    // Check, whether the class implements the protocol
    // The protocol confirmation can be found in a super class
    Class conformingClass = class;
    while(conformingClass!=Nil)
    {
      if (class_conformsToProtocol( conformingClass, protocol )
      {
        break;
      }
      conformingClass = class_getSuperclass( conformingClass );
    }

    // Check, whether the protocol is found in the class or a superclass
    if (conformingClass != Nil )
    {
      // Check, whether the protocol's method is implemented in the class,
      // but NOT the superclass, because you have to swizzle it there. Otherwise
      // it would be swizzled more than one time.
      unsigned int methodsCount;
      Method *methods = class_copyMethodList( class, &methodsCount );

      for( unsigned methodIndex; methodIndex < methodsCount; methodIndex++ )
      {
         if (selector == method_getName( methods[methodIndex] ))
         {
            // Do the method swizzling
         }         
      }
    }
}
like image 183
Amin Negm-Awad Avatar answered Dec 22 '22 00:12

Amin Negm-Awad