10
votes
@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 may cause a leak because its selector is unknown warning in above line }

When am planing to execute below lines form code from any class . its not get called.

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

    NSLog( @"Seccess");    
}
5
Have you tried debugging it with break points? Put some NSLog at the start of function and log memory of object to see whether they are actually called/rishi
- (void) upd_Handler: (id) value Function not called back , I debugged , [target performSelector:funObj]; not geeting excecuted.Musthafa
theBigFunction is called?rishi
yes its called.am got JSon Data also.After getting Json Data im want to call - (void) upd_Handler: (id) value function backMusthafa

5 Answers

15
votes

The modern approach would be for your class to accept a completion block instead of a target / selector. Then you don’t have to insert a bunch of ugly compiler-inhibiting lines, and you get more flexibility.

9
votes

Here are complete replacements of [target performSelector:selector withObject:object]; to avoid the warning. Use either of the replacements like this:

[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
8
votes

Simply use [sender performSelector:selector withObject:object afterDelay:0]; This will remove the warning and the code will run fine.

2
votes

That is a warning, not an error. Your code should still work.

When you invoke a selector and the compiler can't tell what the selector is, it can't tell if the called method is going to take ownership of the passed object or not, or release it, or whatever. Thus ARC can't be sure that memory management of the parameter will be handled correctly.

You should be able to enclosed the performSelector call in a compiler directive to disable that warning. Then the burden will be on you to make sure the called method does not keep any strong references to the object passed to it, or release the object.

2
votes

You don't need to pass your success method in your bigFunction. Instead you should be using a completion block, as suggested by [Wil Shipley][1]

Here is an example of a NSURLConnection making a Asynchronous request and returning; a response, data and an error; if one occurs. In the future you should refer to the documentation.

NSURLConnection Class Reference 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

You could re-write your bigFunction method like this --

- (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);
            }
        }
    }];
}

Then you would implement it somewhere else, via your singleton like so --

[URLClass sharedInstance] bigFunctionWithYourInputData:_someDictionaryData withCompletionHandler:^(NSData* data, NSError* error) {

     if (!error) {
         //success
         NSLog(@"returned the data:%@", data);

     } else {

         //handler the error somehow
     }
 }];