How to call performSelectorInBackground with a function having arguments?

16,187

Solution 1

[self performSelectorInBackground:@selector(callXml:)
                       withObject:@"test"];

ie: what you pass in as withObject: becomes the parameter to your method.

Just as a point of interest here's how you could do it using GCD:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self callXml:@"test"];

    // If you then need to execute something making sure it's on the main thread (updating the UI for example)
    dispatch_async(dispatch_get_main_queue(), ^{
        [self updateGUI];
    });
});

Solution 2

For this

- (void)callXml:(NSString *) name{
     [RXMLElement elementFromURL:[NSURL URLWithString:indXML]];
 } 

You can call like this

  [self performSelectorInBackground:@selector(callXml:)
                               withObject:@"test"];

If your method has parameter then : is used with method_name and pass parameter as withObject argument

Solution 3

Hi try this,

 RXMLElement *rootXML= [self performSelectorInBackground:@selector(callXml:)
                               withObject:@"test"];

- (RXMLElement *)callXml:(NSString *) name{

         NSLog(@"%@",name);//Here passed value will be printed i.e test

     return [RXMLElement elementFromURL:[NSURL URLWithString:indXML]];
 } 

Solution 4

The selector you use needs to be an exact match to the method name - the method name includes the colon (:) characters. So your selector should be:

@selector(callXml:)

If you want to pass a parameter.

If you need to pass more complex data, you have 3 options:

  1. Pass an NSArray or NSDictionary containing the parameters
  2. Pass a custom object which contains all of the required data as attributes
  3. Use GCD (GCD_libdispatch reference)
Share:
16,187
Sasha Grievus
Author by

Sasha Grievus

Updated on July 28, 2022

Comments

  • Sasha Grievus
    Sasha Grievus almost 2 years

    Sorry for the newbie question (maybe). I'm developing an app for ios and i'm trying to execute an external xml reading out of the main thread in order not to freeze the ui while the call is doing its magic.

    This is the only way i know to made a process not to execute in the main thread in objective c

    [self performSelectorInBackground:@selector(callXml)
                               withObject:self];
    

    so i did incapsulate my call into a function

     - (void)callXml{
         [RXMLElement elementFromURL:[NSURL URLWithString:indXML]];
     }
    

    Now i have to make the string indXML be a parameter of the function in order to call different xml as i need to. Something like

     - (void)callXml:(NSString *) name{
         [RXMLElement elementFromURL:[NSURL URLWithString:indXML]];
     }
    

    In this case, how the call to performSelector change? If i do it in the usual way i get syntax errors:

    [self performSelectorInBackground:@selector(callXml:@"test")
                               withObject:self];
    
  • Mike Pollard
    Mike Pollard about 11 years
    Passing an NSString is fine... see the other answers
  • Sasha Grievus
    Sasha Grievus about 11 years
    cool! and what if the function return something i need to get? (i.e. return [RXMLElement etc.....])
  • Sasha Grievus
    Sasha Grievus about 11 years
    In the second way the code will be execute out of the main thread without messing up with the ui flow?
  • Sugan S
    Sugan S about 11 years
    if u want to get from method that called method should return something i.e instead of void use your return type.ex - (return type)callXml:(NSString *) name { } k @ElisabettaFalivene
  • Mike Pollard
    Mike Pollard about 11 years
    Yes. See here ... "Concurrent queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue. The currently executing tasks run on distinct threads that are managed by the dispatch queue. The exact number of tasks executing at any given point is variable and depends on system conditions."
  • Mert
    Mert about 11 years
    3. Option would be passing a custom object, which contains all needed params.
  • Sugan S
    Sugan S about 11 years
    if u want to store it in some variable then type var_name=[self method];then the called method will return some value. @ElisabettaFalivene
  • Sasha Grievus
    Sasha Grievus about 11 years
    It's what i was guessing but when i did - (RXMLElement *)callXml:(NSString *) xmlName{ return [RXMLElement elementFromURL:[NSURL URLWithString:xmlName]]; } and RXMLElement *rootXML=nil; rootXML = [self performSelectorInBackground:@selector(callXml) withObject:indXMLdateAggiornamento]; it began saying "Assigning to 'RXMLElement *' from incompatible type 'void'"
  • Sugan S
    Sugan S about 11 years
    can u tell me what typ will be return for this line [RXMLElement elementFromURL:[NSURL URLWithString:indXML]];? it will be of type (RXMLElement *)???
  • Sugan S
    Sugan S about 11 years
    hey just use return [RXMLElement elementFromURL:[NSURL URLWithString:indXML]]; in your code
  • Sugan S
    Sugan S about 11 years
    RXMLElement *rootXML=[self performSelectorInBackground:@selector(callXml:) withObject:@"test"];
  • Sugan S
    Sugan S about 11 years
    hi friend check my updated answer and let me know @ElisabettaFalivene
  • Sugan S
    Sugan S about 11 years
  • Sugan S
    Sugan S about 11 years
    just try this RXMLElement* var ; - (void)callXml:(NSString *) name{ var= [RXMLElement elementFromURL:[NSURL URLWithString:indXML]]; NSLog("%@",var); } and post what u get in consol @ElisabettaFalivene
  • Sasha Grievus
    Sasha Grievus about 11 years
    It throws an error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSThread initWithTarget:selector:object:]: target does not implement selector (*** +[funzioni callXml:])' ----- where "funzioni" is my class. I tried to define the function in my .m and in my .h. No fortune.
  • Sasha Grievus
    Sasha Grievus about 11 years
    I was still guessing what to do. I have still problem using the performSelector for the way you suggested to use it throws me an exception, but it's true i've solved the problem abandoning performSelector and using dispatch_async. Deal! ;)
  • βhargavḯ
    βhargavḯ about 11 years
    @ElisabettaFalivene Mike Pollard already shown you how to update UI from background thread.
  • Sasha Grievus
    Sasha Grievus about 11 years
    using GCD? Yes, that's why i choose his answer. The problem is solved for me, but i was curios of solving the issue i had with performSelector. ^^' It's not so important, though, so i give up.
  • Mike Pollard
    Mike Pollard about 11 years
    Just picking up on your problem trying the performSelector way: In the 'NSInvalidArgumentException' +[funzioni callXml:]) note the '+'. It means it's looking for a class method ( +(void)callXml: ) not an instance method ( -(void)callXml: ) implying that you were calling performSelector from within a class method rather than an instance method...
  • newacct
    newacct about 11 years
    @ElisabettaFalivene: Bhargavi gave the correct answer based on all the information you gave. Your error is inconsistent with your question. Your error (that it is trying to call a class mehtod, i.e. the object you are calling it on, self is a class) indicates that you are making the call from a class method. If that were the case, then what you were doing previously (if called from the same place) when calling callXml was also calling a class method. However, in your question, you showed callXml and callXml: as instance methods.