I have subclassed the UIToolbar to make it easier to implement a safari next, previous, done sort of thing.
It all worked fine when i was adding it directly (ie not subclassing) but now that i am, it crashes every time i click one of the buttons with
-[keyboardToolBar hideKeyboard:]: unrecognized selector sent to instance
This is the first time i have attempted to subclass something so im not sure if i have done something the wrong way.
Code for the subclass
#interface keyboardToolBar : UIToolbar {
UIToolbar *keyboard;
UIBarItem *previous;
UIBarItem *next;
UIBarItem *done;
}
#property (nonatomic, retain) UIToolbar *keyboard;
#property (nonatomic, retain) UIBarItem *previous;
#property (nonatomic, retain) UIBarItem *next;
#property (nonatomic, retain) UIBarItem *done;
-(void)previousField;
-(void)nextField;
-(void)hideKeyboard;
#end
#import "keyboardToolBar.h"
#implementation keyboardToolBar
#synthesize keyboard, previous, done, next;
-(UIToolbar*)initWithFrame:(CGRect)frame{
//Create a new toolbar
keyboard = [[UIToolbar alloc]initWithFrame:frame];
//Create all the buttons and point them to methods
UIBarButtonItem *previousButton = [[UIBarButtonItem alloc] initWithTitle:#"Previous"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(previousField:)];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:#"Next"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(nextField:)];
UIBarButtonItem *filler = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(hideKeyboard:)];
//Set the width of both of the buttons to make it look pritty
previousButton.width = 70.0f;
nextButton.width = 70.0f;
self.previous = previousButton;
self.next = nextButton;
self.done = doneButton;
//Add the buttons to the toolbar
[keyboard setItems:[[[NSArray alloc] initWithObjects:self.previous, self.next, filler, self.done, nil] autorelease]];
//Release the buttons
[previous release];
[next release];
[filler release];
[done release];
//return the shiny new toolbar
return keyboard;
}
-(void)previousField{
}
-(void)nextField{
}
-(void)hideKeyboard{
NSLog(#"hello");
}
#end
and is called using UIToolbar *keyboard = [[keyboardToolBar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 50)];
I have tried everything i can think of but still get the same error. Im sure i am just not retaining something somewhere of pointing the buttons to the wrong place but any help would be muchly appreciated
Thanks
Darc
The problem here is that your buttons are calling functions that take an input, but your functions do not take an input:
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(hideKeyboard:)];
This means that there must be a method hideKeyboard:(id)sender. But you have
-(void)hideKeyboard{
NSLog(#"hello");
}
Either add the input to the function or remove the : from the selector call.
you effectively wrote it as a class method, here is a little bit better version, because of memory management issues etc.
-(UIToolbar*)initWithFrame:(CGRect)frame{
//Create a new toolbar
if ((self = [super initWithFrame:frame]))
//Create all the buttons and point them to methods
previous = [[UIBarButtonItem alloc] initWithTitle:#"Previous" style:UIBarButtonItemStyleBordered target:self action:#selector(previousField:)];
next = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleBordered target:self action:#selector(nextField:)];
UIBarButtonItem *filler = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
done = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleBordered target:self action:#selector(hideKeyboard:)];
//Set the width of both of the buttons to make it look pritty
previous.width = 70.0f;
next.width = 70.0f;
//Add the buttons to the toolbar
[keyboard setItems:[[[NSArray alloc] initWithObjects:previous, next, filler, done, nil] autorelease]];
//Release the buttons
[previous release];
[next release];
[filler release];
[done release];
//return the shiny new toolbar
return self;
}
also fix your methods to be either
#selector(someAction) to match -(void)someAction;
or #selector(someAction:) to match -(void)someAction:(id)sender;
also no reason to keep a reference to UIToolBar * keyboard, because you want that to be self.
actually probably no reason to keep references to the buttons at all unless you will need to change their titles or action/target pairs later.
You (or something you're doing) is calling hideKeyboard: (note the colon, indicating that the method has one argument.). However, the hideKeyboard method you've implemented, doesn't take any arguments.
Most likely, hideKeyboard should be changed to:
- (void)hideKeyboard:(id)sender {
NSLog(#"hello");
}
As an aside, the usual style for class names is capitalized, so your subclass should be KeyboardToolBar (and I'd also recommend keeping the same camel case as Apple's classes, so KeyboardToolbar would be best).
Related
I am new at iOS Development.I Have UINavigationController as rootviewcontroller for UIWindow.In the subclass i added UITabbarController programatically.I given default Tabbarcontroller selection as first controller. Here i am trying to add 3 buttons to the navigationbar .
Can any send me the corrent code.
Thanks In advance
To add more than one button on the left or the right side you have to call one of the following methods:
- (void)setRightBarButtonItems:(NSArray *)items animated:(BOOL)animated
- (void)setLeftBarButtonItems:(NSArray *)items animated:(BOOL)animated
The array items contains instances of the UIBarButtonItem class. You can instantiate them like this
UIBarButtonItem *FirstButton = [[UIBarButtonItem alloc]
initWithTitle:#"Title"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(buttonTapped:)];
Then you have to implement the selector buttonTapped: which is called when the button has been tapped.
-(void)buttonTapped:(UIBarButtonItem *)button
{
// do the things that should happen when the button is pressed
}
If you don't want to get them on the left or right side it is also possible to create a UIView by yourself containing the buttons and set the view to be the titleView of the UINavigationItem. This effect is similar to the buttons in the Facebook App
[self.navigationItem setTitleView:yourView];
Here is simple code for add UIButton on UINavigationBar
In Following code you can add Button With FlexibleSpace
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
[flexSpace release];
UIBarButtonItem *btnFirst = [[UIBarButtonItem alloc] initWithTitle:#"First" style:UIBarButtonItemStyleBordered target:self action:#selector(FirstTapped:)];
[barItems addObject: btnFirst];
UIBarButtonItem *btnSecond = [[UIBarButtonItem alloc] initWithTitle:#"Second" style:UIBarButtonItemStyleBordered target:self action:#selector(SecondTapped:)];
[barItems addObject:btnSecond];
UIBarButtonItem *btnThird = [[UIBarButtonItem alloc] initWithTitle:#"Third" style:UIBarButtonItemStyleBordered target:self action:#selector(ThirdTapped:)];
[barItems addObject: btnThird];
self.navigationItem.rightBarButtonItems = barItems;
Button Related Methods
-(void) FirstTapped:(UIBarButtonItem *)sender{
//perform your action
}
-(void) SecondTapped:(UIBarButtonItem *)sender{
//perform your action
}
-(void) ThirdTapped:(UIBarButtonItem *)sender{
//perform your action
}
NOTE : self.navigationItem.rightBarButtonItems Works only in iOS 5 or Latter.
UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
// here is custom button setup //
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton];
[self.navigationItem setLeftBarButtonItem:item animated:YES];
Here's what I need.
I have a free version and a paid version of my app. When the paid version loads, I need 3 UIBarButtons on my UIToolBar. When the Free version loads I need 4 UIBarButtons. On the far right barButton, I need the tint Blue, while the rest are default black. And I'm assuming the flexible space between them to even them out. I've tried doing this through IB, but I can't seem to get it to work with the spacing correct. As you can see, the bottom toolbar with 3 buttons are not spaced evenly with the toolbar. (I would like to do this programmatically)
#ifdef LITE_VERSION
#else
[buyButton removeFromSuperview];
#endif
UIToolbar* toolbar = [[UIToolbar alloc]
initWithFrame:CGRectMake(0, 0, 320, 45)];
[toolbar setBarStyle: UIBarStyleBlackOpaque];
// create an array for the buttons
NSMutableArray* BarbuttonsArray = [[NSMutableArray alloc] initWithCapacity:5];
// create a clearAll button
UIBarButtonItem * clearAllButton = [[UIBarButtonItem alloc] initWithTitle:#"Clear All"
style:UIBarButtonItemStylePlain
target:self
action:#selector(clearAllAction:)];
clearAllButton.style = UIBarButtonItemStyleBordered;
[BarbuttonsArray addObject:clearAllButton];
[clearAllButton release];
// create a calculate button
UIBarButtonItem *calculateButton = [[UIBarButtonItem alloc]initWithTitle:#"Calculate"
style:UIBarButtonItemStylePlain
target:self
action:#selector(calculateButton:)];
calculateButton.style = UIBarButtonItemStyleBordered;
[BarbuttonsArray addObject:calculateButton];
[calculateButton release];
// create a settingButton
UIBarButtonItem *settingButton = [[UIBarButtonItem alloc]initWithTitle:#"Setting"
style:UIBarButtonItemStylePlain
target:self
action:#selector(settingButton:)];
settingButton.style = UIBarButtonItemStyleBordered;
[BarbuttonsArray addObject:settingButton];
[settingButton release];
// create a buyNowButton
UIBarButtonItem *buyNowButton = [[UIBarButtonItem alloc]initWithTitle:#"Buy Now"
style:UIBarButtonItemStylePlain
target:self
action:#selector(buyNowButton:)];
buyNowButton.style = UIBarButtonItemStyleBordered;
[BarbuttonsArray addObject:buyNowButton];
[buyNowButton release];
// put the BarbuttonsArray in the toolbar and release them
[toolbar setItems:BarbuttonsArray animated:NO];
[BarbuttonsArray release];
// place the toolbar into the navigation bar
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
[toolbar release];
//before using these lines of code you have to alloc and make the property of UINavigationController in your appDelegate
Try to use this may help you
First add buy button on your toolbar. bind and synthesize.
if(AppPaid) {
NSMutableArray *items = [YourToolBar.items mutableCopy];
[items removeObject:yourBuyButton];
YourToolBar.items = items;
[items release];
}
Add the buy button to your toolbar by default, and tag it with some unique value (say -1), and then at runtime you can remove it from the toolbar like so:
#ifdef LITE_VERSION
//Dont need to do anything, view is set up as lite version by default
#else
NSArray *elements = toolBar.items;
NSMutableArray *newElements = [[NSMutableArray alloc] initWithCapacity:[elements count]];
for ( UIBarItem *item in elements )
{
if ( item.tag != -1 )
{
//Item is not the buy button, add it back to the array
[newElements addObject:item];
}
}
[toolBar setItems:newElements];
#endif
This is some code I use in one of my apps already to replace an item that is tagged in IB with -1 with a specific button at runtime, depending on which view is on display
IBOutlet UITabBarItem * item1;
like this create 4 items... give link to your xib so that we can hide required tabbarItem when ever you want... I hope this will help
In iOS5 we have leftBarButtonItems that we can set to a navigation bar, how can I do this for pre-iOS 5? I basically have an array of UIBarButtonItem that I wanted to set the bar to.
You can build own bar, and add it as left button:
UIBarButtonItem *firstButton = [[UIBarButtonItem alloc] initWithTitle:#"First" style:UIBarButtonItemStyleBordered target:self action:#selector(firstButtonAction:)];
UIBarButtonItem *secondButton = [[UIBarButtonItem alloc] initWithTitle:#"Second" style:UIBarButtonItemStyleBordered target:self action:#selector(secondButtonAction:)];
UIToolbarTransparent *toolbar = [UIToolbarTransparent new];
[toolbar setFrame:CGRectMake(0,0, 140,44)];
[toolbar setItems:[NSArray arrayWithObjects:firstButton, secondButton, nil]];
UIBarButtonItem *customBarButton = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
self.navigationItem.leftBarButtonItem = customBarButton;
UIToolbarTransparent
.h
#import <Foundation/Foundation.h>
#interface UIToolbarTransparent : UIToolbar {
}
.m
#import "UIToolbarTransparent.h"
#implementation UIToolbarTransparent
- (id)init {
if (self = [super init]) {
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];
self.translucent=YES;
}
return self;
}
#end
samfisher is right, but you can just use a custom UIView that contains your UIButtons, than use that UIView as a (single) leftBasButtonItem
I have a UITableView with an Add cell... row and would like to have a keyboard pop up with a view above it like in the "Messages" application, where the user can type the name of the new cell.
I realize that there are several other ways to get user data, and several ways to implement the functionality that I am trying to achieve.
For example, the iPod application presents a popup when a new playlist should be created.
Right now, I have a hidden text field that is set to be the first responder when the Add cell... row is pressed, and I assign the view containing the input field and confirmation button as the inputAccessoryView for this hidden field. Alternatively, I could add this view as a subview of the table and position it using keyboard notifications.
I would just like to know if there is a cleaner way to accomplish what I am trying to do (such as setting the inputAccessoryView of the input textField to be displayed to be the textField's superview). I have tried several approaches, but I cannot seem to be able to dismiss the keyboard using resignFirstResponder when the view should close. I can get the inputAccessoryView to disappear, but the keyboard remains resolutely open, taking up necessary screen real estate. Also, when the nib's view is a UITableView with a UITableViewController as the File's Owner rather than a UIView with a UIViewController as the File's Owner, I get a very odd error: "setting the first responder view of the table but we don't know its type (cell/header/footer)"
Thanks in advance,
Julian Ceipek
You are on the right track with the setInputAccessoryView on the UITextView/UITextField classes' This method allows you to add any view you want to the top of a keyboard.
The view you create would then use a delegation method to tell the main view controller to resignFirstResponder.
So, to get you started:
#protocol TextFieldAccessoryViewDelegate
#required
- (void)keyboardShouldDismiss;
#end
#interface TextFieldAccessoryView : UIView
#property (nonatomic, retain) id<TextFieldAccessoryViewDelegate> delegate;
- (id)initWithFrame:(CGRect)frame withDelegate (id<TextFieldAccessoryViewDelegate>)aDelegate;
#end
The implementation might look a little like (only posting the code that makes the view):
#pragma mark - Private methods
- (void)doneButtonTapped:(id)sender
{
[delegate keyboardShouldDismiss];
}
- (void)setUpChildrenView
{
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(doneButtonTapped:)];
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:#""];
[navigationItem setRightBarButtonItem:doneButton];
[navigationItem setHidesBackButton:YES];
UINavigationBar *navigationBar = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.width, 44.0f)] autorelease];
[navigationBar pushNavigationItem:navigationItem animated:NO];
[self addSubview:navigationBar];
}
I have used a standard NavigationBar looking view, but you could put in anything you like and include buttons, textfields, images of robot unicorns, the works
If you don't get everything thats going on in the above code you might need to brush up on Delegation and creating views programmatically.
- (void)viewDidLoad
{
[self createAccessoryView];
[textField setDelegate:self];
[textField setKeyboardType:UIKeyboardTypeDefault];
[textField setInputAccessoryView:fieldAccessoryView];
}
- (void)createAccessoryView
{
CGRect frame = CGRectMake(0.0, self.view.bounds.size.height, self.view.bounds.size.width, 44.0);
fieldAccessoryView = [[UIToolbar alloc] initWithFrame:frame];
fieldAccessoryView.barStyle = UIBarStyleBlackOpaque;
fieldAccessoryView.tag = 200;
[fieldAccessoryView setBarStyle:UIBarStyleBlack];
UIBarButtonItem *spaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(done:)];
UISegmentedControl* segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:NSLocalizedString(#"Previous", #""), NSLocalizedString(#"Next", #""), nil]];
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[segmentedControl setMomentary:YES];
UIBarButtonItem *segmentButton = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];
[fieldAccessoryView setItems:[NSArray arrayWithObjects:segmentButton, spaceButton, doneButton, nil] animated:NO];
[segmentButton release];
[spaceButton release];
[doneButton release];
[segmentedControl release];
}
I'm trying to disable a button that I add to my navigation controller bar. Here is how I added it:
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithTitle:#"Add" style:UIBarButtonItemStylePlain target:self action:#selector(addNew)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];
What is the best way to enable/disable items like these? I've tried this code:
addButton.disabled = YES;
but it doesn't work of course. Any help would be appreciated. Thanks.
Edit: Should be addButton.enabled = YES;
Oops
If you define addButton in your header, and #synthesize it, then you will be able to use addButton.enabled = NO;, there is no "disabled" setter.
.h
#interface MyViewController {
UIBarButtonItem *addButton;
}
#property(nonatomic,retain) UIBarButtonItem *addButton;
#end
.m
#implementation MyViewController
#synthesize addButton;
-(void)viewDidLoad{
addButton = [[UIBarButtonItem alloc] initWithTitle:#"Add" style:UIBarButtonItemStylePlain target:self action:#selector(addNew)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];
}
-(void)DoSomething{
addButton.enabled = NO;
}