Difference between the use of withObject:self and withObject:nil - iphone

I have been wondering about the following lines of code
[self performSelector:#selector(myMethod) withObject:self afterDelay:1.0];
[self performSelector:#selector(myMethod) withObject:nil afterDelay:1.0];
Whats the difference between the above 2 lines of code.
When should we set object as nil and when should we set object as self?
In most cases I have noticed the object to be set as nil.

In the example you listed you won't experience any different behavior because your method myMethod takes no arguments. Where this is useful, is when you have a method that takes arguments.
Let's say we declared a method, squareRootMethod: that takes a NSNumber and returns the squareRoot. Then you would call [self performSelector:#selector(squareRootMethod:) withObject:numberToRoot afterDelay:1.0]
There are also methods like performSelector:withObject:withObject: for selectors that take more than one argument.

Notice the difference between these two:
#selector(myMethod)
#selector(myMethod:)
The first one is a method that doesn't take any parameters, the second is a method that takes one parameter. The withObject: part of the performSelector: method you're using allows you to pass an object into the method when it is called. However, in the case where the method doesn't take any parameters it doesn't matter because it won't be used.

The difference is whether or not you are passing an object to the selector. All the selector is doing is describing a method.
[self performSelector:#selector(myMethod) withObject:nil afterDelay:1.0];
is different from:
[self performSelector:#selector(myMethod:usingThis:) withObject:nil afterDelay:1.0];
Now if you want the selector (i.e. method) to work on some object that you pass in, say an Array, Dictionary, or class. You use withObject. As in:
[self performSelector:#selector(myMethod:) withObject:myDictionary afterDelay:1.0];
-(void)myMethod:(NSDictionary*)dictionary
{
// Do something with object
}
You could pass in anything including a reference to the current class (e.g. self), as you did in your example.

In the first example, you passed self as the argument to pass to the method when it is invoked. But your method takes no arguments, so it is unnecessary fluff.
In the second example, you passed nil, so the method is passed nil to it's non-existent arguments and then terminates. This is more "efficient" in the sense that because your method takes no arguments, and `nil. Is the object equivalent of NULL, then you pass less fluff through that is ignored anyhow.

Related

How to call a non-void function? Xcode

How do I call a non-void function? Normal [self methodName]; works. But how do I do this for a method that returns an NSString. I keep getting an error. For example:
+ (NSString *)formulateYQLRequestFor:(NSArray *)tickers
How do I call this? [self formulateYQLRequestFor]; gives me an error.
Sorry about the formatting, for some reason safari won't let me indent.
Thanks!
+ designates a class function. You call it with the class name, not an instance.
Instead of:
[self formulateYQLRequestFor:myArray];
Do this:
[MyClassName formulateYQLRequestFor:myArray];
Alternatively, you can do this:
[[self class] formulateYQLRequestFor:myArray];
You don't have to do anything with the return value if you don't want to. At least with ARC, the return value will be automatically released. However, since it's unlikely that the function does anything on its own, you probably should do something with the return value:
NSString *returnValue = [[self class] formulateYQLRequestFor:myArray];
// Do something with returnValue
Finally, if you want to call the function without passing in an array, you still need the array parameter, but perhaps the function will accept nil for the array:
NSString *returnValue = [[self class] formulateYQLRequestFor:nil];
There are two problems with your call to [self formulateYQLRequestFor];
Firstly, the method takes a parameter, which you haven't provided. Because of this, the compiler is looking for the method called formulateYQLRequestFor instead of formulateYQLRequestFor: This is significant, because the : is part of the method name in Objective-C. So you are trying to call a method that doesn't exist.
Secondly, self is sending a message to an instance of your class. The + in the method signature indicates that you have a class method, and so self does not respond to the method you are trying to call.
The correct way to do this is:
NSString *resultString = [[self class] formulateYQLRequestFor:someArray];
where someArray is a valid NSArray parameter.
I don't know what - (NSString *)formulateYQLRequestFor: does with the NSArray, but if it isn't necessary you can just call [self formulateYQLRequestFor:nil];. Alternatively you can call it with an empty array [self formulateYQLRequestFor:[NSArray array]];.

Is this how one method calls another method?

I'm doing some programming and I'm also reading some code at the same time and I come across this code
-(id)init
{
if ((self = [super init]))
{
some code....
[self initEnemy];
}
return self;
}
and below that it has
-(void)initEnemy
{
more code....
[self resetEnemy];
}
and then..
-(void)resetEnemy
{
more code.. etc..
}
The way I see it is the first method called init calls on the method initEnemy and that in turn calls on resetEnemy. Basically one method brings on the other and so on.
Successfully forming an algorithm (you can't really tell because i've shown little code). Am I looking at it the right way?
Also, could I have an explanation on what happens inside the -(id)init method when return self; is performed.
Yup, you're reading that sequence of execution correctly.
When "return" happens in a method, control returns to the "caller" method (whoever originally called it in the first place). The "self" is there to indicate that the value of "self" should be handed back to the caller. (In this case, "self" refers to the instance of the object being initialized in the -init. If you want to know more about initializers, you can break it down into more specific questions.)

perform:#selector using a method with parameters

I have a method hideButton
-(void) hideButton:(UIButton) *button {
[button setHidden:YES];
}
and I get a "can not use an object as parameter to a method" error.
I want to be able to give the button as a parameter to the method when calling this
[self performSelector:#selector(hideButton:smallestMonster1)
withObject:nil afterDelay:1.0];
How can this be done? as the above attempt doesnt work. I need to be able to give the button as a parameter or at least make the method aware of which button is calling to be hidden after 1 second.
Thanks
You can pass parameter to selector via withObject parameter:
[self performSelector:#selector(hideButton:) withObject:smallestMonster1 afterDelay:1.0];
Note that you can pass at most 1 parameter this way. If you need to pass more parameters you will need to use NSInvocation class for that.
Edit: Correct method declaration:
-(void) hideButton:(UIButton*) button
You must put parameter type inside (). Your hideButton method receives pointer to UIButton, so you should put UIButton* there

NSInvocation making app crash

I'm using NSInvocation as follows:
In my init, I'm writing this in my viewDidLoad:
SEL mySelector;
mySelector = #selector(initParsersetId:type:);
NSMethodSignature * sig = nil;
sig = [[self class] instanceMethodSignatureForSelector:mySelector];
myInvocation = nil;
myInvocation = [NSInvocation invocationWithMethodSignature:sig];
[myInvocation setTarget:self];
[myInvocation setSelector:mySelector];
And I'm calling it like this:
Idea *tempIdea = [[Idea alloc]init];
tempIdea = [genericArray objectAtIndex:indexPath.row];
idea.ideaId = tempIdea.ideaId;
[tempIdea release];
NSNumber *_id_ = [NSNumber numberWithInt:idea.ideaId];
[myInvocation setArgument:_id_ atIndex:2]; //CRASHING AT THIS LINE
My application is crashing at the indicated line. Can anybody please help me?
It is not very clear from your codes; however, I see something suspicious. Hopefully, it may provide your some helpful hints.
First, I don't see you retain the instance (auto released from [NSInvocation...). Since the instance from [NSInvocation...] is auto-released, your class level variable myInvocation would not retain it after viewDidLoad event.
Second thing in your codes is that the selector is a kind of customized constructor, beginning with init..... I am not sure if you can invoke the event within the same instance. Another point is that if your init... method to be invoked returns self? It should be.
You may output some messages in your selector event by using NSLog function. All the messages by NSLog will be in your XCode's output console.
I've found the answer but I'm not convinced how. Actually, initially I was writing all the initialisation code in viewDidLoad and simply reusing the NSInvocation object by passing it the different argument since NSInvocation is a mutable object. It didn't work. Then I wrote a method with all the initialisation code inside it and called that method every time I used the NSInvocation object and it worked...
You need to give setArgument: the address of the argument you are passing, and not the argument itself:
[myInvocation setArgument:&_id_ atIndex:2];
NOT
[myInvocation setArgument:_id_ atIndex:2];
Also, are you sure your function takes an NSNumber as first argument?

Objective-C performSelector when to use colon?

Do you only postfix the method name with a : if you are calling a foreign object?
For some reason
[self performSelector:#selector(myMethod:) withObject:nil afterDelay:5];
Does not work but
[self performSelector:#selector(myMethod) withObject:nil afterDelay:5];
Does!
EDIT:
Declared in the implementation of a class but not the interface.
- (void)myMethod
{
// Some stuff
}
The colon represents a method argument. Since myMethod takes no arguments its selector can't have a colon. If you had multiple arguments like this...
- (void)myMethod:(id)method object:(id)object enabled:(BOOL)bool {
// Some Stuff
}
... the selector would be #selector(myMethod:object:enabled:)
In Objective-C the colons are part of the method name. That is, myMethod and myMethod: are distinct selectors (and in your case, only the latter exists).
For instance, for a method declared like:
-(void)doSomethingWithFoo:(int)foo andBar:(int)bar;
The selector is doSomethingWithFoo:andBar:.