UISegmentedControl and registering callback without XIB - iphone

I have added a UISegmented control as follows (this seems to work just fine, but let me know if this is a bad practice):
mapType = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects: #"Map", #"Satelitte", #"Hybrid", nil]];
[_mapView addSubview:mapType];
Then I have a method that I would like to be called when this UISegmentedControl is changed, however, I cannot set the delegate or anything in the interface builder because I am doing this programmatically.
- (void)segmentedChangedType {
// some code here
}
How can I connect these? Thanks in advance for any help!
If the only solution is to use XIB, then I can do that, but would like to know how to do this if it's possible.

OK, figured it out, you add this:
[mapType addTarget:self action:#selector(changeType) forControlEvents:UIControlEventValueChanged];

Related

UIBarButtonItem created using initWithCustomView doesn't trigger action

I'm updating some old code, and to make more room in a toolbar, I'm converting the Buttons from test to images. An example of the new and old code in loadView is this:
// New code, doesn't work.
UIButton *toggleKeyboardBtn = [UIButton buttonWithType:UIButtonTypeCustom];
toggleKeyboardBtn.bounds = CGRectMake( 0, 0, showKeyboardImage.size.width, showKeyboardImage.size.height );
[toggleKeyboardBtn setImage:showKeyboardImage forState:UIControlStateNormal];
UIBarButtonItem *toggleKeyboardItem = [[UIBarButtonItem alloc] initWithCustomView:toggleKeyboardBtn];
[toggleKeyboardItem setTarget:self];
[toggleKeyboardItem setAction:#selector(toggleKeyboard:)];
// Original code, works jut fine.
UIBarButtonItem *setupItem = [[[UIBarButtonItem alloc] initWithTitle:#"Setup" style:UIBarButtonItemStyleBordered target:[UIApplication sharedApplication].delegate action:#selector(showSetupView:)] autorelease];
My new code is copied from Cannot set action on UIBarButtonItem, and I'm fairly certain that I'm not making their mistake since my text button is working just fine.
showSetupView() is in my AppController.m file, and the setup screen appears and disappears as the button is pressed.
toggleKeyboard(), OTOH, is in the same file as the loadView() routine, and currently consists of this code:
//- (void)toggleKeyboard {
- (IBAction)toggleKeyboard:(id)sender {
NSLog(#"Entering toggleKeyboard()...");
hiddenKeyboard = !hiddenKeyboard;
[self prepareToolbarsAndStatusbar];
}
Needless to say, although I see the button-press animation, I never see the NSLog message. And one last observation, made by accident. Changing the setAction selector to this:
[toggleKeyboardItem setAction:#selector(noSuchRoutine:)];
compiles cleanly, possibly indicating that my routine name is being ignored for some reason.
Anyone have any ideas? Thanks.
I found the answer! In button action not responding iphone, it's said that the action and target need to be set on the UIButton, not the UIBarButtonItem. I don't know if that's new with the latest version of Xcode, but I guess it is since other questions (such as the one I mention above) use a different technique. Here's my new code:
UIButton *toggleKeyboardButton = [UIButton buttonWithType:UIButtonTypeCustom];
toggleKeyboardButton.bounds = CGRectMake( 0, 0, keyboardAddImage.size.width, keyboardAddImage.size.height );
[toggleKeyboardButton setImage:keyboardAddImage forState:UIControlStateNormal];
[toggleKeyboardButton addTarget:self action:#selector(toggleKeyboard) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *toggleKeyboardItem = [[UIBarButtonItem alloc] initWithCustomView:toggleKeyboardButton];
//[toggleKeyboardItem setTarget:self];
//[toggleKeyboardItem setAction:#selector(toggleKeyboard:)];
Though its too late, but for future references, I would like to quote apple docs for the method,
- (instancetype)initWithCustomView:(UIView *)customView;
The bar button item created by this method does not call
the action method of its target in response to user interactions.
Instead, the bar button item expects the specified custom view to
handle any user interactions and provide an appropriate response.
Did you try
-(void)toggleKeyboard
and
[toggleKeyboardItem setAction:#selector(toggleKeyboard)]; without :
and it made any difference? Is the method declared in the interface file?

add custom switch to iphone view

I am using the following code to create a custom switch:
UISegmentedControl* switchView=[[UISegmentedControl alloc]
initWithItems:[[NSMutableArray alloc] initWithObjects:#"On",#"Off",nil]];
[switchView setFrame:CGRectMake(20,365,140,28)];
switchView.selectedSegmentIndex=0;
switchView.segmentedControlStyle=UISegmentedControlStyleBar;
[switchView setImage:[UIImage imageNamed:#"onSelected.png"] forSegmentAtIndex:0];
[switchView setImage:[UIImage imageNamed:#"off.png"] forSegmentAtIndex:1];
[switchView addTarget:self action:#selector(checkOnOffState:) forControlEvents:UIControlEventValueChanged];
I would now like to add this control to one of my screens (I believe the correct term is ViewController?). How would I do this in Xcode 4.3?
I looked at a few other posts and was not able to find anything that works. For example, How do I add a custom view to iPhone app's UI? suggested something along the lines of
[[myVC view] addSubview:myView];
and How to customize UISwitch button in iphone? suggested
self.navigationItem.titleView=switchView;
If possible, could you also explain why these approaches did not work? Thanks.
You need to create a class for your switch which is subclass of your UISegmentControl ,
Else you can add this code in your vc directly as well.
Add this code in its initWithFrame method
and then use it in your VC
-(void)viewDidLoad{
urCustomSwitch = [urCustomSwitch alloc] initWithFrame:CGRectMake(20,365,140,28)];
[self.view addSubview:urCustomSwitch];
}
This shall serve your purpose if you are to create custom reusable class.
If you add this switch control i.e. UISegmentedControl in InterfaceBuilder (.xib file)
This task will be much easier for you.

UISegmentedControl and adding targets

I'm sure this is an easy one for someone out there. I have a UISegmentedControl which I am using as a button (so as not to have to use the nasty default button) and I am having trouble getting the target to work....code as follows
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//read.buttonType = UIBarStyleBlackOpaque;
UISegmentedControl* read = [[[UISegmentedControl alloc] initWithFrame:CGRectMake(5, 50, 310, 54)] autorelease];
[read insertSegmentWithTitle:#"Read" atIndex:0 animated:NO];
read.tintColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.9 alpha:1];
read.segmentedControlStyle = UISegmentedControlStyleBar;
[read addTarget:self action:#selector(changeFilter:sender:) forControlEvents:UIControlEventTouchUpInside];
[read setTag:1];
[self.view addSubview:read];
}
and then
-(void)changeFilter:(id)sender{
}
for some reason, clicking on the UISegmentedControl does not fire the target method.
As an addendum, is there a simpler way to make nice looking UIButtons? I don't have access to Photoshop at work (although I do have gimp installed), so a way which doesn't involve image making would be good. I can't believe that apple didn't supply nice looking UIButtons in the UI, it seems such a fundamental thing to need?
Anyway, thanks for the help mis amigos.
thanks for the answers...I've tried the fix but it still doesn't fire
I now have
[read addTarget:self action:#selector(changeFilter:) forControlEvents:UIControlEventTouchUpInside];
then
#interface
-(void)changeFilter:(id)sender;
and
#implementation
-(void)changeFilter:(id)sender{}
Note that the method is in the same class as the UISegmentedControl. Maybe I should just try using the Glass button API which was suggested, but my boss hates me using third party libraries if there is a way of avoiding it!
The selector is wrong. It should be, action:#selector(changeFilter:), And change the event to forControlEvents:UIControlEventValueChanged, as UISegmentedControl doesn't send any actions for UIControlEventTouchUpInside event.
.h file u forgot to put this
-(void)changeFilter:(id)sender;
then
change this
[read addTarget:self action:#selector(changeFilter:sender:) forControlEvents:UIControlEventTouchUpInside];
To
[read addTarget:self action:#selector(changeFilter:) forControlEvents:UIControlEventValueChanged];
The action will automatically send the sender so just try #selector(changeFilter:).
As for your second question, ios5 will help you out there... but I can't say much about that yet. For now, you can use some uibutton classes that people have made to easily make some good looking buttons. Here's one:
http://hboon.com/glass-buttons-in-iphone-apps-without-using-image-files/

How to get keyboard with Next, Previous and Done Button?

I want to have a keyboard which has a Next,Previous and Done button on top of it.
I have seen that in many apps.
Especially where there are forms to be filled.
I want to achieve something similar to above keyboard
How can I get that?
You'll find the answer on this other post.
I checked the iOS Library and the inputAccessoryView of a UITextField is exactly what you're looking for !
Hope this helps !
I just created a class called BSKeyboardControls which makes it very easy to add the controls to a keyboard. The class, instructions and example code can be found here at GitHub.
The controls works for text fields and text views and are optimized for both iPhone and iPad.
-(BOOL)textFieldShouldBeginEditing: (UITextField *)textField
{
UIToolbar * keyboardToolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
keyboardToolBar.barStyle = UIBarStyleDefault;
[keyboardToolBar setItems: [NSArray arrayWithObjects:
[[UIBarButtonItem alloc]initWithTitle:#"Previous" style:UIBarButtonItemStyleBordered target:self action:#selector(previousTextField)],
[[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleBordered target:self action:#selector(nextTextField)],
[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(resignKeyboard)],
nil]];
textField.inputAccessoryView = keyboardToolBar;
}
- (void)nextTextField {
if (textField1) {
[textField1 resignFirstResponder];
[textField2 becomeFirstResponder];
}
}
-(void)previousTextField
{
if (textField2) {
[textField2 resignFirstResponder];
[textField1 becomeFirstResponder];
}
}
-(void)resignKeyboard {
[textField1 resignFirstResponder];
[textField2 resignFirstResponder];
}
I have a utility class that basically does this for you.
https://github.com/kalvish21/CustomKeyboard
The idea is very simple. You have to add an accessory tool bar with bar button items on it. There's a delegate which defines where what that button will do.
https://github.com/hackiftekhar/IQKeyboardManager
This is the best keyboard handler I have seen so far. Very excellent way to manage Text inputs.
Some of its features
1) ZERO LINE OF CODE
2) Works Automatically
3) No More UIScrollView
4) No More Subclasses
5) No More Manual Work
6) No More #imports
This is a custom control which is placed directly above the keyboard. I think a UIToolbar can be used for that.
Previous and next passes around the firstResponder of the textFields and Done will do the resign as well as hide the toolbar.
To match the keyboard animation have a look at this code I found or at SO: "What is the iPhone's default keyboard animation rate?"
I have created a repository with an implementation of this feature that works on iPhone/iPad in all orientations and highly customizable.
As mentioned in other answers, it's the inputAccessoryView that you're looking for.
I would like to add an alternative way here, by using this cocoapods:
pod 'UITextField-Navigation'
All UITextFields will have two additional properties: nextTextField and previousTextField. You can then simply connect the nextTextField in the Interface Builder and the Previous, Next and Done buttons are added automatically for you, all functional, no more code is needed, no subclassing.
You can also customize the UI, add more buttons, etc as you want to.

Hide UIToolbar UIBarButtonItems

I have a UIToolbar that I set up using IB with three buttons, left, middle and right. In some situations I would like to not display the middle button. Does anybody know of a way to hide a specific button on inside a UIToolBar? There is no hide property, all I can find is setEnable but this still leaves the button causing users to wonder what its purpose is. I would like to only display it in situations that it actually has a use.
Thanks in advance!
Reset the items:
-(void)setItems:(NSArray *)items animated:(BOOL)animated
You can get the current items using the items property, then just remove the one you don't want to show and pass in the new NSArray.
As you can see, you can also animate it to make it clear to the user.
Rather than guessing at the index, I added an IBOutlet for the UIBarButtonItem and then removed it by name:
NSMutableArray *toolBarButtons = [self._toolbar.items mutableCopy];
[toolBarButtons removeObject:self._selectButton]; // right button
[self._toolbar setItems:toolBarButtons];
And of course it helps to connect the outlets in the designer :)
This is how i did it.. too much headache but its the best i could come up with :
NSArray *toolBarArray = toolBar.items;
NSMutableArray *newToolBarArray = [NSMutableArray arrayWithArray:toolBarArray];
[newToolBarArray removeObjectAtIndex:2];
[newToolBarArray removeObjectAtIndex:1];
//remove whatever buttons you want to.
NSArray *finalTabBarArray =[[NSArray alloc] initWithObjects:newToolBarArray, nil];
[toolBar setItems:[finalTabBarArray objectAtIndex:0] animated:NO];
I know it is quite old thread for but those who look this page for solution, here you go :
With iOS7, you can use this approach to show/hide your toolbar button :
if(// your code Condition)
{ self.toolbarBtn1.enabled = YES;
self.toolbarBtn1.tintColor = nil; }
else
{ self.toolbarBtn1.enabled = NO;
self.toolbarBtn1.tintColor = [UIColor clearColor]; }
This does not work here because the array you are sending with setItem is not what the function expects.
I had to replace the line:
NSArray *finalTabBarArray = [[NSArray alloc] initWithObjects:newToolBarArray, nil];
with this one:
NSArray *finalTabBarArray = [newToolBarArray copy];
Then it works perfectly.
Mohit's answer is one that I have used, but you dont need to specifically make it a NSArray that the toolbar sets. You can just set the array of items as a NSMutableArray. No real advantage that I am aware off but its a few lines less code. And that way you can take the array and move about UIButton objects as you would any other array with objects and then just reset the toolbar with that mutable array.
[newToolBarArray removeObjectAtIndex:2];
[newToolBarArray removeObjectAtIndex:1];
[toolBar setItems:newToolBarArray];