setting target for a UIButton which was made in IB - interface-builder

I have a UIView with a bunch of buttons in it (something like 200 of them)...
The view was set up in IB so I would have to manually wire every button with a single handler...
I'm trying to traverse the subviews of the view, looking for buttons and then set the button's target programmatically... which results in a crash (I get the compile warning «UIButton may not respond to addTarget...»).
this is the loop:
for(UIButton *aButton in self.view.subviews){
if([aButton isKindOfClass:[UIButton class]]){
[aButton addTarget:self selector:#selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
}
I can access some of the properties of the button, like visibility and title... but not the action?
Any help greatly appreciated...!

wow - it was actually pretty simple - the guys over at devforums.apple.com gave me the hint...
for(UIButton *aButton in self.view.subviews){
if([aButton isKindOfClass:[UIButton class]]){
[aButton addTarget:self action:#selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
}
Can you spot the difference? ;)

You could use respondsTo or some other variant to avoid getting the error. This would ensure you can set the action for aButton.
However, if you are looping over all these buttons anyway, why not just build them programmatically? Are they design heavy?

you should mark your answer as correct.
But just in case anybody else comes:
It should be:
addTarget:self action:#selector(buttonClick:)
instead of:
addTarget:self selector:#selector(buttonClick:)

Related

UISwitch doesn't work on Google Maps SDK for iOS?

I'm trying to create a UISwitch laid on mapView_ of Google Maps for my iOS app, but it seems not to work.
In details, I first followed instruction from google, created mapView_, then made it my viewcontroller's view:
self.view = mapView_;
Then, I created an UISwitch programmatically and added it as a subview:
mySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(50, 360, 0, 0)];
[mySwitch setBackgroundColor:[UIColor clearColor]];
[mySwitch addTarget:self
action:#selector(changeSwitch:)
forControlEvents:UIControlEventTouchDown];
[mapView_ addSubview:mySwitch];
But when I touched the switch both in simulator and device, it didn't change its state from ON->OFF or OFF->ON. I even tried different UIControlEvent, such as UIControlEventValueChanged but it didn't work. To make sure that the code should work, I tried on a normal view of a normal test viewcontroller (that means, not using google maps), it worked fine!
Does anyone have any comment about this issue?
Thanks heaps!
You can work around this issue by adding both the UISwitch and the GMSMapView to a single UIView parent, instead of adding the UISwitch as a child of a GMSMapView. Yes, this means you need to position both the GMSMapView and the UISwitch.

NSPopover switch view

I have a popover menulet and it's contentViewController is some NSViewController. Everything fine here. The problem that I have is that I really don't understand how to change the View. I wanna load another view, and this is what I tried:
popover = [[NextViewController alloc]initWithNibName:#"NextViewController" bundle:nil];
[self.view addSubview:[popover view]];
And this works, new view is shown - but if I click on any button on that view I get error: unrecognized selector sent to instance. Why am I getting this error? Why this new view is not responding?
Please help me understand what I need to do, how to change the view on NSPopover?
I've managed to solve my problem, It turn out to be quite easy:
[self.view setSubviews:[NSArray array]]; //remove all previous subviews
[self.view addSubview:[popover view]];

Deselect text in an NSTextView programmatically?

I am using the following code to deselect an NSTextView, as suggested here. Unfortunately, nothing at all happens. I have tried what I know to debug it, but everything seems to be working correctly, but it doesn't affect the NSTextView.
The code:
// Sets the scrolling bounds and behavior. This might be useful, but I don't know
[[textView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[[textView textContainer] setWidthTracksTextView:FALSE];
// The code for deselecting, beginning by making sure it is actually selected (for testing only, as strange as it is)
[textView setSelectable:TRUE];
[textView setDelegate:self];
[_window makeFirstResponder:textView];
NSText *fieldEditor = [_window fieldEditor:TRUE forObject:textView];
[fieldEditor setSelectedRange:NSMakeRange([[fieldEditor string] length],0)];
[fieldEditor setNeedsDisplay:YES];
Any ideas about why this doesn't work? I am sure my outlets are set properly because I can manipulate other things, such as it's string value.
I'm not sure NSTextViews use the field editor, have you tried calling the method on the text view directly?
[textView setSelectedRange:NSMakeRange(textView.string.length, 0)];
The range location can be adjusted to move the cursor to the start or end, for example. You may also want to check to make sure something is actually selected before calling this method.
EDIT:
From your comment it sounds like you just want it to resign first responder. You can do that manually by calling [textView.window makeFirstResponder:nil];
This almost worked for me;
[textView.window makeFirstResponder:nil];
However, I had trouble setting the first responder to nil. If I set it to any other view it seems to do as you want.
[textView.window makeFirstResponder:[textView superview]];
Tested in 10.7 Lion.
I've using this approach and it works perfectly:
[textView setSelectedRange:NSMakeRange(0, 0)];
As suggested earlier setSelectedRange: will do the trick BUT!
If your goal is to completely remove the selection and the cursor too, f.e. if you subclass an NSTextView to support similar behavior like NSTextEdit has in case of firstResponder status change you should write:
- (BOOL)resignFirstResponder
{
// Invalid range location will remove cursor too
[self setSelectedRange:NSMakeRange(NSUIntegerMax, 0)];
return YES;
}
//------------------------------------------------------------------------------
- (BOOL)becomeFirstResponder
{
[self setSelectedRange:NSMakeRange(0, self.string.length)];
return YES;
}
//------------------------------------------------------------------------------
[textView setDelegate:self];
I have a feeling that one of your delegate methods is preventing things from happening. See the documentation under "Managing the selection".
As a temporary solution, just until somebody comes up with a better idea, setHidden: can be used. I am sure this is not as efficient as is recommended, but it deselects the NSTextView.
Simply toggle it twice, like so:
[textView setHidden:TRUE];
[textView setHidden:FALSE];

Creating a checkbox programmatically using Cocoa

I need to create a checkbox programmatically in Cocoa and when I try and make a button with buttonType set to NSSwitchButton it displays the title, but does not show the button as a checkbox. I think I am missing something but I can't find any resources about making things like checkboxes without using the Xcode GUI.
The question is a little old so you've probably already figured it out, but I found it while searching for this exact thing. Alex danced around the solution without actually providing it. So here, for Google and all mankind: how to programmatically create a checkbox in Cocoa.
NSRect frame;
frame.size.width = frame.size.height = 18;
NSButton *myCheckBox = [[NSButton alloc] initWithFrame:frame];
[myCheckBox setButtonType:NSSwitchButton];
[myCheckBox setBezelStyle:0]; // This is unnecessary. I include it to show that checkboxes don't have a bezel style.
[myView addSubview:myCheckBox];
I don't think buttons are bezeled by default when created programmatically. Check the setBezelStyle: method, as well as setBezeled: and setBordered:. One of those should give you what you want.
I had failed to execute setImagePosition properly and this was causing the checkbox not to display.

NSTextView not refreshed properly on scrolling

I have a NSTextView with a sizeable quantity of text. Whenever I scroll however, the view isn't updated properly. There are some artifacts that remain at the top or the bottom of the view. It appears that the view doesn't refresh itself often enough. If I scroll very slowly the view updates correctly though. If I add a border to the view everything works perfectly, borderless view is the one that has a problem. Here's a link to a screenshot:
Thanks
Have you set the setDrawsBackground and copiesOnScroll propertes for either the NSScrollView or the NSClipView?
The first thing I would suggest is turning off the "draws background" property of the NSScrollView:
[myScrollView setDrawsBackground:NO];
Note that this should be set on the NSScrollView, and not on the embedded NSClipView.
The following excerpt from the documentation may be relevant:
If your NSScrollView encloses an NSClipView sending a setDrawsBackground: message with a parameter of NO to the NSScrollView has the added effect of sending the NSClipView a setCopiesOnScroll: message with a parameter of NO. The side effect of sending the setDrawsBackground: message directly to the NSClipView instead would be the appearance of “trails” (vestiges of previous drawing) in the document view as it is scrolled.
Looks like the text field isn't even in the scrolling-area... Are you sure something isnt overlapping it?
I had a similar trouble - artifacts develop when the NSTextView is embedded in another scrollview (ie. a NSTableView).
I actually turned on the setdrawsbackground, and then added a nice color to make it disappear again.
-(void)awakeFromNib{
NSScrollView *scroll = [self enclosingScrollView];
[scroll setBorderType:NSNoBorder];
[scroll setDrawsBackground:YES];
[scroll setBackgroundColor:[NSColor windowBackgroundColor]];
}
This in combination with a scrollWheel event let me use the NSTextView in a NSTableView.
-(void)scrollWheel:(NSEvent *)theEvent{
NSScrollView *scroll = [self enclosingScrollView];
[[scroll superview] scrollWheel:theEvent];
}
I had the same trouble some time ago. I don't remember how I solved it.
Try to place the NSTextView to another view if the superview is a custom view. Just to see what will happen.

Resources