Reputation: 874
I am trying to add an action to a button programmatically from within a custom class. However, I keep getting an error when I perform the action. I've read a lot about how to do this but am clearly making a mistake somewhere and can't figure out where.
The button is created in the first instance by dragging it onto the storyboard. I then control drag to the ViewControler.h file to get this:
@property (strong, nonatomic) IBOutlet UIButton *testButtonForClass;
In ViewControler.m, I do this:
- (void)viewDidLoad
{
[super viewDidLoad];
testClass *myClass = [[testClass alloc]init];
myClass.myButton = self.testButtonForClass;
[myClass assignActionTargets];
}
Below is the custom class Header and Implementation file.
Header File
#import <Foundation/Foundation.h>
@interface testClass : NSObject
@property (nonatomic, strong) UIButton *myButton;
-(void)assignActionTargets;
@end
Implementation File
#import "testClass.h"
@implementation testClass
-(void)assignActionTargets{
[self.myButton addTarget:
self action:@selector(myButtonInnerTap)
forControlEvents:(UIControlEventTouchUpInside)];
}
-(void)myButtonInnerTap{
UIAlertView *a = [[UIAlertView alloc]initWithTitle:nil
message:@"testClass says hello"
delegate:nil
cancelButtonTitle:@"Dismiss"
otherButtonTitles:nil, nil];
[a show];
}
@end
Upvotes: 0
Views: 115
Reputation: 80271
First, the double nil
for the argument otherButtonTitles
is "problematic". Reduce it to one.
Second, make sure the button and the object is properly retained by your calling class.
Finally, make sure via NSLog
or breakpoints that the objects in question (custom object, button) are not nil.
Upvotes: 0
Reputation: 108169
You create a testClass
instance, but you don't keep a reference to, so it gets deallocated at the end of viewDidLoad
.
- (void)viewDidLoad {
[super viewDidLoad];
TestClass *myClass = [[TestClass alloc] init];
myClass.myButton = self.testButtonForClass;
[myClass assignActionTargets];
// myClass gets deallocated here!
}
When the button is clicked, it tries to access the target you specify, but now that's a dangling pointer to an invalid memory segment, hence leading to a crash.
You have to keep a strong reference to myClass
in order to keep it alive by the time the button is clicked. Declaring a strong property is a good way of achieving that.
@property (nonatomic, strong) TestClass *myThingy;
- (void)viewDidLoad {
[super viewDidLoad];
self.myThingy = [[testClass alloc] init];
self.myThingy.myButton = self.testButtonForClass;
[self.myThingy assignActionTargets];
}
Code style note: Please, use some naming conventions. Class names should be capitalized (I already changed that in the above snippets, since it kills me...) and using myClass
for a pointer to an instance of a class is plain disorienting.
Upvotes: 1