perform:#selector using a method with parameters - iphone

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

Related

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

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.

Return customized UIButton in method?

I have a method that takes a UIButton, modifies its properties and returns a UIButton. However, it doesn't ever seem to be initialized. I'm sure I'm doing something wrong with the memory management here, but don't exactly know how to fix it. No runtime errors occur.
It is called like so...
newGameBtn = [self customButtonFromButton:newGameBtn
withText:[NSString stringWithFormat:#"NEW GAME"]
withFontSize:22
withBorderColor:[UIColor orangeColor]
isSilent:YES];
[dashboardContainer addSubview:newGameBtn];
The method is defined as follows...
- (UIButton*) customButtonFromButton:(UIButton*)button withText:(NSString*)text withFontSize:(int)fontSize withBorderColor:(UIColor*)borderColor isSilent:(BOOL)isSilent {
button = [[[UIButton alloc] init] autorelease];
// Set properties from parameters
// Other conditional custom stuff here
return button;
}
NOTE: newGameBtn is of type UIButton* and is initialized with:
newGameBtn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
Another option might be to subclass UIButton, but I figured I'd try to fix this since I've already walked down this path.
You should use +[UIButton buttonWithType:] when creating buttons to get a properly initialized button.
Most classes are not properly initialized by the default -[NSObject init] method. So please look at the class reference, or superclass reference, for a usable initialization method.
In this case you should also set a frame.
You don't modify this button with your method, you're creating a completely new one with alloc-init!
If you want to change the button in your first argument just remove the first line of your method

pass a variable between two methods

I was trying to pass a variable of type NSString from a method to another. what I have done is:
-(void)some{
NSString *lat = something
NSString *longt = somethingElse
[self test:lat:longt];
}
and then
- (IBAction)test:(NSString *)lat:(NSString *)longt{
doSomeThing
}
But my problem is that now the IBAction button is activated without my press.
how do I run the method IBAction under my control
you cannot pass arbitrary parameters through an IBAction, you can either pass the control sending the action or nothing:
-(IBAction)action:(id)sender;
or
-(IBAction)action;
The test method should not be an IBAction. Instead do this:
- (void)test:(NSString *)lat:(NSString *)longt{
//doSomeThing
}
-(IBAction)myAction:(id)sender
{
//call test from here
[self some];
}
You should use void as returm type of method not ibaction. If u need it for some action thn call it from there.
use
- (void) test:(NSString *)lat:(NSString *)longt
instead of
- (IBAction)test:(NSString *)lat:(NSString *)longt

Selector with argument

I have a method like this:
- (void)methodWithParameter:(id)parameter {
}
and I want to call it using an UIBarButtonItem
barButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(methodWithParameter:)];
I want to specify the parameter but I can't use withObject: after action: because I get a warning:
No -initWithBarButtonSystemItem:target:action:withObject: method found
can anybody help me with this?
It doesn't work that way. You cannot pass a parameter to an action. An action method will always have either:
no arguments at all,
one argument (id)sender,
or two arguments (id)sender and (UIEvent *)event.

#selector key word in iPhone programming

-(void)displayNameBy:(NSString*)name{
mylable.text = name;
}
i want call this method using #selector keywords.
eg:
[MyButton addTarget:self action:***#selector(displayNameBy:name)*** forControlEvents:UIControlEventTouchUpInside];
Here bold italics is my doubt.. could i pass name parameter from here. when i try to pass name value i getting error.
any way to get name value in the displayNameBy:name method . using #selector key words.
here MyButton i created by programatically . not in interface builder.
thanks and regards
Have an intermediate method.
like:
{
...
[MyButton addTarget:self action:#selector(displayName) forControlEvents:UIControlEventTouchUpInside];
...
}
-(void) displayName
{
[self performSelector:#selector(displayNameBy:) withObject:#"name"];
}
-(void)displayNameBy:(NSString*)name{
mylable.text = name;
}
If you create a one-argument selector for your action (like you're doing in displayNameBy:), the argument is the sender of the action. In this case, your button instance.
According to the UIControl docs, there are three different types of supported selectors:
- (void)action
- (void)action:(id)sender
- (void)action:(id)sender forEvent:(UIEvent *)event
Where are you expecting name to be defined? Is it based on the user's actions, the app state, or something else? Depending on what method is used, you could create a UIButton subclass that includes either the necessary logic or declares a delegate protocol, set the delegate to your view controller, and have the delegate implementation set the button's label. The latter is probably better from a MVC standpoint, unless the source of name is blindingly simply (ie, an attribute that could be set on the button, not something the button would have to calculate based on other application state).
The method's selector is just displayNameBy:. The name it the end is the name of the parameter. However, I don't know where you're expecting this NSString *name parameter to come from. The argument for an action method is the sender, which will be the button in this case. So it would be - (void)displayNameBy:(id)sender.
If you're trying to pass the parameter through the selector, that isn't possible. A selector is literally just a name — it doesn't specify any particular behavior.
If you wanted to use PLBlocks, you could create a trampoline class that would be called like:
[myButton setTarget:[BlockProxy proxyWithBlock:^{ [self displayNameBy:name]; }] action:#selector(call:) forControlEvents:UIControlEventTouchUpInside];
That's the closest you'll get, I think. Because what you really want is for the button to call a closure, which is what PLBlocks gives you. Whether it's worth the trouble to get this kind of expressiveness is you're call.