performSelector ARC warning [duplicate]

2019-01-13 22:55发布

问题:

Possible Duplicate:
performSelector may cause a leak because its selector is unknown

I have this code in non-ARC that works without errors or warnings:

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
{
    // Only care about value changed controlEvent
    _target = target;
    _action = action;
}

- (void)setValue:(float)value
{
    if (value > _maximumValue)
    {
        value = _maximumValue;
    } else if (value < _minimumValue){
        value = _minimumValue;
    }

    // Check range
    if (value <= _maximumValue & value >= _minimumValue)
    {
        _value = value;
        // Rotate knob to proper angle
        rotation = [self calculateAngleForValue:_value];
        // Rotate image
        thumbImageView.transform = CGAffineTransformMakeRotation(rotation);
    }
    if (continuous)
    {
        [_target performSelector:_action withObject:self]; //warning here
    }
}

However, after I convert to project to ARC, I get this warning:

"Perform Selector may cause a leak because its selector is unknown."

I would appreciate ideas on how to revise my code accordingly..

回答1:

The only way I've found to avoid the warning is to suppress it. You could disable it in your build settings, but I prefer to just use pragmas to disable it where I know it's spurious.

#       pragma clang diagnostic push
#       pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [_target performSelector:_action withObject:self];
#       pragma clang diagnostic pop

If you're getting the error in several places, you can define a macro to make it easier to suppress the warning:

#define SuppressPerformSelectorLeakWarning(Stuff) \
    do { \
        _Pragma("clang diagnostic push") \
        _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
        Stuff; \
        _Pragma("clang diagnostic pop") \
    } while (0)

You can use the macro like this:

SuppressPerformSelectorLeakWarning([_target performSelector:_action withObject:self]);