Using Super in an Objective C Category?

后端 未结 3 1381
名媛妹妹
名媛妹妹 2020-12-05 02:44

I\'d like to override a method in an Objective C class that I don\'t have the source to.

I\'ve looked into it, and it appears that Categories should allow me to do t

相关标签:
3条回答
  • 2020-12-05 03:23

    If you will be coding against this class, simply rename the selector to something your code can use, and call the original selector on self:

    @implementation SampleClass (filePathResolver)
    -(NSString*) myFullPathFromRelativePath:(NSString*) relPath
    {
        NSString *result = [self fullPathFromRelativePath: relPath];
    
      ... do some stuff with the old result
    
        return result;
    }
    

    If you want to override the default implementation of this selector for that class, you'll need to use the method swizzling approach.

    0 讨论(0)
  • 2020-12-05 03:42

    Categories extend the original class, but they don't subclass it, therefore a call to super doesn't find the method.

    What you want is called Method Swizzling. But be aware that your code could break something. There's an article on Theocacao written by Scot Stevenson about Method Swizzling in the old Objective-C runtime, Cocoa with Love by Matt Gallagher has an article about Method Swizzling in the new Objective-C 2.0 runtime and a simple replacement for it.

    Alternatively, you could subclass the class and then either use the subclass or use + (void)poseAsClass:(Class)aClass to replace the superclass. Apple writes:

    A method defined by a posing class can, through a message to super, incorporate the superclass method it overrides.

    Be aware that Apple has deprecated poseAsClass: in Mac OS X 10.5.

    0 讨论(0)
  • 2020-12-05 03:42

    Not exactly in category but there is a workaround by adding the method dynamically at runtime. Samuel Défago in his article describes a neat way to create block IMP implementation calling super, his original article can be found here

    The relevant code is:

    #import <objc/runtime.h>
    #import <objc/message.h>
    
        const char *types = method_getTypeEncoding(class_getInstanceMethod(clazz, selector));
        class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) {
            struct objc_super super = {
                .receiver = self,
                .super_class = class_getSuperclass(clazz)
            };
    
            id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
            return objc_msgSendSuper_typed(&super, selector, argp);
        }), types);
    
    0 讨论(0)
提交回复
热议问题