I'm trying to get a UIPickerView to display when a UITextField is clicked on by the user. I also want the UIPickerView to have a toolbar at the top with buttons to submit the selection and cancel.
Do I need to connect a UIPickerView in the interface builder, or connect an action somewhere else? I am also getting warnings when I build. One warning is under the resignFirstResponder. It says:
local declaration of age hides instance variable
There are several more warning similar to the one above for different variables.
Another warning is:
Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.
Here are my .h and .m files:
.h
#import <UIKit/UIKit.h>
#interface PracticePickerViewController : UIViewController <UITextFieldDelegate>{
IBOutlet UITextField *age;
IBOutlet UIPickerView *agePickerView;
IBOutlet UIActionSheet *actionSheet;
IBOutlet UIToolbar *pickerToolbar;
}
#end
.m
#import "PracticePickerViewController.h"
#implementation PracticePickerViewController
-(void)textFieldDidBeginEditing:(UITextField *)age{
[age resignFirstResponder];
actionSheet = [[UIActionSheet alloc] initWithTitle:#"Pick Your Age" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0,40,0,0);
UIPickerView *agePickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
agePickerView.showsSelectionIndicator = YES;
agePickerView.dataSource = self;
agePickerView.delegate = self;
[actionSheet addSubview:agePickerView];
pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0,0,320,44)];
pickerToolbar.barStyle = UIBarStyleBlackOpaque;
[pickerToolbar sizeToFit];
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(doneButtonPressed:)];
[barItems addObject:doneBtn];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelButtonPressed:)];
[barItems addObject:cancelBtn];
[pickerToolbar setItems:barItems animated:YES];
[actionSheet addSubview:pickerToolbar];
[actionSheet addSubview:agePickerView];
[actionSheet showInView:self.view];
[actionSheet setBounds:CGRectMake(0,0,320,485)];
}
local declaration of age hides instance variable
This means you've defined a variable name that is already used by a class variable (so in this case, you may have declared UITextField *age somewhere in the class, but you can't re-use variable name age in this class because the compiler will confuse it with the class variable).
Class 'PracticePickerViewController' does not implement the 'UIActionsheetDelegate' protocol.
You haven't made your PracticePickerViewController a UIActionsheetDelegate. To do this, you have change your interface header (PracticePickerViewController.h) to read:
#interface PracticePickerViewController : UIViewController <UITextFieldDelegate, UIActionsheetDelegate>{
Don't forget to implement the required delegate methods as well!
Finally, I strongly recommend you check out the ActionSheetPicker project.It's a drop-in class that has exactly the functionality you're trying to implement, so you can either replace your current code with that, or just use it as a reference to see how to implement the embedded ActionSheet inside the UIPickerView correctly. Hope all that helps!
Related
For my app, I have a UIToolBar that appears above a UIWebView. What I'm attempting to do is remove both the tool-bar and the web-view from the superview when UIBarButtonItem in the tool-bar is clicked.
I've made the tool-bar and web-view properties of my ViewController like so:
#property (nonatomic, weak) UIToolbar *toolBar;
#property (nonatomic, weak) UIWebView *webView;
These views are supposed to be removed when the method below is called
// Remove the toolbar and the webview
- (void)hideToolbarAndWebView
{
[_toolBar removeFromSuperview];
[_webView removeFromSuperview];
NSLog(#"Button clicked");
}
Below is where I'm first creating the bar-button item, and assigning the action to be the hideToolbarAndWebView method:
// Create a bar button and add it to the toolbar. Action is to dismiss the tool-bar and thew web-view.
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:#"Close" style:UIBarButtonItemStylePlain target:self action:#selector(hideToolbarAndWebView)];
I know that the bar-button is successfully calling the hideToolbarAndWebView method through logging, but the views are not being removed from the superview. How do I fix this?
EDIT Below is the code where the tool-bar is created. It's inside a method called showToolbarthat is called from the AppDelegate.
// Create a toolbar
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:self.view.bounds];
toolBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// Default height is 44 points, but seems to close to the status bar
toolBar.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds),64);
toolBar.barStyle = UIBarStyleBlackTranslucent;
[self.view addSubview:toolBar];
Below is the code that creates the web-view, and calls the above showToolbarmethod:
// Create a web view that displays the update info, and save settings for current version
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
NSString *url=#"http://google.com";
webViewController.URL = url;
webViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:webViewController animated:YES completion:nil];
[webViewController showToolbar];
Thanks to #Midhun MP, I realized what I was doing wrong. Instead of trying to use properties, I needed to set toolBar and webView to be global variables:
UIToolbar *toolBar;
UIWebView *webView;
And instead of creating toolBar and webView like so:
UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:self.view.bounds];
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
Since the variables were now created, I now only needed to assign them like so:
toolBar = [[UIToolbar alloc] initWithFrame:self.view.bounds];
webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
Then, when I called hideToolbarAndWebView, the toolBar and webView were both removed from the superview.
I am coding a TableViewController with a Section called Information where the user enter a name , a date , a description. My problem is that after i've done all the settings for the NSDate picker on the date's textfield , when i click on the description's textfield instead of keyboard i see the date picker and it stores date in the date's textfield.
.h file
#interface ViewControllerInfo : UITableViewController <UITableViewDelegate, UITextFieldDelegate>{
NSDate *date;
UIActionSheet *dateSheet;
}
#property (weak, nonatomic) IBOutlet UITextField *scadenza;
#property (weak, nonatomic) IBOutlet UITextField *dateTextField;
#property (nonatomic, retain)NSDate *date;
-(void)setDatario;
-(void)dismissDateSet;
-(void)cancelDate;
.m file (pointing only the functions needed):
-(void)setDatario;{
dateSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[dateSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0, 44, 0, 0);
UIDatePicker *datePicker = [[UIDatePicker alloc]initWithFrame:pickerFrame];
[datePicker setDatePickerMode:UIDatePickerModeDate];
[dateSheet addSubview:datePicker];
UIToolbar *controlToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, dateSheet.bounds.size.width, 44)];
[controlToolbar setBarStyle:UIBarStyleBlack];
[controlToolbar sizeToFit];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *setButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissDateSet)];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelDate)];
[controlToolbar setItems:[NSArray arrayWithObjects:spacer, setButton, cancelBtn, nil] animated:NO];
[dateSheet addSubview:controlToolbar];
[dateSheet showInView:self.view];
[dateSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
-(void)cancelDate{
[dateSheet dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)dismissDateSet{
NSArray *listofViews = [dateSheet subviews];
for (UIView *subview in listofViews){
if ([subview isKindOfClass:[UIDatePicker class]]){
self.date = [(UIDatePicker*)subview date];
}
[dateSheet dismissWithClickedButtonIndex:0 animated:YES];
}
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
[dateTextField setText:[dateFormatter stringFromDate:self.date]];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
[self setDatario];
return NO;
}
I couldn't understand why is interesting also the description's texfield.
Question is : why the description's textfield is matched with the datepicker ?
Replace your textFieldShouldBeginEditing method like this
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField == scadenza) {
return YES;
}
else if(textField == scadenza){
[self setDatario];
return NO;
}
return YES;
}
Even better, put a custom UIButton (invisible) of the same size as the textfield right over the textfield. Set the textfield enabled attribute to NO and then show the picker when the button is tapped. When the user selects a date from the picker, update the text in the textfield. This way you won't have to manage the textfield's delegate. I have used both methods and the button is much cleaner and smoother for the user.
I have two buttons on my navbar. One on the left and one on the right. The button on the left works but the one on the right does not work. If I swap the buttons, recompile and load the issue persist with the right button regardless of which button is in the right spot of the bar.
Also while the left button works as soon as I try to use the right button the left button stops working too.
How do I make the right button work? Below is the code.
UINavigationBar *NavBar = [[UINavigationBar alloc] init];
[NavBar sizeToFit];
[self.view addSubview:NavBar];
UIBarButtonItem *cmdBack = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(cmdBackClicked:)];
UIBarButtonItem *cmdAddDevice = [[UIBarButtonItem alloc] initWithTitle:#"Add Device"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(cmdAddDeviceClicked:)];
UINavigationItem *NavBarItems = [[UINavigationItem alloc] initWithTitle:#"Settings"];
NavBarItems.leftBarButtonItem = cmdBack;
NavBarItems.rightBarButtonItem = cmdAddDevice;
NavBar.items = [NSArray arrayWithObjects:NavBarItems, nil];
The functions for the buttons are these
- (void) cmdBackClicked:(id)sender
{
[self.view removeFromSuperview];
}
- (void) cmdAddDeviceClicked:(id)sender
{
vcAddDevice *ViewAddDevice = [[vcAddDevice alloc] initWithNibName:#"vcAddDevice" bundle:nil];
[ViewAddDevice SetEditDeviceMode:[NSString stringWithFormat:#"No"]];
[self.view addSubview:ViewAddDevice.view];
}
In the .h file I have this.
#import <UIKit/UIKit.h>
#import "vcAddDevice.h"
#interface ViewControllerSettings : UIViewController<vcAddDeviceControllerDelegate, UITableViewDelegate, UITableViewDataSource>
- (IBAction) cmdBackClicked:(id) sender;
- (IBAction) cmdAddDeviceClicked:(id) sender;
#end
I have a UIActionSheet and I have added the following - UIPickerView and 2 BarButtonItems. I am trying to close the action sheet when someone clicks the Cancel Button (it is one of the bar button items).
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles: nil];
[actionSheet setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
CGRect pickerFrame = CGRectMake(0,40,0,0);
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:pickerFrame];
pickerView.showsSelectionIndicator = YES;
pickerView.dataSource = self;
pickerView.delegate = self;
[actionSheet addSubview:pickerView];
UIToolbar *tools = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
tools.barStyle = UIBarStyleBlackOpaque;
[actionSheet addSubview:tools];
UIBarButtonItem *doneButton=[[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleBordered target:self action:#selector(btnActinDoneClicked)];
doneButton.imageInsets=UIEdgeInsetsMake(200, 6, 50, 25);
UIBarButtonItem *CancelButton=[[UIBarButtonItem alloc]initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(btnActinCancelClicked)]; //this is where the problem is
NSArray *array = [[NSArray alloc]initWithObjects:CancelButton, doneButton, nil];
[tools setItems:array];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet setBounds:CGRectMake(0, 0, 320, 485)];
I have added another method to dismiss the action sheet -
-(IBAction)btnActinCancelClicked:(id)sender{
[sender dismissWithClickedButtonIndex:0 animated:YES];
}
The problem is that the app crashes when the BarButton is clicked. I think the problem is caused where the CancelButton is declared and it is unable to send a message to the btnActinCancelClicked method, but I can't figure out how to fix it.
Thanks
Your method is this;
-(IBAction)btnActinCancelClicked:(id)sender
So you need to add it like this (because it receives a parameter);
#selector(btnActinCancelClicked:)
So for example, if a method had three parameters you'd call it #selector(myMethod:andX:andY:)
Also, to access your UIActionSheet (not entirely sure this will work);
UIActionSheet *acSheet = sender.superView;
//Check if it is the ActionSheet here then dismiss it
[acSheet dismissWithClickedButtonIndex:0 animated:YES];
It's not the sender you want to dismiss. It's the ActionSheet. You'll need a reference for that and change your code for something like:
- (IBAction)btnActinCancelClicked:(id)sender{
[self.actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
i use storyboard for developing UI for my project. There are many issues were solved, but this problem killing me. I have added action for UIBarButtonItem :
- (IBAction)pressAddActionButton:(UIBarButtonItem *)sender {
if (_mode == itemSelect) {
LookUpTableViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"lookupTable"];
vc.key = #"title";
vc.data = [Linesheet MR_findAllSortedBy:#"title" ascending:YES];
vc.lookUpDelegate = self;
self.myPopoverController = [[UIPopoverController alloc] initWithContentViewController:vc];
[self.myPopoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
} else {
self.mode = itemSelect;
}
}
If i using storyBoard segue for showing popover - all good, but if i do it in runtime a popover does not show. I should manually create UIBarButtonItem.
Thanks for help!!!
Update, code for buttons:
- (void)setupNavigationItems {
self.navigationController.navigationBarHidden = NO;
UIBarButtonItem *addItem;
if (_mode == itemSelect) {
addItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(pressAddActionButton:)];
} else {
addItem = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone
target:self
action:#selector(pressDoneButton:)];
}
[addItem setStyle:UIBarButtonItemStyleBordered];
UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
UIBarButtonItem *action = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction
target:self
action:#selector(pressActionButton:)];
[action setStyle:UIBarButtonItemStyleBordered];
[toolbar setItems:[NSArray arrayWithObjects:separator, addItem, action, nil] animated:YES];
}
Make sure you're hitting the code as you expect using a breakpoint on the presentPopoverFromBarButtonItem line. Also, make sure that the myPopoverController property is declared strong if you're using arc, as otherwise it will be nil before the presenting line.
Did you check if LookUpTableViewController *vc actually gets a proper instance? If not then check that your storyboard does have #"lookupTable" set as your controller's identifier.
The code is right. Try replacing the sender with self.navigationItem.leftBarButtonItem or self.navigationItem.rightBarButtonItem. The sender may not be what you are expecting.
Also remove the if (_mode == itemSelect) clause for testing I'm not sure why you need to access the ivar _mode ivar directly.