使我的代码符合ARC模型

时间:2018-08-21 20:13:36

标签: objective-c xcode

我正在使用一个旧的应用程序,并将其内存处理转换为ARC(自动引用计数),并且在我的一个类中,我收到以下警告: PerformSelector可能会导致泄漏,因为其选择器未知。正如 wbyoung 所解释的那样,我研究了这个问题并发现了出色的find。为了减轻警告,我将原始代码从以下位置更改:

- (void)launchExecution {
    @autoreleasepool {
    // Start executing the requested task
        [targetForExecution performSelector:methodForExecution withObject:objectForExecution]; //--WARNING happens here...

        // Task completed, update view in main thread (note: view operations should
        // be done only in the main thread)
        [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];      
    }
}

我将其修改为:

- (void)launchExecution {
    @autoreleasepool {
        if(!targetForExecution) return;
        SEL selector = methodForExecution;
        IMP imp = [targetForExecution methodForSelector:selector];
        void (*func)(id, SEL) = (void *)imp;
        func(targetForExecution, selector);

        // Task completed, update view in main thread (note: view operations should
        // be done only in the main thread)
        [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];

    }
}

现在我的问题是这样的:虽然它没有给我任何错误(是的!),但我仍然必须将 ObjectForExecution 值传递到此新配置中。怎么做?我知道有一些变通方法,人们已使用编译指示来忽略此类警告,但我想适当地解决此警告。

2 个答案:

答案 0 :(得分:2)

我只会直接使用objc_msgSend,就像这样:

// At top of file:
#import <objc/message.h>

// To send the message:
((void (*)(id, SEL, id))objc_msgSend)(targetForExecution, methodForExecution, objectForExecution);

请注意,该方法实际返回void很重要。如果返回一个对象,则该对象可能会泄漏。如果返回struct,则此代码将崩溃。但是,如果该方法返回void,则不会泄漏任何内容,并且调用不会崩溃。

答案 1 :(得分:2)

您应将targetForExecutionmethodForExecutionobjectForExecution替换为block并使用GCD:

- (void)launchExecution {
    blockForExecution();
    dispatch_async(dispatch_get_main_queue(), ^{
     [self cleanUp];    
    });
}