PerformSelector可能会导致泄漏,因为其选择器在Singleton类/函数指针中未知(作为参数)


@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

//PerformSelector可能会导致泄漏,因为其选择器在上线中未知警告 }

正计划在以下执行以下行以从任何类中形成代码。它没有被称为。

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

现代方法是让您的班级接受完成块而不是目标/选择器。然后,您不必插入一堆丑陋的编译器线条,并且会获得更大的灵活性。

这是[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

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

这是一个警告,而不是错误。您的代码仍应工作。

当您调用选择器并且编译器无法判断选择器是什么时,它无法分辨出该方法是否将对传递的对象拥有,或释放它或其他任何方式。因此,ARC无法确定参数的内存管理是否正确处理。

您应该能够将performSelector呼叫包含在编译器指令中,以禁用该警告。然后,负担将承担您的负担,以确保所谓的方法不会保留对对象传递给对象或释放对象的任何有力的引用。

您不需要在大功能中传递成功方法。相反,您应该使用一个完成块,如[Wil Shipley] [1]

的建议

这是Nsurlconnection提出异步请求和返回的示例;响应,数据和错误;如果发生。将来您应该参考文档。

nsurlconnection类参考https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/nsurlconnection_class/index.html

+ (void)sendAsynchronousRequest:(NSURLRequest *)request
                      queue:(NSOperationQueue *)queue
          completionHandler:(void (^)(NSURLResponse *response,
                                      NSData *data,
                                      NSError *connectionError))handler

您可以像这样重写您的大函数方法 -

- (void)bigFunctionWithYourInputData:(NSDictionary*)userInfo withCompletionHandler:(void(^)(NSData* data, NSError* error))completionHandler {
    NSURL *theUrl = [NSURL URLWithString:[userInfo objectForKey:@"url"];
    NSURLRequest *req = [NSURLRequest requestWithURL:theUrl];
   [NSURLConnection sendAsynchronousRequest:req queue:nil completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if (!connectionError) {
            //do what you want with your data
            NSLog(@"response :%@", response);
            NSLog(@"data     :%@", data);
            //pass to your completion handler
            if(completionHandler) {
                completionHandler(data, nil);
            }
        } else {
            //something went wrong
            NSLog(@"Got the error with code :%ld", (long)connectionError.code);
            //pass to your completion handler
            if(completionHandler) {
                completionHandler(nil, error);
            }
        }
    }];
}

然后,您可以通过单身人士像这样在其他地方实现它 -

[URLClass sharedInstance] bigFunctionWithYourInputData:_someDictionaryData withCompletionHandler:^(NSData* data, NSError* error) {
     if (!error) {
         //success
         NSLog(@"returned the data:%@", data);
     } else {
         //handler the error somehow
     }
 }];  

最新更新