Objective C - UIStepper reaction - iphone

I tried to ask this question, but somehow I failed to express myself right I guess so I deleted it and started fresh.
I have a hierarchy:- ViewController => UIView => Stepper
Here is my code of the UIView:-
#implementation Controls
#synthesize m_numColumn=_whatever;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
int i;
m_numColumn= [[UIStepper alloc]init];
m_numColumn.frame = CGRectMake(1, 1, 30, 30);
m_numColumn.autorepeat= FALSE;
[m_numColumn setValue:2];
m_displayColumnNum= [[UILabel alloc]init];
m_displayColumnNum.frame = CGRectMake(30, 30, 60, 30);
// m_displayColumnNum.backgroundColor =lgammaf(<#float#>);
// m_displayColumnNum.text= [NSString stringWithFormat:#"aaaaaa"];
i= m_numColumn.value;
m_displayColumnNum.text= [NSString stringWithFormat:#"%d",i];
[self addSubview:m_numColumn];
[self addSubview:m_displayColumnNum];
// Controls.delegate = [m_numColumn.navigationController.viewControllers objectAtIndex:0];
[m_numColumn addTarget:self action:#selector(stepperChanged:) forControlEvents:UIControlEventTouchUpInside];
//[m_numColumn setdelegate];
}
return self;
}
The important line here is:
[m_numColumn addTarget:self action:#selector(stepperChanged:) forControlEvents:UIControlEventTouchUpInside];
What I would like is to react on that event in the UIViewController (parent object). How do I do that?

Is the problem that you don't get the event? I have always used UIStepper with "UIControlEventValueChanged", in your case it should be:
[m_numColumn addTarget:self action:#selector(stepperChanged:) forControlEvents:UIControlEventValueChanged];

there is the point of the controlEvents you are listening to, but there is also a problem with the target
[m_numColumn addTarget:self action:#selector(stepperChanged:) forControlEvents:UIControlEventTouchUpInside];
you shouldn't use "self" which is a reference to your view and not your view controller, either use a "myController" variable or do this method inside your controller

Related

UIButton Crashes on Click

Okay, so this is pretty weird; before upgrading to the final GMseed of Xcode my buttons worked perfectly fine...
Now I can't even do them on a super simple scale without the program crashing on click.
The absolute most bizarre aspect is that it works SOME of the time, but like 85%, it just crashes; and when it does work, it'll crash after extensive use.
Here is my code (stripped down to the simplest button implementation I could think of):
#interface TESTViewController ()
{
UIButton *button;
}
#end
#implementation TESTViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addButton];
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
}
- (void)addButton
{
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 45)];
[button setTitle:#"CLICK" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:button];
}
- (void)buttonPressed
{
NSLog(#"WORKED");
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
TESTViewController *test = [[TESTViewController alloc] init];
[self.window addSubview:test.view];
return YES;
}
I've tried creating the button in the init function, viewDidLoad -- neither works consistently, though viewDidLoad seems to work a little more frequently...
I tried -(void) addButton:(UIButton*)button as well
Using:
[button addTarget:self action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchDown];
--No difference.
I am at a total loss. I tried looking it up here on the forums, but unfortunately most of it refers to programming with IBActions.
The error I get is bad access
So my guess is that when the button is clicked, it's not actually accessing the buttonPressed function but something else entirely... I have no clue as to why this would be the case...
Thanks for any help!
The problem is in your "didFinishLaunchingWithOptions" method. Here you are creating a local object which gets Deallocated i.e "TESTViewController *test = [[TESTViewController alloc] init]".
You should retain this object, so try making it a property and use "self.test = [[TESTViewController alloc] init]". It will work.
Also conventionally you should use rootViewController rather adding your viewController to windows's subview.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.test = [[TESTViewController alloc] initWithNibName:nil bundle:nil];
self.window.rootViewController = self.test;
[self.window makeKeyAndVisible];
return YES;
}
I think you have a memory leak on that Button object are you using ARC or manual memory management? If manual make sure you retain it. If it is ARC use a property and the compiler will do the rest of the work
#property (nonatomic, strong) UIButton *button;
try it this way
- (void)addButton
{
button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 80, 45)];
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"CLICK" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blackColor]];
[self.view addSubview:button];
}
and remove
[button addTarget:self action:#selector(buttonPressed)
forControlEvents:UIControlEventTouchDown];
this line from viewDidLoad
I am not sure if this is the cause of the crash but actions (like your buttonPressed) should have a sender parameter:
[button addTarget:self action:#selector(buttonPressed:)
- (void)buttonPressed:(id)sender
{
...
}
To define a button programatically use the buttonWithType method, Try this
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonPressed)
forControlEvents: UIControlEventTouchUpInside];//Any control event type
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 80, 45);
[view addSubview:button];

wrapping a UIButton in UIBarButtonItem selector doesn't invoke

I created the following class to get a toolbar with colored images
#interface likeUIBarButtonItem : UIBarButtonItem
- (id) initWithStatus: (enum ApartmentLikeStatus)p_status;
#end
and the m file looks like this:
- (IBAction) likeStatus_Clicked: (id) sender
{
self.numberOfClicks++;
[self.statusButton setImage:[self getStatusImage] forState:UIControlStateNormal];
}
- (id) initWithStatus: (enum ApartmentLikeStatus)p_status
{
self.statusButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.statusButton setImage:[self getStatusImage] forState:UIControlStateNormal];
[self.statusButton addTarget:self action:#selector(likeStatus_Clicked:) forControlEvents:UIControlEventTouchUpInside];
[self.statusButton setFrame:CGRectMake(0, 0, 20, 20)];
self = [[likeUIBarButtonItem alloc] initWithCustomView:self.statusButton];
return self;
}
in the view controller I do the following:
likeUIBarButtonItem* stausBtn = [[likeUIBarButtonItem alloc] initWithStatus:self.apartmentToShow.userLikness];
// List of toolbaritems
NSArray* toolbarItems = [NSArray arrayWithObjects: stausBtn, nil];
self.toolbarItems = toolbarItems;
self.navigationController.toolbarHidden = NO;
the button gets displayed but when clicking it i get an assembly code
0x120a09f: movl (%edi), %esi <-- thread 1: EXC_BAD_ACCESS (code=2 address=0x0)
although my statusButton is declared (strong, nonatomic) my guess it gets released somewhere between the init and the call to the function, is that the case or is it something else? and whatever it is how do I fix it?
That's not how you override an init* method.
You might be better off with something like this
- (instancetype)initWithStatus:(enum ApartmentLikeStatus)status
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[self getStatusImage] forState:UIControlStateNormal];
[button addTarget:self action:#selector(likeStatus_Clicked:) forControlEvents:UIControlEventTouchUpInside];
[button setFrame:CGRectMake(0, 0, 20, 20)];
self = [super initWithCustomView:button];
if (self) {
self.statusButton = button;
}
return self;
}
The problem with your version is that you create a button and assign it to self but then you reassign self to a completely new object at the end. So the initial self probably be released immediately as no one else can get a handle on it, which basically means you are passing a dangling pointer into the initWithCustomView: method

How to see the tag of a programmatically created UIButton

on one viewController of my app there is a long list of 20 or so buttons added programmatically, all which i want to call the same method, but to identify themselves through their button tag, but i ran into a problem that has set me back a few hours of research and attempts.The basic problem is i dont quite know how to access a programmatically created button in any other method than the method that they were initialized in.
My questions summerized:
1) if i were to create the button in the viewDidLoad method, how can I access it in a void method that i create?
2) How can i access those button tags in the created void method?
Here is the code that i have so far, but it is producing errors that ill explain below.
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
button.tag =1;
[button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected{
if ([sender tag] == 1) { //Gets error "Use of undeclaired identifier 'sender'"
button.hidden = YES; //Gets error "Use of undeclaired identifier 'button1'"
}
}
We aren't working in the mystical relm of ruby, things need to be initialized and stored somewhere inorder for you to call them, try this:
#.h
#interface MyController : UIViewController{
NSMutableArray *buttons;
}
#.m
-(void)init // Or whatever you use for init
{
buttons = [[NSMutableArray alloc] init];
}
-(void)viewDidLoad{
//blah blah (what you already have)
[button addTarget:self action:#selector(itemSelected:) //Add ":"
forControlEvents:UIControlEventTouchUpInside];
button.tag =0;
[buttons addObject:button] //Add button to array of buttons
//blah blah (what you already have)
}
-(IBAction)itemSelected:(id)sender{
UIButton* button = [buttons objectAtIndex:sender.tag]
button.hidden = YES;
}
Note: I'm doing this from memory on, so it might not work perfectly.
#.h
#interface MyController : UIViewController{
UIButton *buttons;
}
#.m
-(void)viewDidLoad{
float itemScrollerXdirection =0;
float itemScrollerYdirection =0;
float ySize =70.0;
float xSize = 70.0;
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.button.frame = CGRectMake(itemScrollerXdirection,itemScrollerYdirection,xSize,ySize);
[self.button addTarget:self action:#selector(itemSelected) forControlEvents:UIControlEventTouchUpInside];
self.button.tag =1;
[self.button setTitle:#"button1" forState:UIControlStateNormal];
[itemScroller addSubview:button];
}
//no errors in the above code
-(void)itemSelected
{
if ([sender tag] == 1)
{
self.button.hidden = YES;
}
}

Programmatically added button getting crash in storyboard

I am adding a button in UIScrollView in StoryBoard
Below is the code i am using.
-(void)addScrollView
{
for(int i=0;i<[array count];i++)
{
UIScrollView *subScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 400, SUBSCROLLVIEW_WIDTH, SUBSCROLLVIEW_HEIGHT)];
UITextView *txtVwDetail = [[UITextView alloc] initWithFrame:CGRectMake(342, 0, TEXTVIEW_WIDTH, TEXTVIEW_HEIGHT)];
txtVwDetail.text = SAMPLE_STRING;
[self addSubScrollView:subScrollView];
[self.view addSubview:subScrollView];
[self.view addSubview:txtVwDetail];
}
}
-(void)addSubScrollView:(UIScrollView *)aSubScrollView
{
for(int i=0;i<[array count];i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
aButton.frame = CGRectMake(intBtnX, (aSubScrollView.frame.size.height - 80)/2, 50, 80);
[aButton setImage:[UIImage imageNamed:[self.items objectAtIndex:i]] forState:UIControlStateNormal];
**[aButton addTarget:self action:#selector(btnSubImageClicked) forControlEvents:UIControlEventTouchUpInside];**
aSubScrollView.contentSize = CGSizeMake(intScrollViewWidth, aSubScrollView.frame.size.height);
[aSubScrollView addSubview:aButton];
}
}
In addSubScrollView method I have added Button and its click event which is getting crashed.
-(void)btnSubImageClicked
{
NSLog(#"btnSubImageClicked");
}
I am having scenario as
MyMainViewController is the sourceViewController for my created customSegue which is the UIStoryboardSegue class
MyMainViewController having a UIView as PlaceHolderView in which I am adding MydestinationViewContoller's View which is this Scrollview
-(void)perform
{
BrowseScreenVC *srcObj = (BrowseScreenVC *)[self sourceViewController];
UIViewController *dstObj = (UIViewController *)[self destinationViewController];
for(UIView *vw in srcObj.viewPlaceHolder.subviews)
{
[vw removeFromSuperview];
}
NSLog(#"dest : %#",dstObj.view);
NSLog(#"destobj :%#",dstObj);
srcObj.currentViewController = dstObj;
[srcObj.viewPlaceHolder addSubview:[dstObj.view retain]];
}
UPDATE
With answer I also have to change the line
srcObj.currentViewController = dstObj;
to
srcObj.addChildViewController = dstObj;
to make it working
you have to add target as follow:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
#selector(), within these braces you have to provide the method that you want to perform. the ":" represents that the method has some argument. In this case the argument would be the button itself that is calling the method.
You have to implement your method then its signature would look like this
- (void)btnSubImageClicked:(id)sender{
// sender would be the button that is calling the method. you can use this object according to your requirements if you want.
// your code
}
if you want to call this method from somewhere else as well you can call it by passing sender argument nil. e.g [self btnSubImageClicked:nil];
Your action needs to accept an (id) sender argument, even if you are not using it:
-(void)btnSubImageClicked:(id) sender
{
NSLog(#"btnSubImageClicked");
}
In the addSubScrollView:
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Button target should like
-(void) btnSubImageClicked:(id)sender{}
try this.
Updated:-
Please correct your code,change this line
[aButton addTarget:self action:#selector(btnSubImageClicked:) forControlEvents:UIControlEventTouchUpInside];
Now working i checked.
Instead of
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
write this,
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
and for better practice always write this,
-(void) btnSubImageClicked:(id)sender{}

How to add a UIButton at runtime

I am trying to add a UIButton at runtime however it is not visible. What am I doing wrong?
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick:)
forControlEvents:UIControlEventTouchUpInside];
btn.center = self.center;
[self addSubview:btn];
}
return self;
}
First, make sure the initWithFrame: method is being called. If your view is in a Nib, initWithCoder: is being called instead.
Second, is the button the only subview (from your code it looks like it is, but you never know). The button could be hidden behind another subview. Call bringSubviewToFront: if you need to.
Finally, is the view itself visible? Is it big enough to show the button? Given your example, if the view is less than 100 pixels wide, the button won't show because it will get clipped by the view's bounds.
You must release btn and remove ":" in buttonClick:
UIButton *btn= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[btn release];
if it still doesn't work, try removing the : at the end of the selector name: #selector(buttonClick)
You don't need to retain the UIButton because it is retained by [self.view addSubview:btn];
First check whether your code is executing the initwithFrame method.
Because if you are loading the view from nib i.e using
NSArray *xibviews = [[NSBundle mainBundle] loadNibNamed: #"MySubview" owner: mySubview options: NULL];
MySubview *msView = [xibviews objectAtIndex: 0];
[self.view addSubview:msView];
Then the initWithFrame part will not be executing.So please check once.