UIDocumentInteractionController not appearing on iPad but working on iPhone - ios

I'm trying to display a UIDocumentInteractionController on my app. Everything is working perfectly on iPhone, but nothing is happening on iPad. Here is my code:
interactionController = [UIDocumentInteractionController interactionControllerWithURL:imageFile];
interactionController.UTI = #"com.instagram.photo";
interactionController.annotation = [NSDictionary dictionaryWithObject:[self commentForInstagram] forKey:#"InstagramCaption"];
[interactionController presentOpenInMenuFromRect:self.view.frame inView:self.view animated:YES];
interactionController is a strong reference to an instance, and imageFile exists. On iPhone, it brings up the 'Open With..' dialog and Instagram is present. On iPad, absolutely nothing happens when the above code runs. Yes, I do have Instagram installed and working on my iPad.
What could be the reason that nothing is happening when the code is executed? self.view and self.view.frame are valid objects (tested on debug).
Thanks, Can.

On iPad UIDocumentInteractionController appearing like Pop Up
Try something like this:
-(void)shareClick:(UIButton*)sender {
/*some code*/
CGRect rectForAppearing = [sender.superview convertRect:sender.frame toView:self.view];
[interactionController presentOptionsMenuFromRect:rect inView:self.view animated:YES];
}

For iPad you have to meet these 2 things:
Define area for DocumentActionMenu
CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0);
[interactionController presentOpenInMenuFromRect:rect inView:self.view animated:YES];
Use iPad, not simulator

Use presentOptionsMenuFromRect:inView:animated:.
For example, if you want the menu to be presented from the bottom, try
[interactionController presentOptionsMenuFromRect:self.view.bounds inView:self.view animated:YES];

I had the same problem earlier today.
First of all, do not pass the frame of your view to presentOptionsMenuFromRect:inView:animated. The given rect is supposed to be in the coordinates of the view. The frame of the view is in the coordinates of the view's superview.
On iPhone, passing the bounds of the view worked, but on iPad, Xcode (7.2.1) would complain about unsatisfiable constraints and not display the document interaction controller's view (DIC).
Instead of the bounds, I tried to pass CGRectZero as the first parameter which anchors the DIC in the upper left corner of the view. This works but it looks bad.
In order to position the DIC at the center of the bottom edge of the view, you can specify a rect of size CGSizeZero positioned at the center of the bottom edge of the view (use the view's bounds to compute the position). This works and looks ok.

presentOptionsMenuFromRect:inView: - This is talking about where the popover arrow points.
The view is the view that the arrow points at, and the rect is the rect inside the view that the arrow points at.
Once you understand that this is easy.
- (void)shareClick:(UIButton*)sender
{
/*some code*/
[interactionController presentOptionsMenuFromRect:sender.bounds inView:sender animated:YES];
}
So now the arrow will point to an edge of the bounds of the button.
Most of the time this is what you want but you could for example inset this rect to have the arrow point inside the button.

I had the same issue. I checked the frame that is being passed and saw that x and y are set to 0. Next I tried to change those values (by keeping width and height as passed) and the popup showed up. Here the code:
-(void)openDocument:(UIView*)senderView {
CGRect rectForAppearing = [senderView convertRect:senderView.frame toView:senderView];
if (isIPAD)
rectForAppearing = CGRectMake(100, 100, rectForAppearing.size.width, rectForAppearing.size.height);
[interactionController presentOptionsMenuFromRect:rect inView:self.view animated:YES];
}
The popup appears on an Ipad in the top right corner. You can of course twist those 100,100 parameters to your desire. On iPhones i leave the popover as is (at the bottom)

Related

Need to set pop up at top instead of inposition centre

I just followed one project for use pop up.But in that project the pop up view position is in centre.But i need to show pop up at top (i.e should show up in top with use half space of navigation bar)github project
I use UIViewController+ENPopUp.m UIViewController+ENPopUp.h JWBlurView.h JWBlurView.m files.I have changed all values .But not able to show pop up at top.i need to show pop up at this image position
But in that project the position is in centre. Knindly any one can help me out.I need show pop up at top Like this image
Thanks in advance !
Your question is not clear.I assume that you want to show pop at top of your viewcontroller instead of that project popup showing at centre.If so, then this is your solution:
I will explain with that github project that you post in your question.
you can change what ever you want in your own project. Go to ENViewController.m.And change the code to
- (IBAction)showPopUp:(id)sender
{
UIViewController *vc = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"PopUp"];
vc.view.frame = CGRectMake(20, 30, 270.0f, 230.0f);
[self presentPopUpViewController:vc];
}
You can also change your popup viewcontroller size and update that size,height in this line on your showpopup action method:
vc.view.frame = CGRectMake(20, 30, Any size, Any height);
And if you want to change your postion of pop up view means .you can use any X , Y Values in this line on your showpopup action method:
vc.view.frame = CGRectMake(x, Y, Any size, Any height);
Then go to UIViewController+ENPopUp.m On under //Customize popUpView.delete one line(i have comment that).
// Customize popUpView
popUpView.layer.cornerRadius = 8.0f;
popUpView.layer.masksToBounds = YES;
popUpView.layer.zPosition = 99;
popUpView.tag = kENPopUpViewTag;
//popUpView.center = overlayView.center;
[popUpView setNeedsLayout];
[popUpView setNeedsDisplay];
[overlayView addSubview:popUpView];
[sourceView addSubview:overlayView];
Hope this helpfull.If not please ask your question clear .Let me know !

Why would an activity indicator show up properly on iPhone but not on iPad?

I have my app setup to show this view when it is loading data:
self.loadingView = [UIView new];
self.loadingView.frame = CGRectMake(0, 0, self.tableView.frame.size.width, self.view.frame.size.height);
self.loadingView.backgroundColor = [UIColor groupTableViewBackgroundColor];
[self.view addSubview:self.loadingView];
[self.view bringSubviewToFront:self.loadingView];
self.activityIndicator = [UIActivityIndicatorView new];
self.activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
self.activityIndicator.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
[self.view addSubview:self.activityIndicator];
[self.view bringSubviewToFront:self.activityIndicator];
[self.activityIndicator startAnimating];
Then, I remove it from its superview. It works on iPhone. It works on iPad sometimes too, except for when I'm using the same code in a UISplitViewController. I've tried various adjustments to centering the views, etc., but can't figure it out. What's going wrong?
I've add trouble with activity indicators in the past as well. Make sure you are not calling the startAnimating or stopAnimating while any animations are taking place. I recommend calling the startAnimating selector in viewDidLayoutSubviews.
The line where you set the center of the indicator looks like the source of the problem. self.view.frame.size is probably equal to screen size at this point and so when you show that view controller over the whole screen it's ok, but inside a split view controller it's not because indicator is off-bounds. You can check that from Xcode's Debug -> View Debugging -> Capture View Hierarchy (while the app is running).
Try setting activity indicator's center using autolayout and it should work.

UIPopover equal screen width

I need to make popover size Equal device screen width, is it possible? I try such code:
ShareViewController *shareVC = [[ShareViewController alloc] init];
sharePopover = [[UIPopoverController alloc] initWithContentViewController:shareVC];
sharePopover.popoverContentSize = shareVC.view.frame.size; // width there is 1024 i'm sure
sharePopover presentPopoverFromRect:CGRectMake(sender.frame.origin.x, sender.frame.origin.y + 10, sender.frame.size.width, sender.frame.size.height) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
also i tried to set width in popoverContentSize by number like 1024, or bigger, but no effect, i have some spaces in left and right, how can i fix it?
Here screenshot of problem:
http://uaimage.com/image/c54d471d
From Apple's UIPopoverController documentation, regarding the 'popoverLayoutMargins' property (can be found here: UIPopoverController documentation:
The margins that define the portion of the screen in which
it is permissible to display the popover....
...The edge inset values are measured in points from the edges of the screen,
relative to the current device orientation...
...The default edge insets are 10 points along each edge.
Try adding the following and see if it helps:
sharePopover.popoverLayoutMargins = UIEdgeInsetsZero;

Translucent Modal ViewController - how to handle rotation

I would like to display a UIViewController modally and be able to see a blurred version of the view that presented it.
Following a number of similar questions such as this:
iOS 7 Translucent Modal View Controller
I have added a background to my controller's view that is based on the captured view of the presenting controller. The problem I am facing is that my app supports multiple orientations and when the modal view is presented and rotated, the underlying background image no longer matches.
I tried grabbing a fresh snapshot of the presenting viewController in didRotateFromInterfaceOrientation: of the modal viewController, but it appears that the UI of the presenting viewController is not being updated and the resulting image is still the wrong orientation. Is there any way to force redrawing of a view that is being hidden by the modal one?
After long considerations, I have come up with a passable way to handle it. How well it will work depends a bit on the type of content you have in the presenting viewController.
The general idea is to take not one, but two screenshots before presenting a new viewController - one for portrait, one for landscape. This is achieved by changing the frames of the top viewController and navigation bar (if applicable) to emulate a different orientation, taking the screenshot of the result, and changing it back. The user never sees this change on device, but the screen grab still displays a new orientation.
The exact code will depend on where you are calling it from, but the main logic is the same. My implementation runs from AppDelegate because it is reused by several subclasses of UIViewController.
The following is the code that will grab the appropriate screenshots.
// get references to the views you need a screenshot of
// this may very depending on your app hierarchy
UIView *container = [self.window.subviews lastObject]; // UILayoutContainerView
UIView *subview = container.subviews[0]; // UINavigationTransitionView
UIView *navbar = container.subviews[1]; // UINavigationBar
CGSize originalSubviewSize = subview.frame.size;
CGSize originalNavbarSize = navbar.frame.size;
// compose the current view of the navbar and subview
UIImage *currentComposed = [self composeForeground:navbar withBackground:subview];
// rotate the navbar and subview
subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.height, originalSubviewSize.width);
// the navbar has to match the width of the subview, height remains the same
navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalSubviewSize.height, originalNavbarSize.height);
// compose the rotated view
UIImage *rotatedComposed = [self composeForeground:navbar withBackground:subview];
// change the frames back to normal
subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.width, originalSubviewSize.height);
navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalNavbarSize.width, originalNavbarSize.height);
// assign the variables depending on actual orientations
UIImage *landscape; UIImage *portrait;
if (originalSubviewSize.height > originalSubviewSize.width) {
// current orientation is portrait
portrait = currentComposed;
landscape = rotatedComposed;
} else {
// current orientation is landscape
portrait = rotatedComposed;
landscape = currentComposed;
}
CustomTranslucentViewController *vc = [CustomTranslucentViewController new];
vc.backgroundSnap = portrait;
vc.backgroundSnapLandscape = landscape;
[rooVC presentViewController:vc animated:YES completion:nil];
The method composeForeground:withBackground: is a convenience method that generates an appropriate background image based on two input views (navigation bar + view controller). Aside from composing the two view together, it does a bit more magic to make the result look more natural when rotating the presented viewController. Specifically, it extends the screenshot to a 1024x1024 square and fills the extra space with a mirrored copy of the composed image. In many cases, once blurred this looks good enough since the animation of the views re-drawing for the orientation change is not available.
- (UIImage *)composeForeground:(UIView *)frontView withBackground:(UIView *)backView {
UIGraphicsBeginImageContextWithOptions(backView.frame.size, 0, 0);
[backView.layer renderInContext:UIGraphicsGetCurrentContext()];
// translation is necessary to account for the extra 20 taken up by the status bar
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), frontView.frame.origin.x, frontView.frame.origin.y);
[frontView.layer renderInContext:UIGraphicsGetCurrentContext()];
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -frontView.frame.origin.x, -frontView.frame.origin.y);
// this is the core image, would have left it at this if we did not need to use fancy mirrored tiling
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// add mirrored sections
CGFloat addition = 256; // 1024 - 768
if (newImage.size.height > newImage.size.width) {
// portrait, add a mirrored image on the right
UIImage *horizMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationUpMirrored];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width+addition, newImage.size.height), 0, 0);
[horizMirror drawAtPoint:CGPointMake(newImage.size.width, 0)];
} else {
// landscape, add a mirrored image at the bottom
UIImage *vertMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationDownMirrored];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height+addition), 0, 0);
[vertMirror drawAtPoint:CGPointMake(0, newImage.size.height)];
}
// combine the mirrored extension with the original image
[newImage drawAtPoint:CGPointZero];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// for ios 6, crop off the top 20px
if (SYSTEM_VERSION_LESS_THAN(#"7")) {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height-20), NO, 0);
[newImage drawAtPoint:CGPointMake(0, -20)];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return newImage;
}
The resulting landscape and portrait images can be blurred and tinted as desired, and set as background for the presented viewController. Use willRotateToInterfaceOrientation:duration: method of this viewController to select the appropriate image.
Note: I have tried to reduce the amount of work done on images and graphics contexts as much as possible, but there is still a slight delay when generating the background (around 30-90 ms per composeForeground:withBackground: iteration, depending on the content, on a vintage slow iPad 2). If you know of a way to further optimize or simplify the above solution, please share!

How do I keep my modal dialog close to the top in both landscape modes objective-c

I'm using this to change the width and height of the modal dialog
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterface {
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
self.view.superview.frame = CGRectMake(74, 170, 380.0f, 712.0f);
}
}
The self.view.superview.frame = CGRectMake(74, 170, 380.0f, 712.0f); works will on the one landscape but when you turn the iPad around the y position is to low. It needs to be at the same y position for both landscapes.
edit
This seams to work. Not sure if its the best answer. Will accept better answers.
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
self.view.superview.frame = CGRectMake(174, 170, 380.0f, 712.0f);
self.view.superview.transform = CGAffineTransformTranslate(self.view.superview.transform,0,-72);
}
If we are talking here about a UIVIewcontroller presented with the help of PresentModalViewcontroller.
We should not change the height and width of the view controller.
Presentation styles are provided by apple :
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/c/econst/UIModalPresentationFormSheet
Also if you want to create, custom modal, you can create by transitioning using CATransition on simple UIViews.

Resources