Button's action causes "invalid selector" crash -- why? - objective-c

This code results in an "invalid selector" error when the button I create is pressed. Where is the test function fetched from?
Main.m
mainScreen = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
[self.view addSubview:mainScreen];
TaskButtons *tB = [[TaskButtons alloc] init];
[mainScreen addSubview:[tB TaskStart]];
TaskButtons.m
- (UIButton*)TaskStart {
CGRect buttonFrame = CGRectMake(500, 206, 400, 35);
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = buttonFrame;
[button setTitle:#"Task Button" forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
button.titleLabel.textAlignment = UITextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[button addTarget:self action:#selector(test) forControlEvents:UIControlEventTouchUpInside];
return button;
}
- (void)test{
NSLog(#"test line");
}
It seems that the test function isn't being called. Doesn't setting the button's target to self here mean it should look in the TaskButtons class for the function called test?

The problem is ARC is releasing the instantiated object too soon. So to solve this I would need to retain it longer.
Main.h
#import "TaskButtons.m"
#interface ViewController : UIViewController {
TaskButtons *tB;
}
#property (nonatomic, retain) TaskButtons *tB;

[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
- (void)test:(id)sender{
NSLog(#"test line");
}
Syntax problem :) In your code replace these lines.

Related

Objective-c : action:#selector(xxxxxx) not called

I'm currently trying to add a button to my app. If the user push on it, it should display an alert.
I want to add the button to a section header of a tableview. Here is my code in tableView:viewForHeaderInSection:
UIImageView *headerView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 20)] autorelease];
...
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(180, 4, 15, 15)];
UIImage *img=[UIImage imageNamed:#"myimg"];
[button setImage:img forState:UIControlStateNormal];
[button addTarget:self action:#selector(showMyAlert) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:button];
return headerView;
And in the same class, I have the method :
-(void)showMyAlert{
NSLog(#"HERE SHOW ALERT");
...
}
The button is correctly displayed but the showMyAlert method is never called when I push on it.
Does anyone have an idea of what is wrong with my code ?
Thanks if you could help me :)
Change your UIImageView as UIView and return it as the header view.
UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 20)] autorelease];
Make sure img is not nil. If that is nil, your button will have no image and you will see nothing.
Modified below lines of code, Try like this:-
[button addTarget:self action:#selector(showMyAlert:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)showMyAlert:(id)sender{
NSLog(#"HERE SHOW ALERT");
...
}
Try this, in viewDidLoad,
-(void)viewDidLoad
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(XXX, YYY, XXX, YYY)];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 20)] autorelease];
[headerView addSubview:imageView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(180, 4, 15, 15)];
UIImage *img=[UIImage imageNamed:#"myimg"];
[button setImage:img forState:UIControlStateNormal];
[button addTarget:self action:#selector(showMyAlert) forControlEvents:UIControlEventTouchUpInside];
[headerView addSubview:button];
self.tableView.tableHeaderView = headerView;
}

textfield for ios

i am very new to iOS and xcode. i want to create a textfield without using nib files or storyboard. i searched for the answers but everywhere its kind of confusing or they have used nib files. i have created buttons and its working fine but for textfields m facing problems. here is my viewcontroller.m please help.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor purpleColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
UITextField *textfield;
button.frame = CGRectMake(10 ,350 , 300, 40);
button1.frame = CGRectMake(10 ,50 , 300, 40);
textfield.frame = CGRectMake(10, 100, 200, 30);
[button setTitle:#"Change screen to green!" forState:UIControlStateNormal];
[button1 setTitle:#"click screen to red!" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[button1 addTarget:self action:#selector(buttonPressed1) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[self.view addSubview:button1];
[self.view addSubview:textfield];
}
-(void)buttonPressed {
self.view.backgroundColor = [UIColor greenColor];
}
-(void)buttonPressed1 {
self.view.backgroundColor = [UIColor redColor];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
thanks & regards
You just declared the UITextField instead of allocating. You must allocate it first then set frame & add it on the view like -
UITextField *txt = [[UITextField alloc] init];
txt.frame = CGRectMake(10, 100, 200, 30);
txt.delegate = self;
[self.view adsubview:txt];
It solves your problem.
First use
UITextField *textfield = [[UITextField alloc] init];
instead of
UITextField *textfield;
Then set backgroud color of textfield since the backgroud color will be clearColor by default.
textfield.backgroundColor = [UIColor whiteColor];
or use
textfield.borderStyle = UITextBorderStyleRoundedRect;
to get white colored bordered text field.
If you've added the alloc init like the answers have suggested, your text field is in fact on the screen, but since it has no border or no text, you can't see it. Try adding this line, and then you will see it:
textfield.borderStyle = UITextBorderStyleRoundedRect;
Use this:
UITextField *textfield = [[UITextField alloc] init];
Insetd of
UITextField *textfield;
UITextField *textfield; Just crete object reference Not object.
UITextField *textfield =[[UITextField alloc] init];
textfield.frame = CGRectMake(10, 100, 200, 30);
textfield.delegate = self; [self.view addSubview:textfield];
[self.view bringSubViewToFront:textfield];
may solve the problem

Why is my UIButton not displaying on my view?

I have a iOS5 project using storyboard and with ARC on.
I have a view in storyboard with the class thisViewController and in there I got a smaller subview which I dragged in and gave it the class thisView.
thisView has a custom drawRect function, that works and draws what I want nicely.
But I also want to add buttons dynamically, so I'll add them in the initWithFrame method of thisView like so:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"This is called <3");
UIButton *btn= [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(0, 0, 50, 50);
btn.backgroundColor = [UIColor redColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
[self bringSubviewToFront:btn]; // last thing I tried, didn't work, thought z-index was to low or something
}
return self;
}
The function is being called since the NSLog displays, but the button is nowhere to be found
--EDIT--
Extra information:
ThisView.h
#interface RadarView : UIView <CLLocationManagerDelegate>{
CLLocation *currentLocation;
}
Dont add the SubView in the init method.
Add the SubView in the - (void)layoutSubviews.
- (void)layoutSubviews {
[super layoutSubviews];
if (![self viewWithTag:12345]) {
UIButton *btn= [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(0, 0, 50, 50);
btn.tag = 12345;
btn.backgroundColor = [UIColor redColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
}
}
I found what the problem was thanks to some comments and the chat
There was an init in the radarviewcontroller, which triggered initwithframe, which made the NSLog display, and the initwithcoder wasn't used so I didn't see anything, that was the problem and got stuff mixed up. Thanks for commenting and helpin!

How can I replace the text in a round rect button with a spinner?

I have a view with a generic rounded rect button that segues to another view. When users press the rounded rect it starts a fetch. I would like to have a spinning wheel replace the text ("Next") inside the rounded rect button while the fetch is processed.
I created the spinner:
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];
But I don't know how to make it replace the text in the rounded rect button.
Any suggestion? Thank you.
Create (or get a reference to) the button as usual, then, while handling the button click, create your spinner and set it as a subview of the button. It's probably also worth disabling the button to stop multiple clicks.
Something along the following lines should do the trick:
...
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(10, 10, 70, 40);
[button setTitle:#"Next" forState:UIControlStateNormal];
[button addTarget:self action:#selector(click:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
...
- (void)click:(UIButton *)button {
[button setTitle:#"" forState:UIControlStateNormal];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];
spinner.frame = button.bounds;
[button addSubview:spinner];
button.enabled = NO;
// do your actual work...
}
I wrote a category that utilizes associated objects
UIButton+ActivityIndicator.h
// Created by reynaldo on 1/16/14.
#import <Foundation/Foundation.h>
#interface UIButton (ActivityIndicator)
- (void)startActivityIndicator;
- (void)stopActivityIndicator;
#end
UIButton+ActivityIndicator.m
// Created by reynaldo on 1/16/14.
#import <objc/runtime.h>
#import "UIButton+ActivityIndicator.h"
static char TITLE_KEY;
static char ACTIVITY_INDICATOR_KEY;
#implementation UIButton (ActivityIndicator)
- (void)startActivityIndicator {
objc_setAssociatedObject(self, &TITLE_KEY, self.currentTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self setTitle:#"" forState:UIControlStateNormal];
UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[self addSubview:activityIndicatorView];
activityIndicatorView.frame = CGRectMake(self.frame.size.width / 2, self.frame.size.height / 2. - 2, 7, 7);
[activityIndicatorView startAnimating];
objc_setAssociatedObject(self, &ACTIVITY_INDICATOR_KEY, activityIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)stopActivityIndicator {
NSString *title = objc_getAssociatedObject(self, &TITLE_KEY);
UIActivityIndicatorView *activityIndicatorView = objc_getAssociatedObject(self, &ACTIVITY_INDICATOR_KEY);
if(activityIndicatorView) {
[activityIndicatorView removeFromSuperview];
}
if(title.length) {
[self setTitle:title forState:UIControlStateNormal];
}
}
#end

Custom TabBar with UIButtons

First: Sorry for my bad English!
I have a class in which I create UIButton. The UIButton I add a UIView. In the ViewController I would like to add these custom tabbar. This works well so far. However, there are problems with addTarget: action: forControlEvents: - How can I run from the ViewController an instance method in the class? The class is of type NSObject. My code:
TabBar *tabBar = [[TabBar alloc] init];
[tabBar tabBarButton];
[tabBar.home addTarget:tabBar action:#selector(switchView) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:tabBar.tabView];
And here is my Class:
#implementation TabBar
#synthesize tabView, home, list, charts, favorits, more;
-(void)tabBarButton{
tabView = [[UIView alloc] initWithFrame:CGRectMake(0, 360, 320,56)];
home = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 43, 56)];
list = [[UIButton alloc] initWithFrame:CGRectMake(63, 0, 40, 56)];
charts = [[UIButton alloc] initWithFrame:CGRectMake(123, 0, 49, 56)];
favorits = [[UIButton alloc] initWithFrame:CGRectMake(192, 0, 66, 56)];
more = [[UIButton alloc] initWithFrame:CGRectMake(278, 0, 42, 56)];
[home setImage:[UIImage imageNamed:#"home.png"] forState:UIControlStateNormal];
[list setImage:[UIImage imageNamed:#"liste.png"] forState:UIControlStateNormal];
[charts setImage:[UIImage imageNamed:#"charts.png"] forState:UIControlStateNormal];
[favorits setImage:[UIImage imageNamed:#"favorites.png"] forState:UIControlStateNormal];
[more setImage:[UIImage imageNamed:#"more.png"] forState:UIControlStateNormal];
home.tag = 1;
list.tag = 2;
charts.tag = 3;
favorits.tag = 4;
more.tag = 5;
[tabView addSubview:home];
[tabView addSubview:list];
[tabView addSubview:charts];
[tabView addSubview:favorits];
[tabView addSubview:more];
}
-(void)switchView{
NSLog(#"hi");
}
When I start the app, it crashes immediately when I press one button.
If you're getting an unrecognized selector error, you might try:
[tabBar.home addTarget:tabBar action:#selector(switchView:) forControlEvents:UIControlEventTouchUpInside];
Note the colon behind action:#selector(switchView:)