performSelector may cause a leak because its selector is unknown

后端 未结 19 2454
小蘑菇
小蘑菇 2020-11-22 01:54

I\'m getting the following warning by the ARC compiler:

\"performSelector may cause a leak because its selector is unknown\".

Here\'s what

19条回答
  •  离开以前
    2020-11-22 02:45

    Well, lots of answers here, but since this is a little different, combining a few answers I thought I'd put it in. I'm using an NSObject category which checks to make sure the selector returns void, and also suppresses the compiler warning.

    #import 
    #import 
    #import "Debug.h" // not given; just an assert
    
    @interface NSObject (Extras)
    
    // Enforce the rule that the selector used must return void.
    - (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object;
    - (void) performVoidReturnSelector:(SEL)aSelector;
    
    @end
    
    @implementation NSObject (Extras)
    
    // Apparently the reason the regular performSelect gives a compile time warning is that the system doesn't know the return type. I'm going to (a) make sure that the return type is void, and (b) disable this warning
    // See http://stackoverflow.com/questions/7017281/performselector-may-cause-a-leak-because-its-selector-is-unknown
    
    - (void) checkSelector:(SEL)aSelector {
        // See http://stackoverflow.com/questions/14602854/objective-c-is-there-a-way-to-check-a-selector-return-value
        Method m = class_getInstanceMethod([self class], aSelector);
        char type[128];
        method_getReturnType(m, type, sizeof(type));
    
        NSString *message = [[NSString alloc] initWithFormat:@"NSObject+Extras.performVoidReturnSelector: %@.%@ selector (type: %s)", [self class], NSStringFromSelector(aSelector), type];
        NSLog(@"%@", message);
    
        if (type[0] != 'v') {
            message = [[NSString alloc] initWithFormat:@"%@ was not void", message];
            [Debug assertTrue:FALSE withMessage:message];
        }
    }
    
    - (void) performVoidReturnSelector:(SEL)aSelector withObject:(id)object {
        [self checkSelector:aSelector];
    
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        // Since the selector (aSelector) is returning void, it doesn't make sense to try to obtain the return result of performSelector. In fact, if we do, it crashes the app.
        [self performSelector: aSelector withObject: object];
    #pragma clang diagnostic pop    
    }
    
    - (void) performVoidReturnSelector:(SEL)aSelector {
        [self checkSelector:aSelector];
    
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self performSelector: aSelector];
    #pragma clang diagnostic pop
    }
    
    @end
    

提交回复
热议问题