I have a UIPopover that I have created several UITextFields programmatically. If one of the UITextfields is tapped, I want to have a UIDatePicker inside a UIPopoverController point to the UITextfield that caused the tap. I am able to get the tag, so I know which CGRect caused the tap; the problem is that I am unable to have the arrow of the UIPopoverController to point to that specific rectangle.
Here is the code (inView: self.frame is incorrect; it's just one of the things I tried)
if(textField.tag == 1301 ) { // 'startTime' text field
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
UIView *popoverView = [[UIView alloc] init]; //view
popoverView.backgroundColor = [UIColor blackColor];
UIDatePicker *datePicker=[[UIDatePicker alloc]init];//Date picker
datePicker.frame=CGRectMake(0,44,180,186); // 180,186
datePicker.datePickerMode = UIDatePickerModeTime;
[datePicker setMinuteInterval:15];
[datePicker setTag:1310];
[datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:datePicker];
popoverContent.view = popoverView;
innerPopoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[innerPopoverController setPopoverContentSize:CGSizeMake(180,206) animated:NO];
[innerPopoverController presentPopoverFromRect:CGRectMake(305, -190, 80, 35) // WRONG! TODO
inView:self.frame
permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
The CGRectMake has the same parameters (x,y,w,h) that the UITextfield was created with. The error I'm getting is:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPopoverController presentPopoverFromRect:inView:permittedArrowDirections:animated:]: Popovers cannot be presented from a view which does not have a window.'
Is this even possible, having a UIPopover within a UIPopover?
It should be like this:
innerPopoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[innerPopoverController setPopoverContentSize:CGSizeMake(180,206) animated:NO];
[innerPopoverController presentPopoverFromRect:CGRectMake(305, -190, 80, 35) // WRONG! TODO
inView: SubViewData.view
permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
If you have the tag of a view then do like this:
UIView *tappedView=[SubViewData.view viewWithTag:yourTag];
innerPopoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
[innerPopoverController setPopoverContentSize:CGSizeMake(180,206) animated:NO];
[innerPopoverController presentPopoverFromRect:CGRectMake(305, -190, 80, 35) // WRONG! TODO
inView: tappedView.superView
permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
Related
I have used UIDatePicker on the UITextField. I have press UITextField to select the date using datepicker 1st time(App working correct), 2nd Time when I have press again on UITextField to select the new date set on UITextField using UIDatePicker then application is crashes.
I am not using UITableView, I am using simple view that's viewController.
Please Help me...
Thanks
- (void)viewDidLoad
{
[super viewDidLoad];
form=[[NSDateFormatter alloc]init];
[form setDateFormat:#"MM-dd-yyyy"];
datePicker=[[UIDatePicker alloc]init];//Date picker
datePicker.frame=CGRectMake(0,0,320, 216);
datePicker.backgroundColor = [UIColor whiteColor];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
BOOL a;
if (textField.tag==10) {
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
UIView *popoverView = [[UIView alloc] init]; //view
popoverView.backgroundColor = [UIColor blackColor];
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker setMinuteInterval:5];
[datePicker setTag:10];
[datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:datePicker];
popoverContent.view = popoverView;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:popoverContent];
navigationController.delegate=self;
popoverController = [[UIPopoverController alloc]
initWithContentViewController:navigationController];
popoverController.delegate=self;
[popoverController setPopoverContentSize:CGSizeMake(320, 250) animated:NO];
[popoverController presentPopoverFromRect:textField.frame inView:self.addView permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
a=NO;
}
else
{
a=YES;
}
return a;
}
-(void)Result
{
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
formDay.dateFormat=#"MM-dd-yyyy";
NSString *day = [formDay stringFromDate:[datePicker date]];
self.edit_dob.text = day;
}
Error
*** Assertion failure in -[UIPickerTableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:], /SourceCache/UIKit/UIKit-3318.16.14/UITableView.m:9269
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource is not set'
I have share a screenshot. I have select date first time successfully and when I have press to reset new date on that textfield that time app crash.
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker setMinuteInterval:5];
[datePicker setTag:10];
[datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
[popoverView addSubview:datePicker];
You are repeating these operations every time the textfield is focused. This practice is plain wrong, and is a potential cause of various unexpected behavior like the one you encountered. The fact that it works for the first time makes me think that one of these unnecessarily repeated actions is the culprit. (I'd bet on the addTarget:forControlEvents: method call. This should never be done in any case. I don't even know what happens when you try to add the same target again.)
You should structure your code better to make these method calls only once, instead of multiple times like in the code you've shown (e.g. in viewDidLoad instead of textFieldShouldBeginEditing:) and most probably, the error will go away.
You need to retain the datepicker object i.e.:
#property(nonatomic,strong) UIDatePicker *datePicker;
in the .h file.
Here is updated code:
- (void)viewDidLoad
{
[super viewDidLoad];
form=[[NSDateFormatter alloc]init];
[form setDateFormat:#"MM-dd-yyyy"];
_datePicker=[[UIDatePicker alloc]init];//Date picker
_datePicker.frame=CGRectMake(0,0,320, 216);
_datePicker.backgroundColor = [UIColor whiteColor];
_datePicker.datePickerMode = UIDatePickerModeDate;
[_datePicker setMinuteInterval:5];
[_datePicker setTag:10];
[_datePicker addTarget:self action:#selector(Result) forControlEvents:UIControlEventValueChanged];
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
BOOL a;
if (textField.tag==10) {
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
UIView *popoverView = [[UIView alloc] init]; //view
popoverView.backgroundColor = [UIColor blackColor];
[popoverView addSubview:_datePicker];
popoverContent.view = popoverView;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:popoverContent];
navigationController.delegate=self;
UIPopoverController *popoverController = [[UIPopoverController alloc]
initWithContentViewController:navigationController];
popoverController.delegate=self;
[popoverController setPopoverContentSize:CGSizeMake(320, 250) animated:NO];
[popoverController presentPopoverFromRect:textField.frame inView:textField permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
a=NO;
}
else
{
a=YES;
}
return a;
}
-(void)Result
{
NSDateFormatter *formDay = [[NSDateFormatter alloc] init];
formDay.dateFormat=#"MM-dd-yyyy";
NSString *day = [formDay stringFromDate:[_datePicker date]];
_edit_dob.text = day;
}
I'm writing an app that needs to spawn a popover in order to add a new note. To that end, I have something that does kind of the trick, however, I can't seem to adjust the size of the popover. This is how I'm spawning it:
UIButton* btn =sender;
UIViewController* fooTroller = [[UIViewController alloc] init];
CGRect rectFoo = CGRectMake(0, 0, 100, 100);
UIView* fooView = [[UIView alloc] initWithFrame:rectFoo];
[fooView setBackgroundColor:[UIColor redColor]];
[fooTroller setView:fooView];
popOver =[[UIPopoverController alloc] initWithContentViewController:fooTroller];
[popOver presentPopoverFromRect:btn.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionLeft
animated:YES];
Any thoughts? It's not respecting the view size.
You should not be calling setView: on the view controller. Let the view controller setup its own view.
The proper way to size a popover is to either override the contentSizeForViewInPopover method of your view controller to return the size or to set the popoverContentSize property on the popover.
UIButton* btn =sender;
UIViewController* fooTroller = [[UIViewController alloc] init];
popOver = [[UIPopoverController alloc] initWithContentViewController:fooTroller];
popOver.popoverContentSize = CGSizeMake(100, 100);
[popOver presentPopoverFromRect:btn.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionLeft
animated:YES];
I have a button I have created programmatically within a view controller. Once the button is pressed I want it to to use a method to create the popover programmatically.
The button which is created in the ViewDidLoad in my view controller.m
UIView *moreFundInfoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 540, 620)];
[self.view addSubview:moreFundInfoView];
[moreFundInfoView setBackgroundColor:[UIColor RMBColor:#"b"]];
btnContact = [UIButton buttonWithType:(UIButtonTypeRoundedRect)];
[btnContact setFrame:CGRectMake(390, 575, contactButton.width, contactButton.height)];
btnContact.hidden = NO;
[btnContact setTitle:#"Contact" forState:(UIControlStateNormal)];
[moreFundInfoView addSubview:btnContact];
[btnContact addTarget:self action:#selector(showContactDetails:) forControlEvents:UIControlEventTouchUpInside];
Then I have the method I use when the button is pressed.
-(void) showContactDetails: (id) sender
{
UIViewController *popoverContent = [[UIViewController alloc]init];
UIView *popoverView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 300)];
[popoverView setBackgroundColor:[UIColor RMBColor:#"b"]];
popoverContent.view = popoverView;
popoverContent.contentSizeForViewInPopover = CGSizeMake(200, 300);
UIPopoverController *contactPopover =[[UIPopoverController alloc] initWithContentViewController:popoverContent];
[contactPopover presentPopoverFromRect:btnContact.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES ];
[contactPopover setDelegate:self];
}
What am I missing here? Cause it runs fine, but as soon as I click the button the app crashes. I think it is a delegate issue, but I am not sure. Any advice would be appreciated.
I think this code will help you. You are certainly missing delegate methods
ViewController *viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:navigationController];
popover.delegate = self;
popover.popoverContentSize = CGSizeMake(644, 425); //your custom size.
[popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections: UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionUp animated:YES];
Just make sure you are not forgetting UIPopover Delegate methods or else application will definitely crash. It is mandatory.
UIViewController *controller = [[UIViewController alloc] init];
[view removeFromSuperview]; //view is a view which is displayed in a popover
controller.view = view;
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:controller];
popover.delegate = self;
[popover presentPopoverFromRect:button.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
All I had to do was change the property from "retain" to "strong" in the .h file and it works, stopped the app from crashing.
Yes, changing property for "retain" to "strong" makes you to hold your picker view object.
I think the problem with your code was, UIPopoverController object gets deallocated automatically when method finishes.
making strong property gets you to strongly point an object.
I'm attempting to present a popoverView when a barButton is pressed. Unfortunately, the app crashes with the signal SIGABRT every time I try to call it. The "Empty.xib" does have a view designed in it. (As I'm using a barButton, I was unable to use the frame, if you have a workaround for that, please say so too).
- (IBAction)loadPopover:(id)sender
{
UIView *someView = [[UIView alloc] init];
UIViewController *someVC = [[UIViewController alloc] initWithNibName:#"Empty.xib" bundle:[NSBundle mainBundle]];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:someVC];
someView.frame = CGRectMake(0, 44, 320, 372);
someView.backgroundColor = [UIColor lightGrayColor];
popoverController.delegate = self;
self.popoverView = popoverController;
[self.popoverView presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// CGRect popoverRect = [self.view convertRect:[btn frame] fromView:[btn superview]];
CGRect popoverRect = CGRectMake(0, 88, 320, 311);
popoverRect.size.width = MIN(popoverRect.size.width, 100);
[self.popoverView presentPopoverFromRect:popoverRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Remove .xib part from initWithNibName:#"Empty.xib". Change line to this:
UIViewController *someVC = [[UIViewController alloc] initWithNibName:#"Empty" bundle:nil];
Edit:
From here -
The nib file name should not contain any leading path information.
Few suggestions here.
Check if the view's outlet is connected
Why do you need to allocate a UIView like the following? UIView *someView = [[UIView alloc] init];
Check if the sender is of type of UIBarButtonItem
What is the retain policy for self.popoverView? Check if it is retain or strong (if ARC)
Why do you present the popover two times?
Said this, here a simple snippet.
UIBarButtonItem* barButton = (UIBarButtonItem*)sender;
UIViewController *someVC = [[UIViewController alloc] initWithNibName:#"Empty" bundle:[NSBundle mainBundle]];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:someVC];
popoverController.delegate = self;
self.popoverView = popoverController;
[self.popoverView setPopoverContentSize:CGSizeMake(300, 200)];
[self.popoverView presentPopoverFromBarButtonItem:barButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
P.S. Make attention to memory if you don't use ARC.
Hope it helps.
How to add the UIView into UIPopoverViewController
-(void) buttonAction:(id)sender {
//build our custom popover view
UIViewController* popoverContent = [[UIViewController alloc]
init];
UIView* popoverView = [[UIView alloc]
initWithFrame:CGRectMake(0, 0, 200, 300)];
popoverView.backgroundColor = [UIColor whiteColor];
popoverContent.view = popoverView;
//resize the popover view shown
//in the current view to the view's size
popoverContent.contentSizeForViewInPopover =
CGSizeMake(200, 300);
//create a popover controller
self.popoverController = [[UIPopoverController alloc]
initWithContentViewController:popoverContent];
//present the popover view non-modal with a
//refrence to the button pressed within the current view
[self.popoverController presentPopoverFromRect:popoverButton.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
//release the popover content
[popoverView release];
[popoverContent release];
}
This will add the view to your UIPopoverViewController
You can check the following link below to get some idea as to how to do this
Are there examples of how to use UIPopoverController on iOS?
Try the below Code:
if (mycontroller == nil) {
MyController * viewController = [[MyController alloc] initWithNibName:#"ControllerView" bundle:nil];
mycontroller = viewController;
PopoverController = [[UIPopoverController alloc] initWithContentViewController:self.mycontroller];
PopoverController.delegate = self;
}
[PopoverController presentPopoverFromRect:CGRectMake(260, 120, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];