performSelector可能导致泄漏,因为其选择器未知IN Singleton Class/FUNCTION Pointer -Passing Function作为参数

Mus*_*afa 10 delegates objective-c ios

@interface URLClass : NSObject
{
    id target;
    SEL funObj;
}
+ (URLClass *)sharedInstance;
-(void)theBigFunction:(SEL)func :(id)target;
@property (nonatomic,retain) SEL funObj;

#import "URLClass.h"

static URLClass *instance = NULL;


@implementation URLClass
{
    NSMutableData *webData;
}
- (id)init
{
    if ( self = [super init] )
    {

    }
    return self;    
}

+ (URLClass *)sharedInstance
{
    @synchronized([URLClass class])
    {
        if (!instance)
            instance = [[super alloc] init];        
        return instance;
    }    
    return nil;
}
-(void)theBigFunction:(SEL)func :(id)targetObj{

    funObj =func;
    target=targetObj;  
    NSURL *URL = [NSURL URLWithString:@"urlString"];    
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];

    if( connection )
    {
        webData = [NSMutableData data] ;
    }
    else
    {
        NSLog(@"theConnection is NULL");
    }
}



-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{

    return YES;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{    
    NSLog(@"ERROR with theConenction");
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{    

    NSError *error;
    id jsonObj = [NSJSONSerialization JSONObjectWithData:webData options:0 error:&error];    
    if (jsonObj!=nil && error==nil) {        
        if ([jsonObj isKindOfClass:[NSDictionary class]]) {            
            NSDictionary *dic=(NSDictionary*)jsonObj;
            NSLog(@"DIC jsonObj %@ ",dic);
            NSArray *array=[dic objectForKey:@"items"];
            NSLog(@"array jsonObj %@  %d",array,[array count]);
        }else if ([jsonObj isKindOfClass:[NSArray class]]) {

            NSArray *arr=(NSArray*)jsonObj;
            NSLog(@"arr jsonObj %@ ",arr);
        }
    }
    [target performSelector:funObj];
// Not gEtting called the aboue line
Run Code Online (Sandbox Code Playgroud)

// performSelector可能会导致泄漏,因为它的选择器是上面行中的未知警告}

当我计划执行下面的行形式来自任何类的代码.它不被称为.

-(void)loginPress:(id)sender{
    URLClass *rlOBJ=[URLClass sharedInstance];   
    [rlOBJ theBigFunction:@selector(upd_Handler:) :self];
}
- (void) upd_Handler: (id) value{

    NSLog( @"Seccess");    
}
Run Code Online (Sandbox Code Playgroud)

Wil*_*ley 15

现代方法是让您的类接受完成块而不是目标/选择器.然后你不必插入一堆丑陋的编译器抑制行,你就会获得更大的灵活性.

  • 你可以举个例子,在完成NSURL Delegate函数之后我想返回json data/webData. (4认同)

小智 9

以下是完全替代[target performSelector:selector withObject:object];以避免警告.使用这样的替换之一:

[NSObject target:target performSelector:selector withObject:object];

@interface NSObject (NSPerformSelector)

+ (id)target:(id)target performSelector:(SEL)selector;
+ (id)target:(id)target performSelector:(SEL)selector withObject:(id)object;
+ (id)target:(id)target performSelector:(SEL)selector withObject:(id)object1 withObject2:(id)object2;

@end

@implementation NSObject (NSPerformSelector)

+ (id)target:(id)target performSelector:(SEL)selector {

    IMP imp = [target methodForSelector:selector];
    id (*func)(id, SEL) = (void *)imp;
    return func(target, selector);
}

+ (id)target:(id)target performSelector:(SEL)selector withObject:(id)object {

    IMP imp = [target methodForSelector:selector];
    id (*func)(id, SEL, id) = (void *)imp;
    return func(target, selector, object);
}

+ (id)target:(id)target performSelector:(SEL)selector withObject:(id)object1 withObject2:(id)object2 {

    IMP imp = [target methodForSelector:selector];
    id (*func)(id, SEL, id, id) = (void *)imp;
    return func(target, selector, object1, object2);
}

@end
Run Code Online (Sandbox Code Playgroud)


Ash*_*rma 8

只需使用[sender performSelector:selector withObject:object afterDelay:0]; 这将删除警告,代码将运行正常.


Dun*_*n C 2

这是警告,而不是错误。您的代码应该仍然有效。

当您调用选择器并且编译器无法判断选择器是什么时,它无法判断被调用的方法是否将获取传递的对象的所有权,或者释放它,或者其他什么。因此 ARC 无法确保参数的内存管理得到正确处理。

您应该能够将 PerformSelector 调用包含在编译器指令中以禁用该警告。然后,您将有责任确保被调用的方法不会保留对传递给它的对象的任何强引用,或者释放该对象。