Using -performSelector: vs. just calling the method

后端 未结 5 1918
陌清茗
陌清茗 2020-11-28 18:26

I\'m still kind of new to Objective-C and I\'m wondering what is the difference between the following two statements?

[object performSelector:@selector(doSom         


        
5条回答
  •  我在风中等你
    2020-11-28 19:08

    For this very basic example in the question,

    [object doSomething];
    [object performSelector:@selector(doSomething)]; 
    

    there is no difference in what is going to happen. doSomething will be synchronously executed by object. Only "doSomething" is a very simple method, that does not return anything, and does not require any parameters.

    were it something a little more complicated, like:

    (void)doSomethingWithMyAge:(NSUInteger)age;
    

    things would get complicated, because [object doSomethingWithMyAge:42];

    can no longer be called with any variant of "performSelector", because all variants with parameters only accept object parameters.

    The selector here would be "doSomethingWithMyAge:" but any attempt to

    [object performSelector:@selector(doSomethingWithMyAge:) withObject:42];  
    

    simply won't compile. passing an NSNumber: @(42) instead of 42, wouldn't help either, because the method expects a basic C type - not an object.

    In addition, there are performSelector variants up to 2 parameters, no more. While methods many times have many more parameters.

    I have found out that although synchronous variants of performSelector:

    - (id)performSelector:(SEL)aSelector;
    - (id)performSelector:(SEL)aSelector withObject:(id)object;
    - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
    

    always return an object, I was able to return a simple BOOL or NSUInteger too, and it worked.

    One of the two main uses of performSelector is to compose dynamically the name of the method you want to execute, as explained in a previous answer. For example

     SEL method = NSSelectorFromString([NSString stringWithFormat:@"doSomethingWithMy%@:", @"Age");
    [object performSelector:method];
    

    The other use, is to asynchronously dispatch a message to object, that will be executed later on the current runloop. For this, there are several other performSelector variants.

    - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
    - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
    - (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes;
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
    - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;
    

    (yes I gathered them from several Foundation class categories, like NSThread, NSRunLoop and NSObject)

    Each of the variants has its own special behavior, but all share something in common (at least when waitUntilDone is set to NO). The "performSelector" call would return immediately, and the message to object will only be put on the current runloop after some time.

    Because of the delayed execution - naturally no return value is available form the method of the selector, hence the -(void) return value in all these asynchronous variants.

    I hope I covered this somehow...

提交回复
热议问题