4

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

rmaddy
  • 314,917
  • 42
  • 532
  • 579
YogevSitton
  • 10,068
  • 11
  • 62
  • 95

1 Answers1

11

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
         }         
      }
    }
}
nhgrif
  • 61,578
  • 25
  • 134
  • 173
Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50
  • Just messing around with the language - testing and trying new things in order to learn. If I swizzle a protocol method in a specific class - I can just change it's implementation in that class. I want to use method swizzling in order to change implementation in all conforming classes at once. – YogevSitton May 05 '15 at 04:48
  • 1
    You can parse the class tree and ask each class, what protocol it implements. You can search for the protocol of subject and change the implementation in the class, if the protocol is implemented. I can add some source code for doing so, if you want. Just reply. – Amin Negm-Awad May 05 '15 at 04:57