Add custom UIButton to UIKeyboard's accessory view for a UIWebView - cocoa-touch

I need to add a camera button to a UIWebView's keyboard accessory view toolbar (the one that already has the "Back|Next" and "Done" buttons).
Is there an easy way to do this?

I'm still looking for a better way to do it, but one solution for the moment would be to destroy the bar and recreate it like so :
- (void)viewDidLoad
{
[super viewDidLoad];
UIWebView *web = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSURL *aURL = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *aRequest = [NSURLRequest requestWithURL:aURL];
[web loadRequest:aRequest];
[self.view addSubview:web];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self performSelector:#selector(removeBar) withObject:nil afterDelay:0];
}
- (void)removeBar {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
// iOS 5 sticks the UIWebFormView inside a UIPeripheralHostView.
if ([[possibleFormView description] rangeOfString:#"UIPeripheralHostView"].location != NSNotFound) {
for (UIView *subviewWhichIsPossibleFormView in [possibleFormView subviews]) {
if ([[subviewWhichIsPossibleFormView description] rangeOfString:#"UIWebFormAccessory"].location != NSNotFound) {
UISegmentedControl *nav = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Previous",#"Next", nil]];
nav.momentary = YES;
nav.frame = CGRectMake(5, 8, 120, 30);
nav.segmentedControlStyle = UISegmentedControlStyleBar;
nav.tintColor = [UIColor colorWithWhite:0.25 alpha:1];
[nav addTarget:self action:#selector(navigate) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *pictureBtn =[[UIBarButtonItem alloc] initWithTitle:#"Picture" style:UIBarButtonItemStyleBordered target:self action:#selector(takePic:)];
UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyboard)];
NSArray *buttons = [NSArray arrayWithObjects:flexButton,pictureBtn,flexButton,doneButton, nil];
[(UIToolbar *)subviewWhichIsPossibleFormView addSubview:nav];
[(UIToolbar *)subviewWhichIsPossibleFormView setItems:buttons];
}
}
}
}
}
But then, you have to implement the previous, next and done function again. But it's not the hardest part.

there is an easier way to do this.
Keep your keyboard notification in your viewDidLoad
After that all you will need is the following method:
-(void)keyboardDidShow:(NSNotification*)notif
{
NSArray *array = [[UIApplication sharedApplication] windows];
for (UIWindow* wind in array) {
for (UIView* currView in wind.subviews) {
if ([[currView description] hasPrefix:#"<UIPeripheralHostView"]) {
for (UIView* perView in currView.subviews) {
if ([[perView description] hasPrefix:#"<UIWebFormAccessory"]) {
UIBarButtonItem *doneBttn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(resignKeyBoard)];
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray: [(UIToolbar *) perView items]];
[arr addObject:doneBttn];
[(UIToolbar *) perView setItems:arr];
}
}
}
}
}
}
I have basically taken the original prev/next buttons from the UIWebFormAccessory and added a done button to the end of it, but you can add what ever buttons you want to this.
Some may think this shouldn't be implemented in -(void)keyboardDidShow: because you are changing the UI after it displays on screen, but so far I haven't noticed any issues with this. (only tested in simulator)
Hope this was useful!

Related

Unrecognized selector issue

This is the code:
#interface CreateAccountViewController : UIViewController<UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate>
{
UIToolbar *keyboardToolbar;
NSDate *birthdate;
UIActionSheet *dateSheet;
}
#property(strong, nonatomic) IBOutlet UITextField *txtFirstName;
#property(strong, nonatomic) IBOutlet UITextField *txtLastName;
#property(strong, nonatomic) IBOutlet UITextField *txtGender;
#property(strong, nonatomic) IBOutlet UITextField *txtBirthdate;
#property(strong, nonatomic) IBOutlet UITextField *txtEmail;
-(void)resignKeyboard:(id)sender;
-(void)gotoPreviousField:(id)sender;
-(void)gotoNextField:(id)sender;
-(void)setBirth;
-(void)dismissDateSet;
-(void)gotoPreviousBirthdate;
-(void)gotoNextBirthdate;
#end
#implementation CreateAccountViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[[[keyboardToolbar items] objectAtIndex:0] setEnabled:YES];
[[[keyboardToolbar items] objectAtIndex:1] setEnabled:YES];
if([textField isEqual:self.txtFirstName])
{
[[[keyboardToolbar items] objectAtIndex:0] setEnabled:NO];
}
else if([textField isEqual:self.txtEmail])
{
[[[keyboardToolbar items] objectAtIndex:0] setEnabled:NO];
}
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if([textField isEqual:self.txtBirthdate])
{
[self setBirth];
return NO;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view
if(keyboardToolbar==nil)
{
keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem *btnPrevious = [[UIBarButtonItem alloc] initWithTitle:#"Previous" style:UIBarButtonItemStyleBordered target:self action:#selector(gotoPreviousField:)];
UIBarButtonItem *btnNext = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleBordered target:self action:#selector(gotoNextField:)];
UIBarButtonItem *btnExtraSpace= [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *btnDone=[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(resignKeyboard:)];
[keyboardToolbar setItems:[[NSArray alloc] initWithObjects:btnPrevious, btnNext, btnExtraSpace, btnDone, nil]];
}
}
-(void) resignKeyboard:(id)sender
{
if([self.txtFirstName isFirstResponder])
{
[self.txtFirstName resignFirstResponder];
}
else if([self.txtLastName isFirstResponder])
{
[self.txtLastName resignFirstResponder];
}
else if([self.txtGender isFirstResponder])
{
[self.txtGender resignFirstResponder];
}
else if([self.txtBirthdate isFirstResponder])
{
[self.txtBirthdate resignFirstResponder];
}
else if([self.txtEmail isFirstResponder])
{
[self.txtEmail resignFirstResponder];
}
}
-(void) gotoPreviousField:(id)sender
{
if([self.txtFirstName isFirstResponder])
{
[self.txtEmail becomeFirstResponder];
}
else if([self.txtLastName isFirstResponder])
{
[self.txtFirstName becomeFirstResponder];
}
else if([self.txtGender isFirstResponder])
{
[self.txtLastName becomeFirstResponder];
}
else if([self.txtEmail isFirstResponder])
{
[self.txtBirthdate becomeFirstResponder];
}
}
-(void)gotoNextField:(id)sender
{
if([self.txtFirstName isFirstResponder])
{
[self.txtLastName becomeFirstResponder];
}
else if([self.txtLastName isFirstResponder])
{
[self.txtGender becomeFirstResponder];
}
else if([self.txtGender isFirstResponder])
{
[self.txtBirthdate becomeFirstResponder];
}
else if([self.txtEmail isFirstResponder])
{
[self.txtFirstName becomeFirstResponder];
}
}
-(void)setBirth
{
dateSheet=[[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[dateSheet setActionSheetStyle:UIActionSheetStyleDefault];
CGRect pickerFrame=CGRectMake(0, 44, 0, 0);
UIDatePicker *birthDayPicker=[[UIDatePicker alloc] initWithFrame:pickerFrame];
[birthDayPicker setDatePickerMode:UIDatePickerModeDate];
[dateSheet addSubview:birthDayPicker];
UIToolbar *birthDayToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, dateSheet.bounds.size.width, 44)];
[birthDayToolbar setBarStyle:UIBarStyleBlackTranslucent];
[birthDayToolbar sizeToFit];
UIBarButtonItem *btnPrevious = [[UIBarButtonItem alloc] initWithTitle:#"Previous" style:UIBarButtonItemStyleBordered target:self action:#selector(gotoPreviousBirthdate:)];
UIBarButtonItem *btnNext = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStyleBordered target:self action:#selector(gotoNextBirthdate:)];
UIBarButtonItem *btnExtraSpace= [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *btnDone=[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(dismissDateSet:)];
[birthDayToolbar setItems:[[NSArray alloc] initWithObjects:btnPrevious, btnNext, btnExtraSpace, btnDone, nil]];
[dateSheet addSubview:birthDayToolbar];
[dateSheet showInView:self.view];
[dateSheet setBounds:CGRectMake(0, 0, 320, 485)];
}
-(void)dismissDateSet
{
NSArray *listOfViews = [dateSheet subviews];
for(UIView *subView in listOfViews)
{
if([subView isKindOfClass:[UIDatePicker class]])
{
NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM/dd/yyyy"];
self.txtBirthdate.text=[dateFormatter stringFromDate:[(UIDatePicker*)subView date]];
}
}
}
-(void)gotoPreviousBirthdate
{
[self dismissDateSet];
[self.txtGender becomeFirstResponder];
}
-(void)gotoNextBirthdate
{
[self dismissDateSet];
[self.txtEmail becomeFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CreateCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UITextField *textField = [[UITextField alloc] init];
textField.enablesReturnKeyAutomatically = YES;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.clearButtonMode=UITextFieldViewModeWhileEditing;
textField.delegate=self;
CGRect aRect=CGRectMake(10, 10.f, CGRectGetWidth(cell.bounds)-40.f, 30.f );
textField.frame = aRect;
if(indexPath.row==0)
{
textField.placeholder = #"First name";
self.txtFirstName=textField;
}
else if(indexPath.row==1)
{
textField.placeholder = #"Last name";
self.txtLastName=textField;
}
else if(indexPath.row==2)
{
textField.placeholder = #"Gender";
self.txtGender=textField;
}
else if(indexPath.row==3)
{
textField.placeholder = #"Date of birth";
self.txtBirthdate=textField;
}
else
{
textField.placeholder = #"Email";
self.txtEmail=textField;
}
[cell.contentView addSubview:textField];
cell.selectionStyle=UITableViewCellSelectionStyleNone;
textField.inputAccessoryView=keyboardToolbar;
return cell;
}
#end
If i press the Previous button from the date picker toolbar i get this exception:
[CreateAccountViewController gotoPreviousBirthdate:]: unrecognized selector sent to instance
If i press the Next button from the date picker toolbar i get this exception:
[CreateAccountViewController gotoNextBirthdate:]: unrecognized selector sent to instance
If i press the Done button from the date picker toolbar i get this exception:
[CreateAccountViewController dismissDateSet:]: unrecognized selector sent to instance
It seems that i am making the same mistake 3 times but i can't quite figure out what is that.
Thanks
Your setting the target selector to be:
#selector(gotoPreviousBirthdate:)
But you declare it as:
-(void)gotoPreviousBirthdate;
Remove the : in the selector as #selector(gotoPreviousBirthdate) since you're not taking an argument, or change the declaration to be -(void)gotoPreviousBirthday:(id)sender.
Then repeat for the other two.
You are calling the methods as if they are class methods, but they are declared as instance methods in your interface. Also the invocation of the selector is incorrect.
Create an instance of the class first:
CreateAccountViewController *vc = [[CreateAccountViewController alloc] init]; //Something like this
Then you can call the instance methods:
[vc gotoPreviousBirthday]; //Note no trailing colon!
Or, if you declared the method as
+(void)gotoPreviousBirthdate;
note the + in the signature - then you could call the method as your code shows.
This is a pretty fundamental concept in Objective-C so I would recommend you read the documentation first. Apple Objective-C Primer

Picker View does not reappear once dismissed, and text field clicked a second time

Here's a simplified code, with a view controller with just a text field I also updated the title to reflect the newer issue.
When run, I click the text field and it brings up the picker view, and I'm able to click a value on the picker view and it shows up on the text field. I'm able to dismiss the picker view now when I press the Done button on the navigation bar. But now when I click the text field a second time, I don't get the picker view to pop up a second time.
import
#interface MyPickerViewViewController : UIViewController <UIPickerViewDelegate,
UIPickerViewDataSource,
UITextFieldDelegate>
#end
#interface MyPickerViewViewController () {
UIPickerView *_pv;
NSArray *_array;
IBOutlet __weak UITextField *_tf;
}
#end
#implementation MyPickerViewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_array = [NSArray arrayWithObjects:#"One", #"Two", #"Three", nil];
// Do any additional setup after loading the view, typically from a nib.
_pv = [[UIPickerView alloc] initWithFrame:CGRectZero];
_pv.dataSource = self;
_pv.delegate = self;
_tf.inputView = _pv;
UIToolbar* mypickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 56)];
mypickerToolbar.barStyle = UIBarStyleBlackOpaque;
[mypickerToolbar 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(pickerDoneClicked:)];
[barItems addObject:doneBtn];
[mypickerToolbar setItems:barItems animated:YES];
_tf.inputAccessoryView = mypickerToolbar;
_tf.delegate = self;
}
- (void)pickerDoneClicked:(id)sender
{
[_pv removeFromSuperview];
[_tf.inputView removeFromSuperview];
[_tf.inputAccessoryView removeFromSuperview];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Added this method and now the picker view comes up every time I
// click on the text field, even after I dismiss it. However, the
// picker view is in wrong place, so I just have to adjust the
// CGRect assigned to it.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[self.view addSubview:_tf.inputAccessoryView];
[self.view addSubview:_tf.inputView];
return NO;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"Hello there");
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated
{
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:( NSInteger)component
{
return [_array objectAtIndex:row];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return _array.count;
}
- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
_tf.text = [_array objectAtIndex:row];
}
#end
I think you missed this:
[datePicker removeFromSuperview];
[pickerView removeFromSuperview];
You may try:
[self.view endEditing:YES];
in your action method
See update with this addition
// Added this method and now the picker view comes up every time I
// click on the text field, even after I dismiss it. However, the
// picker view is in wrong place, so I just have to adjust the
// CGRect assigned to it.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[self.view addSubview:_tf.inputAccessoryView];
[self.view addSubview:_tf.inputView];
return NO;
}
Here is an adjusted CGRect for the pickerview and tool bar that worked. I was wondering though if there is a default height for a pickerview?
- (void)viewDidLoad
{
[super viewDidLoad];
_array = [NSArray arrayWithObjects:#"One", #"Two", #"Three", #"Four", nil];
// Do any additional setup after loading the view, typically from a nib.
CGRect viewRect = [[UIScreen mainScreen] bounds];
CGFloat pvHeight = 235;
CGFloat pvYpos = viewRect.size.height - pvHeight;
CGRect pvRect = CGRectMake(viewRect.origin.x, pvYpos, viewRect.size.width, pvHeight);
_pv = [[UIPickerView alloc] initWithFrame:pvRect];
_pv.dataSource = self;
_pv.delegate = self;
_tf.inputView = _pv;
CGFloat tbYpos = pvYpos-44;
UIToolbar* mypickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, tbYpos, viewRect.size.width, 44)];
mypickerToolbar.barStyle = UIBarStyleBlackOpaque;
[mypickerToolbar 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(pickerDoneClicked:)];
[barItems addObject:doneBtn];
[mypickerToolbar setItems:barItems animated:YES];
_tf.inputAccessoryView = mypickerToolbar;
_tf.delegate = self;
}

UIPickerView in a UIActionSheet: UI freezes

I'm having an issue with my iOS app freezing whenever I trigger a UIActionSheet with a UIPickerView inside it. The picker wheel scrolls fine until I try to hit the "Done" button on the UIActionSheet, at which point the UI freezes. However, XCode isn't registering any kind of crash in the program, so I'm pretty confused.
Has anyone else run into this problem before? How can I solve it?
I never Face this type of problem.I think this one is hekp you to solve your problem. I used the PickerView in same way
UIActionSheet *actionSheet;
NSString *pickerType;
- (void)createActionSheet {
if (actionSheet == nil) {
// setup actionsheet to contain the UIPicker
actionSheet = [[UIActionSheet alloc] initWithTitle:#"Select"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
UIToolbar *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];
[flexSpace release];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(pickerDone:)];
[barItems addObject:doneBtn];
[doneBtn release];
[pickerToolbar setItems:barItems animated:YES];
[barItems release];
[actionSheet addSubview:pickerToolbar];
[pickerToolbar release];
[actionSheet showInView:self.view];
[actionSheet setBounds:CGRectMake(0,0,320, 464)];
}
}
-(IBAction)BtnPressed:(id)sender
{
[self createActionSheet];
pickerType = #"picker";
select = NO;
UIPickerView *chPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(0.0, 44.0, 0.0, 0.0)];
chPicker.dataSource = self;
chPicker.delegate = self;
chPicker.showsSelectionIndicator = YES;
[actionSheet addSubview:chPicker];
sessoTxt.text = [sessoArray objectAtIndex:0];
[chPicker release];
}
#pragma mark UIPickerViewDelegate Methods
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
int count;
if ([pickerType isEqualToString:#"picker"])
count = [array count];
return count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *string;
if ([pickerType isEqualToString:#"picker"])
string = [array objectAtIndex:row];
return string;
}
// Set the width of the component inside the picker
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 300;
}
// Item picked
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
select = YES;
if ([pickerType isEqualToString:#"picker"])
{
Txt.text = [array objectAtIndex:row];
}
}
- (void)pickerDone:(id)sender
{
if(select == NO)
{
if ([pickerType isEqualToString:#"picker"])
{
Txt.text = [array objectAtIndex:0];
}
}
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
[actionSheet release];
actionSheet = nil;
}
}

iPad Won't Load Modal View

I'm getting this error when loading a modal view.
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x72785a0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key aboutTableView.'
It works perfectly fine from the iPhone, but I'm having this trouble with the iPad.
- (IBAction)showOptionsMenu
{
self.optionsNavController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.optionsNavController.modalPresentationStyle = UIModalPresentationFormSheet;
self.optionsNavController.modalInPopover = YES;
[self presentModalViewController:self.optionsNavController animated:YES];
}
Update:
This works but the UIButton is not being displayed:
MoreViewController *svc = [[[MoreViewController alloc] init] autorelease];
optionsNavController= [[UINavigationController alloc] initWithRootViewController:svc];
self.optionsNavController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.optionsNavController.modalPresentationStyle = UIModalPresentationFormSheet;
self.optionsNavController.modalInPopover = YES;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]initWithTitle:#"Done" style:UIBarButtonItemStyleBordered target:self action:#selector(dissmissView)];
self.optionsNavController.navigationItem.rightBarButtonItem = doneButton;
[doneButton release];
[self presentModalViewController:self.optionsNavController animated:YES];
Here is a good way to launch a modal view for both devices:
#define IDIOM UI_USER_INTERFACE_IDIOM()
#define IPAD UIUserInterfaceIdiomPad
SomeViewController *svc = [[[SomeViewController alloc] init] autorelease];
if ( IDIOM == IPAD ) {
UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:svc];
[controller setModalPresentationStyle:UIModalPresentationFormSheet];
[controller setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentModalViewController:controller animated:YES];
[controller release];
} else {
/* or you can present the view as modal: */
[self.navigationController pushViewController:svc animated:YES];
}
SomeViewController
-(void)viewDidLoad
{
[super viewDidLoad];
if ( IDIOM == IPAD ) {
UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self action:#selector(dismiss)] autorelease];
self.navigationItem.leftBarButtonItem = doneButton;
}
}
-(void)dismiss
{
[self dismissModalViewControllerAnimated:YES];
}
Are you using different xibs for iphone/ipad?
If so check your connections in your iPad version there is probably a handing connection that you have not removed.

Action sheet getting caught on tabbar

This is a tricky one that I've been working on for a while. I have a an action sheet that appears in a view with a tabbar, sometimes when I dismiss the action sheet it gets "caught" in the tabbar and am unable to do anything.The app doesn't crash because if i minimize it and then come back in it is dimissed, it just appears that the modal behavior isn't being dismissed properly.
I recently changed how the action sheet is displayed from "showInView" to "showFromTabBar" and am not sure if this is creating the issue.
Thanks,
William
Edit:
Below is the code I use to dismiss my actionsheet:
-(void)doneButtonPressed:(id)sender{
if ([[self viewWithTag:1] isKindOfClass:[PickerView class]]) {
PickerView *picker = (PickerView *)[self viewWithTag:1];
if (picker.selectedRow == nil) {
[picker populateSelectRowForRow:0 andComponent:0];
}
NSNotification *note = [NSNotification notificationWithName:#"doneButtonPressed" object:self.indexPath userInfo:picker.selectedRow];
[[NSNotificationCenter defaultCenter] postNotification:note];
}else {
DatePickerView *picker = (DatePickerView *)[self viewWithTag:1];
NSDictionary *extraInfo = [[NSDictionary alloc] initWithObjects:[[NSArray alloc] initWithObjects:[self formatDateToString:[picker date]], nil] forKeys:[[NSArray alloc] initWithObjects:#"value", nil]];
NSNotification *note = [NSNotification notificationWithName:#"doneButtonPressed" object:self.indexPath userInfo:extraInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
}
[self dismissWithClickedButtonIndex:0 animated:YES];
}
and the notification method that is called:
-(void)pickerUpdate:(NSNotification *)note{
NSIndexPath *indexPath = [note object];
NSDictionary *extraInfo = [note userInfo];
NSDictionary *dict = [[tableController.sectionAndFields objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row + kHeaderAndFooterOffset)];
[tableController.formDetails setObject:[extraInfo objectForKey:#"value"] forKey:[dict objectForKey:#"key"]];
NSArray *reloadArray = [[NSArray alloc] initWithObjects:indexPath, nil];
[indexPath release];
[self.tv reloadRowsAtIndexPaths:reloadArray withRowAnimation:NO];
[reloadArray release];
}
I did manage to solve this however it feels very much like a hack, I introduced a delay into the code using:
[self performSelector:#selector(dismissFromActionSheet) withObject:nil afterDelay:0.2];
With dismissFromActionSheet being:
-(void)dismissFromActionSheet{
[self dismissWithClickedButtonIndex:0 animated:YES];
}