in iOS8: UIPopoverController presentPopoverFromRect not work for keyWindow any more - uipopovercontroller

As titled, in iOS8, [UIPopoverController presentPopoverFromRect] does not work for [UIApplication sharedApplication].keyWindow any more. (It does work in iOS7)
I verified following codes:
TestViewController *test = [[TestViewController alloc] initWithNibName:nil bundle:nil];
if (testPopoverController == nil) {
testPopoverController = [[UIPopoverController alloc] initWithContentViewController:test];
testPopoverController.popoverContentSize = CGSizeMake(250, 95*5);
}
CGPoint point = [sender convertPoint:CGPointMake(0, 0) toView:nil];
CGRect rect = CGRectMake(point.x, point.y, 24, 24);
[testPopoverController presentPopoverFromRect:rect inView:[UIApplication sharedApplication].keyWindow permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

The best solution I've come up with is to handle it conditionally. If on iOS 7, use the working code we had for presenting a UIPopoverController on the key window. If on iOS 8, use the following:
viewController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *presentationController = viewController.popoverPresentationController;
[presentationController setDelegate:self];
presentationController.permittedArrowDirections = 0;
presentationController.sourceView = [[UIApplication sharedApplication] keyWindow];
presentationController.sourceRect = [[UIApplication sharedApplication] keyWindow].bounds;
[viewController setPreferredContentSize:CGSizeMake(320, 480)];
[parentController presentViewController:viewController animated:YES completion:nil];
This ends up functioning identically to:
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:viewController];
[self.popoverController setDelegate:self];
[self.popoverController setPopoverContentSize:isLandscape() ? CGSizeMake(480*2, 320*2) : CGSizeMake(320*2, 480*2)];
[self.padPopover presentPopoverFromRect:CGSizeMake(320, 480)
inView:[[UIApplication sharedApplication] keyWindow]
permittedArrowDirections:0
animated:YES];

Change the inView parameter in
[testPopoverController presentPopoverFromRect:rect inView:[UIApplication sharedApplication].keyWindow permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
to
[testPopoverController presentPopoverFromRect:rect inView:"your current View Controller's view" permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
And make sure it is in dispatch block
dispatch_async(dispatch_get_main_queue(), ^{
});
Also kip changing your rect origin n size values if it is within the bounds

Try the solution found at this link: http://github.com/werner77/WEPopover
1st, let's do this code:
if ([viewController respondsToSelector:#selector(setPreferredContentSize:)]) {
viewController.preferredContentSize = CGSizeMake(200, 300.0f);
} else {
viewController.contentSizeForViewInPopover = CGSizeMake(200.0f, 300.0f);
}
self.popoverController = [[popoverClass alloc] initWithContentViewController:viewController];
if ([self.popoverController respondsToSelector:#selector(setContainerViewProperties:)]) {
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
}
self.popoverController.delegate = self;
[self.popoverController presentPopoverFromRect:[sender bounds]
inView:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
I hope this helps. It was tested and works for iOS6-iOS8.
PS. Don't forget to check viewDidLoad, and give thanks to the WEPopover Library.

I think you have to display it in full view/viewcontroller and not in [UIApplication sharedApplication].keyWindow
So change this code:
[testPopoverController presentPopoverFromRect:rect inView:[UIApplication sharedApplication].keyWindow permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
to:
[testPopoverController presentPopoverFromRect:rect inView:aViewControllerInYourApp permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

Related

View shifted across to the right

I am trying to figure out why this tableView is shifted across to the right, it appears in every view the app uses, yet the app itself displays fine, it's only when the tableView appears is everything shifted out of the screen.
I believe the initializing is here;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Lets load the frame");
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame: frame];
self.contentSizeForViewInPopover = CGSizeMake(320, 480);
m_mywork = nil;
dataArray = [LoadSessionController loadTableData:YES];
}
Here is the initializing from another class;
on iPad display is perfect.
- (void) ShowInitialMenu
{
InitialMenuController *MewMgrController = [[InitialMenuController alloc] initWithStyle:UITableViewStyleGrouped];
MewMgrController.delegate = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController: MewMgrController];
if(![ColorSplashAppDelegate isiPad]){
[self presentViewController:navController animated:YES completion:nil];
}
else{
UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:navController];
popover.delegate = self;
[popover presentPopoverFromRect:CGRectMake(30.0, 940.0, 30.0, 480.0)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
ColorSplashAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.popoverController = popover;
}
[navController release];
[MewMgrController release];
[self enableUserAction:YES];
}
Try This.
-(void)viewDidLayoutSubviews
{
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame: frame];
self.contentSizeForViewInPopover = CGSizeMake(320, 480);
m_mywork = nil;
}

UIPopoverController for iphone in ios8 shows white screen

Using UIPopovercontroller below ios8.0 in iphone working fine with this code. But in ios8 it display white screen.
Code :
pickerController = [[UIViewController alloc] init];
UIView *viewV = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 160)];
[viewV setBackgroundColor:[UIColor clearColor]];
popOverController = [[UIPopoverController alloc] initWithContentViewController:pickerController];
popOverController.popoverContentSize = CGSizeMake(150, 160);
[popOverController setDelegate:self];
CGRect ImageBtnFrame = [self.view convertRect:sender.frame fromView:self.view];
[popOverController presentPopoverFromRect:ImageBtnFrame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
Any alternative for ios8, need suggestion.
According to 2014 WWDC, in the 30 minute mark, the right answer is:
- (void) tapButton:(id) sender
{
MyViewControllerClass * vc = [[MyViewControllerClass alloc] init];
vc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController * popOverController = vc.popoverPresentationController;
[popOverController setDelegate:self];
popOverController.sourceView = sender;
popOverController.sourceRect = ((UIButton*)sender).frame;
popOverController.permittedArrowDirections = UIPopoverArrowDirectionUp;
[self presentViewController:vc
animated:YES
completion:nil];
}
Notice that the accepted answer has some problems like:
Not setting the modalPresentationStyle
Presenting the UIPopoverPresentationController * instead of the UIViewController
Try to use the new iOS 8 API for popovers.
pickerController = [[UIViewController alloc] init];
UIView *viewV = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 160)];
[viewV setBackgroundColor:[UIColor clearColor]];
UIPopoverPresentationController *popOverController = pickerController .popoverPresentationController;
popOverController.popoverContentSize = CGSizeMake(150, 160);
[popOverController setDelegate:self];
popOverController.sourceView = self.view;
popOverController.sourceRect = sender.frame;
popOverController.permittedArrowDirections = UIPopoverArrowDirectionUp;
[self presentViewController:popOverController
animated:YES
completion:nil];
That will cause on iOS 8. So, I recommended to use following Github library.
https://github.com/skywinder/ActionSheetPicker-3.0 or you can write code base on iOS version.
if (OLDER_THAN_IOS_8) {
// Your regular code
pickerController = [[UIViewController alloc] init];
UIView *viewV = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 160)];
[viewV setBackgroundColor:[UIColor clearColor]];
popOverController = [[UIPopoverController alloc] initWithContentViewController:pickerController];
popOverController.popoverContentSize = CGSizeMake(150, 160);
[popOverController setDelegate:self];
CGRect ImageBtnFrame = [self.view convertRect:sender.frame fromView:self.view];
[popOverController presentPopoverFromRect:ImageBtnFrame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
} else {
// New Code that support iOS -8 using UIPopoverPresentationController
// Checkout #AndreasZ answer for the same
}

UIPopoverController presentPopoverFromRect not displaying correctly

I am loading a popover view that displays the camera view. everything works however it dose not dsplay any bigger than a playing card on the iPad. No matter what I do I cannot resize it only change its position.
This is the code I use
[self.popOver presentPopoverFromRect:CGRectMake(44, 6, 111, 111) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
How can I adjust the size?
Update
This is what my whole method looks like:
- (void) cameraButtonSelected
{
// create picker
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.preferredContentSize = CGSizeMake(400.0, 400.0);
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
CGFloat scaleFactor=1.3f;
picker.cameraViewTransform = CGAffineTransformScale(CGAffineTransformMakeRotation(M_PI * -90 / 180.0), scaleFactor, scaleFactor);
}
// create popover
self.popOver = [[UIPopoverController alloc] initWithContentViewController:picker];
[self.popOver presentPopoverFromRect:CGRectMake(44, 6, 111, 111) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
try settings this property to the controller contained in popover
someViewController.contentSizeForViewInPopover = CGSizeMake(200.0, 200.0)
try using
preferredContentSize
property.
sorry I don't have a mac on me to check it
You should try to set the size in viewWillAppear:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.popover.preferredContentSize = ...
}
Nothing worked for me, so I resized the popoverController after displaying it like this:
[popoverController presentPopoverFromRect:cell.mediaComment.frame
inView:cell
permittedArrowDirections:UIPopoverArrowDirectionRight
animated:YES];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
popoverController.contentViewController.preferredContentSize = REQUIRED_RECT.size;
popoverView.frame = REQUIRED_RECT;
});

Show dynamic result in a UIPopoverController

I can't set data inside the viewController "searchController" managed by a UIPopoverController:
in viewDidLoad i have:
searchController = [[PopOverSearchController alloc] initWithNibName:#"PopOverSearchController" bundle:nil];
popoverController = [[UIPopoverController alloc] initWithContentViewController:searchController];
I do a method for call this popover that work fine:
if ([popoverController isPopoverVisible]) {
[popoverController dismissPopoverAnimated:YES];
} else {
searchController.data = data;
[searchController.tableResult reloadData];
CGRect popRect = CGRectMake(self.searchBar.frame.origin.x,
self.searchBar.frame.origin.y +15,
self.searchBar.frame.size.width,
self.searchBar.frame.size.height);
[popoverController presentPopoverFromRect:popRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
[searchController.tableResult reloadData]; was not called: the popup appear (above the search bar )but with an empty table

How to attach a UIPopover to a rectangle I have drawn

I have an iPad app (XCode 4.6, ios 6.2, ARC and Storyboards). I have drawn a GCRect on a position of a UIView.
CGRect rectangle = CGRectMake( [appSelected.aPosX floatValue], [appSelected.aPosY floatValue],[appSelected.aPosW floatValue], [appSelected.aPosH floatValue]);
I have a method that does the drawing for me; this is the code for that method:
-(void)showHTMLHelp:(NSString *)htmlString pointTo:(id)target background:(UIColor *)bgColor {
UIViewController* popoverContent = [[UIViewController alloc] init];
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
popoverView.backgroundColor = [UIColor colorWithWhite:(CGFloat)1.0 alpha:(CGFloat)1.0]; // frame color?
popoverContent.view = popoverView;
//resize the popover view shown in the current view to the view's size
popoverContent.contentSizeForViewInPopover = CGSizeMake(200, 300);
// add the UIWebView for RichText
UIWebView *webView = [[UIWebView alloc] initWithFrame:popoverView.frame];
webView.backgroundColor = [UIColor whiteColor]; // change background color here
// add the webView to the popover
[webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:nil]];
[popoverView addSubview:webView];
//create a popover controller
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
//present the popover view non-modal with a refrence to the button pressed within the current view
if([target isKindOfClass: [UITextField class]])
[popoverController presentPopoverFromRect:((UITextField *)target).frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
else if([target isKindOfClass: [UISegmentedControl class]])
[popoverController presentPopoverFromRect:((UISegmentedControl *)target).frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
else if([target isKindOfClass: [UIButton class]])
[popoverController presentPopoverFromRect:((UIButton *)target).frame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
else
[popoverController presentPopoverFromRect:*(CGRect *)CFBridgingRetain(target)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
Now I want to have a UIPopover point to that rectangle. Since GCRect is a C structure, I can't figure out how to do it. This is what I tried, but obviously it's wrong. How can I do this? This is the code where I call the method to display the popover:
PreferencesViewController *pvc = [[PreferencesViewController alloc] init];
[pvc showHTMLHelp:html pointTo: rectangle background:[UIColor whiteColor]];
There is absolutely no problem with passing a C structure (or C primitive variable) to an Objective-C method. In fact, presentPopoverFromRect:inView:permittedArrowDirections:animated: takes a simple CGRect as you can tell by the header (or the documentation):
- (void)presentPopoverFromRect:(CGRect)rect
inView:(UIView *)view
permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections
animated:(BOOL)animated;
Simply call it like this:
[popoverController presentPopoverFromRect:rectangle
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
And as Mar0ux already pointed out, it's CGRect, not GCRect. CG stands for Core Graphics.
May i ask you why you are sending an CGRect and casting it to 'id'? Where is the sense?! I would prefer to change your parameter type to CGRect too.
Kind regards.

Resources