I've been trying to figure out something that might be obvious and I'm missing the point or losing it. Is something wrong with my toggleStormButtons function that XCode isn't seeing it?
In my main class I have the following to call a function in another class:
STopLeftMenu *mTopLeft = [[STopLeftMenu alloc]init];
[mTopLeft drawStormToggleButton];
Then in the other class I have 2 functions:
- (void)toggleStormButtons{
[UIButton animateWithDuration:0.50 animations:^{
if (stormToggleBtn.transform.tx == 0){
[stormToggleBtn setTransform:CGAffineTransformMakeTranslation(307, 0)];
UIImage* hideButtonImg = [UIImage imageNamed:#"aiga_right_arrow_mod_hide_resize.png"];
[stormToggleBtn setBackgroundImage:hideButtonImg forState:UIControlStateNormal];
}
else{
[stormToggleBtn setTransform:CGAffineTransformMakeTranslation(0, 0)];
UIImage* showButtonImg = [UIImage imageNamed:#"aiga_right_arrow_mod_show_resize.png"];
[stormToggleBtn setBackgroundImage:showButtonImg forState:UIControlStateNormal];
}
}];
for(UIView* storm in stormButtonSaves){
[UIView animateWithDuration:0.50 animations:^{
if (storm.transform.tx == 0){
[storm setTransform:CGAffineTransformMakeTranslation(307, 0)];
storm.alpha = .65;
}
else{
[storm setTransform:CGAffineTransformMakeTranslation(0, 0)];
storm.alpha = 0;
}
}];
}
}
- (void)drawStormToggleButton{
//Storm Pullout Toggle Button
UIImage *buttonImageNormal = [UIImage imageNamed:#"aiga_right_arrow_mod_show_resize.png"];
stormToggleBtn = [[UIButton alloc] initWithFrame:CGRectMake(10, 10, 65, 75) ];
[stormToggleBtn setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
stormToggleBtn.backgroundColor = [UIColor clearColor];
stormToggleBtn.alpha = 0.5;
[stormToggleBtn addTarget:self action:#selector(toggleStormButtons) forControlEvents:UIControlEventTouchUpInside];
[viewsToRemove addObject:stormToggleBtn];
[mv addSubview:stormToggleBtn];
}
I seem to be getting an unrecognized selector message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSMallocBlock__ toggleStormButtons]: unrecognized selector sent to instance 0x7bc9ca0'
*** First throw call stack:
(0x1b9e012 0x1966e7e 0x1c294bd 0x1b8dbbc 0x1b8d94e 0x197a705 0x8ae2c0 0x8ae258 0x96f021 0x96f57f 0x96e6e8 0x8ddcef 0x8ddf02 0x8bbd4a 0x8ad698 0x2599df9 0x2599ad0 0x1b13bf5 0x1b13962 0x1b44bb6 0x1b43f44 0x1b43e1b 0x25987e3 0x2598668 0x8aaffc 0x2285 0x2185)
libc++abi.dylib: terminate called throwing an exception
It sounds like your STopLeftMenu is being deallocated too early. The button does not retain its target, so you'll need to keep this object around as long as it needs to respond to the button's messages. If you're not sure how the object is getting deallocated, try debugging with Instruments.
I don't see anything wrong with the code you have shown. I tried it in an existing app of mine and while I had to a) declare a UIButton local variable, b) change the image used for the button and c) comment out the stuff in toggleStormButtons, the method was called every time I tapped the button, no problems.
You don't show your storage for the button. Are you using ARC? Is the button strong? If ARC it should be strong. If not ARC and you are not using a property to assign with a retain, that could cause problems.
What does viewsToRemove do? Looks like an array but it could be something else.
Why don't you use + buttonWithType: and set the frame later?
Related
I have below code to create simple NSButton in a separate function
-(void)myFunction
{
NSButton *btn = [self createButton:#"Button_Name"];
if(some condition )
{
[btn setEditable:YES];
}
}
- (NSButton*)createButton:(NSString *)buttonName
{
NSButton *btn = [[NSButton alloc] initWithFrame:NSMakeRect(20, 0, 20, 20)];
[btn setButtonType:NSSwitchButton];
[btn setImagePosition:NSImageOnly];
[btn setTarget:self];
[btn setTitle: buttonName];
return btn;
}
In my same It is working fine.I am using this code in a Big project.Will It work normally or will cause some problem.Is this a correct way?
Few things I would like to bring in your notice:
You pass buttonName and buttonTitle but never uses it.
You create an object of type NSButton but your object name is against the convention, by reading btnCell someone will expect it to be NSButtonCell.
In the above code I cant see any reference to the newly created button and even you are not adding it to any view. (I hope in your real Big project you are not missing those.)
In my application there is a subclass of NSWindowController. In - (void)awakeFromNib I create an instance of a NSView subclass to create a bottom placed button bar:
self.buttonBar = [[CNButtonBar alloc] initWithSize:NSMakeSize(tableViewRect.size.width-1, 25)];
This CNButtonBar thing has a method to add buttons to itself. I create two of it:
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameAddTemplate]
target:self
action:#selector(btnAccountAddAction:)
alignment:CNBarButtonAlignLeft];
[buttonBar addButtonWithTitle:nil
image:[NSImage imageNamed:NSImageNameRemoveTemplate]
target:self
action:#selector(btnAccountRemoveAction:)
alignment:CNBarButtonAlignLeft];
These two action methods are defined in the same instance of NSViewController where I send the two addButtonWithTitle:... messages.
The methods, used to set the action are defined as followed:
- (void)btnAccountAddAction:(id)sender
{
....
}
- (void)btnAccountRemoveAction:(id)sender
{
....
}
But, it doesn't work. Each time if I click one of these two buttons my application crashes throwing an exception like this one:
-[__NSArrayM btnAccountAddAction:]: unrecognized selector sent to instance 0x1001454e0
Examined this exception is absolutely correct. NSArray doesn't have such a method I want to call. But, from time to time the object that throws this exception is changing. Some times there is a __NSData object, some times a __NSDictionary and so on. It seems that the receiver is anything but my NSWindowController subclass. But the given instance ID 0x1001454e0 is the same my NSWindowController has.
It makes me want to tear my hair out! What's going wrong here...?
Thanks.
UPDATE
I have to say, that both, the CNButtonBar and CNButtonBarButton are completely drawn by code. The complete method of addButtonWithTitle:image:target:action:alignment: is here (remember, this happens in CNButtonBar, a subclass of NSView (should I use NSViewController instead of it?), CNButtonBarButton is a subclass of NSButton):
- (void)addButtonWithTitle:(NSString*)title image:(NSImage*)image target:(id)target action:(SEL)action alignment:(CNBarButtonAlign)align
{
if (self.buttons == nil)
self.buttons = [[NSMutableArray alloc] init];
CNButtonBarButton *button = [[CNButtonBarButton alloc] init];
[self.buttons addObject:button];
button.title = title;
button.image = image;
button.target = target;
button.action = action;
button.align = align;
NSRect buttonRect;
NSSize titleSize = NSMakeSize(0, 0);
if (button.title.length > 0) {
NSMutableParagraphStyle* textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
[textStyle setAlignment: NSCenterTextAlignment];
NSColor *textColor = [[NSColor blackColor] colorWithAlphaComponent:0.9];
NSShadow* textShadow = [[NSShadow alloc] init];
[textShadow setShadowColor: [NSColor whiteColor]];
[textShadow setShadowOffset: NSMakeSize(0, -1)];
[textShadow setShadowBlurRadius: 0];
button.titleTextAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont fontWithName:#"Helvetica Neue" size:11.0], NSFontAttributeName,
textShadow, NSShadowAttributeName,
textColor, NSForegroundColorAttributeName,
textStyle, NSParagraphStyleAttributeName,
nil];
titleSize = [title sizeWithAttributes:button.titleTextAttributes];
buttonRect = NSMakeRect(0, 0, roundf(titleSize.width) + kTextInset * 2, NSHeight(self.frame) - 1);
}
if (button.image != nil) {
NSSize imageSize = [image size];
if (button.title.length == 0) {
buttonRect = NSMakeRect(0, 0, imageSize.width + kImageInset * 2, NSHeight(self.frame) - 1);
} else {
buttonRect = NSMakeRect(0, 0,
(imageSize.width + kImageInset * 2) + (roundf(titleSize.width) + kTextInset),
NSHeight(self.frame) - 1);
}
}
switch (self.align) {
case CNButtonBarAlignNormal: {
switch (button.align) {
case CNButtonBarButtonAlignLeft: {
button.frame = NSMakeRect(offsetLeft, 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetLeft += 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
case CNButtonBarButtonAlignRight: {
button.frame = NSMakeRect(offsetRight - NSWidth(buttonRect), 0, NSWidth(buttonRect), NSHeight(buttonRect));
offsetRight -= 1 * [self.buttons indexOfObject:button] + NSWidth(button.frame);
break;
}
}
break;
}
case CNButtonBarAlignCentered: {
break;
}
}
[self addSubview:button];
}
UPDATE 2
The problem is solved. After some debugging I found out that it must be a problem of ARCs auto retain/release stuff. And I'm right. But the problem was my NSViewController subclass. It was leaking because of making an instance as a local variable (without a strong pointer). Thanks to Sean D., that pointed me to the right way. (-;
Looks like one of two things is happening. The first possibility is that your CNButtonBar object is getting released while the buttons are still around. If the buttons are still there, they'll try to send those selectors to whatever happens to occupy the memory the CNButtonBar used to be in. I'd say make sure it isn't autoreleasing itself anywhere, and that you're not accidentally autoreleasing it in the window controller's -awakeFromNib method. (If you're anything like me, that's the most likely culprit.)
The second possibility is that your -addButtonWithTitle:image:target:action:alignment: method is setting the buttons' actions but not their targets. Make sure your implementation of that method calls -setTarget: as well as -setAction: on the button.
We created button in the init method and we created two Uiimage objects and created Boolean
if(!isHint)
{
[hintBtn setImage:hintBtnImage forState:UIControlStateNormal];
}
else
{
[hintBtn setImage:hintBtnImagex forState:UIControlStateNormal];
}
hintBtn =[[UIButton alloc]initWithFrame:CGRectMake(794, 144, hintBtnImage.size.width, hintBtnImage.size.height)];
[hintBtn setImage:hintBtnImage forState:UIControlStateNormal];
[hintBtn addTarget:self action:#selector(showHint) forControlEvents:UIControlEventTouchUpInside];
When ever user taps the tableview cell we changes the boolean variable and we set the image .like the below code
if(wrongx==1)
{
NSLog(#"the wrong x is %i",wrongx);
isHint = NO;
[hintBtn setImage:hintBtnImage forState:UIControlStateNormal];
}
But when i tap the application first time it is working but second time i am getting the below error
[UIImage retain]: message sent to deallocated instance
Plz reply to my post.Thanks in advance
where you allocated "hintBtnImage" object.I think your trying to access the "hintBtnImage" withoout allocating.
hintBtn =[[UIButton alloc]initWithFrame:CGRectMake(794, 144, hintBtnImage.size.width, hintBtnImage.size.height)];
small code modification needed ,its not related to solve your problem,above line should be like this
hintBtn =[[UIButton alloc]initWithFrame:CGRectMake(794, 144, hintBtnImage.size.width, hintBtnImage.size.height)];
if(!isHint)
{
[hintBtn setImage:hintBtnImage forState:UIControlStateNormal];
}
else
{
[hintBtn setImage:hintBtnImagex forState:UIControlStateNormal];
}
In my app I've got a button which is an instance variable declared in the .h file already.
Now after allocating it an assigning at target to it and actually pressing the button, the app crashes giving me following output in the debugger:
-[__NSCFString handleActionSheet:]: unrecognized selector sent to instance 0x9090330
2012-05-04 17:51:02.646 financeAppV2[2595:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString handleActionSheet:]: unrecognized selector sent to instance 0x9090330'
*** First throw call stack:
(0x13d1022 0x1562cd6 0x13d2cbd 0x1337ed0 0x1337cb2 0x13d2e99 0x1e14e 0x1e0e6 0xc4ade 0xc4fa7 0xc3d8a 0x2dfa1a 0x13a599e 0x133c640 0x13084c6 0x1307d84 0x1307c9b 0x12ba7d8 0x12ba88a 0x1b626 0x29dd 0x2945)
terminate called throwing an exceptionCurrent language: auto; currently objective-c
My code looks like following:
saveButton=[UIButton buttonWithType:UIButtonTypeCustom];
[saveButton setBackgroundImage:[UIImage imageNamed:#"intervalbutton"] forState:UIControlStateNormal];
[saveButton setBackgroundImage:[UIImage imageNamed:#"intervalbuttonpressed"] forState:UIControlStateHighlighted];
saveButton.alpha=.8;
saveButton.frame= frame;
UILabel* label=[[UILabel alloc]initWithFrame:CGRectMake(0, 2, saveButton.frame.size.width, 21)];
[saveButton addSubview:label];
[saveButton addTarget:self action:#selector(handleActionSheet:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:saveButton];
-(void)handleActionSheet:(id)sender{
NSLog(#"working");
}
Any ideas why the app could be crashing?
Without seeing the rest of your code it's difficult to be specific, but self is not correctly being retained.
You set up your button correctly (as far as I can see) and point the target to self. Unfortunately, by the time you press the button self has gone out of scope and the same memory is used by an NSString. iOS gets surprised when you send a string the handleActionSheet: message.
You're sending a message named initAllIVars: to an __NSCFString object (likely an NSString).
Do a search for that message and try to figure out why the object receiving the message is an NSString.
Just tested your code and it works. Maybe the frame it's not properly set
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIButton *saveButton = [[UIButton alloc] init];
saveButton=[UIButton buttonWithType:UIButtonTypeCustom];
[saveButton setBackgroundImage:[UIImage imageNamed:#"intervalbutton"] forState:UIControlStateNormal];
[saveButton setBackgroundImage:[UIImage imageNamed:#"intervalbuttonpressed"] forState:UIControlStateHighlighted];
saveButton.alpha=.8;
saveButton.frame= CGRectMake(5, 5, 200, 40);
UILabel* label=[[UILabel alloc]initWithFrame:CGRectMake(0, 2, saveButton.frame.size.width, 21)];
label.text = #"Hello";
[saveButton addSubview:label];
[saveButton addTarget:self action:#selector(handleActionSheet:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:saveButton];
}
-(void)handleActionSheet:(id)sender{
NSLog(#"working");
}
I am writing an app for iPad. In this app I have to use a Share button on the navigation bar on all the screens. I have applied the Share button on my Home class. I wrote the following code to apply button on the navigation bar:
CGRect frame5 = CGRectMake(835.0, 0.0, 40.0, 40.0);
UIImage *buttonImage5 = [UIImage imageNamed:#"ShareIcon.png"];
UIButton *ShareButton = [UIButton buttonWithType:UIButtonTypeCustom];
ShareButton.frame = frame5;
[ShareButton setBackgroundImage:buttonImage5 forState:UIControlStateNormal];
ShareButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
ShareButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[ShareButton addTarget:self action:#selector(actionSheet) forControlEvents:UIControlEventTouchUpInside];
[ShareButton setBackgroundColor:[UIColor clearColor]];
[self.navigationController.navigationBar addSubview:ShareButton];
The share button is used to Email or print a screen. For this purpose I have used UIActionSheet. I wrote the following method to apply UIActionSheet:
-(void)actionSheet:(id)sender
{
UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Email", #"Print", nil];
[popup showFromRect:CGRectMake(720.0, 3.0, 40.0, 40.0) inView:[self view] animated:TRUE];
[popup showFromBarButtonItem:(UIBarButtonItem *)sender animated:TRUE];
[popup release];
}
This method is applied on the Share button. When I build and run my app, there is no error or warning, i.e. the build is successful. But when I click on the share button the application crashes and it shows following in the debugger console window:
[Session started at 2011-10-21 21:26:58 +0530.]
2011-10-21 21:27:03.895 NewBostonEndoscopy[1351:207] -[Home actsht]: unrecognized selector sent to instance 0x6227010
2011-10-21 21:27:03.898 NewBostonEndoscopy[1351:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Home actsht]: unrecognized selector sent to instance 0x6227010'
I am not getting why this is happening. Any guess?
Any help will be highly appreciated.
Thanks and regards
Prateek
You are showing the popup twice, I'm not sure if this is the reason for you crash, but try removing the line
[popup showFromRect:CGRectMake(720.0, 3.0, 40.0, 40.0) inView:[self view] animated:TRUE];
[ShareButton addTarget:self action:#selector(actionSheet) forControlEvents:UIControlEventTouchUpInside];
change to:
[ShareButton addTarget:self action:#selector(actionSheet:) forControlEvents:UIControlEventTouchUpInside];
The missing ':' after actionSheet is the culprit.
As the log says, you are calling -actsht on Home, which apparently does not implement a method with this name. Try searching your document for actsht and see what you meant.
Probably, you used it in a UIBarButtonItem initializer, e.g. -initWithBarButtonSystemItem:target:action:, and specified a selector for action that does not exist. The compiler would not notice this.