Creating a UIPopoverController - objective-c

I'm creating a popover in Xcode 4.3.
I don't get any error messages but when I click build and run and I press the button that is supposed to open the popover screen, the app crashes and highlights in green a line in my code and says:
Thread 1: breakpoint 2.1..
What does this mean and how can I fix it?
- (IBAction)popOver
{
SecondView *secondview = [[SecondView alloc] init];
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:secondview];
[popover setDelegate:self];
[popover presentPopoverFromRect:CGRectMake(801, 401, 300, 200) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
[popover setPopoverContentSize:CGSizeMake(300, 200)];
}
Thanks in advance.

Few suggestions here...
First, are you using Automatic Reference Counting (ARC)? if yes you need to have an instance variable to control your UIPopoverController. For example:
#property (strong, nonatomic) UIPopoverController* popover;
if you are not using ARC create a retain one:
#property (retain, nonatomic) UIPopoverController* popover;
In the first case you have to do this because if not, ARC will release for you the just created popover at the end of your IBAction. In addition you do this to have a reference for your popover. See NOTE. This is valid also if you don't use ARC.
NOTE At some point you could have the necessity to release the popover. For example in - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController do
self.popover = nil;
Then, if your SecondView is a UIViewController call it SecondViewController. But this is a simple naming suggestion.
Finally, the correct way for display the popover from the action sender (e.g a UIButton), instead of hardcode positions, could be:
- (IBAction)openPopover:(id)sender
{
// create the popover here...
UIButton* senderButton = (UIButton*)sender;
[popover setPopoverContentSize:CGSizeMake(300, 200)];
[popover presentPopoverFromRect:senderButton.bounds inView:senderButton permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}

-(IBAction)showpop:(id)sender
{
UIPopoverController *pop = [[UIPopoverController alloc]initWithContentViewController:popoverview];
[pop setDelegate:self];
[pop presentPopoverFromRect:popbutton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}

The SecondView that you're passing into UIPopOverController is a UIView. Make it a UIViewController, because, what UIPopOverController expects is a UIViewController.
-Suraj

Make sure you simulate on iPad device
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
// We are using an iPhone
UIActionSheet *alertSheet = [[UIActionSheet alloc] initWithTitle:#"Where do you want to get your daily image?" delegate:(self) cancelButtonTitle:#"Cancel" destructiveButtonTitle:nil otherButtonTitles:#"Camera", #"Library", nil];
[alertSheet setTag:0];
[alertSheet setDelegate:self];
[alertSheet showFromTabBar:[[self tabBarController] tabBar]];
[alertSheet release];
}else {
// We are using an iPad
/// here you should pass UIViewController inside the popover
/// follow #flexaddicted notes to implement the popover
}

Check below link for popover tutorial in ios
UIPopOverController Tutorial

Related

Creating multiple subviews inside view controller

I have a view controller named ViewController.
ViewController displays a UIView that has a button on it, which allows me to advance to a second view controller - SecondViewController.
SecondViewController also has a button on it, which allows me to advance to a third view controller.
However, I am having trouble displaying ThirdViewController. When I tap the button in SecondViewController it throws an error:
Warning: Attempt to present ... on ... whose view is not in the window hierarchy!
I have been to a bunch of other sites and posts that address this issue, but cannot seem to find a working solution. I have implemented quite a few solutions, but none seem to work.
Here is my code:
- (void)secondaryView:(UIView *)secondaryView
{
UIView *theView = secondaryView;
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.frame = [UIScreen mainScreen].bounds;
[viewController.view addSubview:theView];
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:viewController animated:YES completion:nil];
}
secondaryView is a UIView that I am constructing elsewhere in the application. I add it to the viewController then present the viewController.
Is there any way to dynamically create UIViewControllers, add a UIView to each one, and add them to the window hierarchy?
If you can use navigation in your ViewControllers, you can try the below code
In the place where you call the firstViewController,
-(void)callFirst
{
FirstViewController *first = [FirstViewController alloc] init];
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:first];
navigationController.modalPresentaionStyle = UIModalPresenationFormSheet;
[self presentModalViewController:navigationController animated:YES];
}
And in the FirstViewController button action ,you can write
-(void)callSec
{
SecondViewController *sec = [SecondViewController alloc] init];
[self.NavigationController pushViewController:sec animated:YES];
}
And in SecondViewController you can do the same
-(void)callThird
{
ThirdViewController *third = [ThirdViewController alloc] init];
[self.NavigationController pushViewController:third animated:YES];
}
Try this...And in these ViewControllers you can do whatever coding you want to meet the requirement like
-(void)viewDidLoad
{
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(20,20,400,400)];
newView.backGroundColor = [UIColor redColor];
[self.view addSubView:newView];
}

presentPopoverFromBarButtonItem

I am trying to display my popover menu whenever the user clicks on a button.
I have two methods, the first creates the button
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *btnMenu = [[UIBarButtonItem alloc]initWithTitle:#"Forms List" style:UIBarButtonItemStyleBordered target:self action:#selector(showPopover:)];
self.navigationItem.leftBarButtonItem = btnMenu;
}
And the second is called by the first, to display the popover
-(IBAction)showPopover:(id)sender{
NSLog(#"called with %#", sender);
self.popoverController = popoverController;
popoverController.delegate = self;
[popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Presently, when I click the button nothing happens. I think the problem lies in the second method, mainly the presentPopoverFromBarButtonItem line.
Any help would be appreciated, I don't really understand how that method call works.
Thanks.
EDIT 1:
Here is the code where I (think) initialize the popoverController
#interface DetailViewController ()
#property (nonatomic, retain) UIPopoverController *popoverController;
- (void)configureView;
#end
#implementation DetailViewController
#synthesize toolbar, popoverController, detailItem, detailDescriptionLabel;
Have you initialized your UIPopoverController?
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:VCTHATGOESINSIDE];
If all else fails, try presenting it from rect and specify a CGRect. Hope this helps!
edit: initWith*Content*ViewController

iOS iPad UIActionSheet Issue

I am currently developing an application which needs an option to 'share' using multiple services; such as email, twitter.
To to this, I have a UIBarButtonItem coded in and when touched, it triggers this:
UIActionSheet *sheet = [[UIActionSheet alloc]
initWithTitle:#""
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
[sheet addButtonWithTitle:#"Email"];
[sheet addButtonWithTitle:#"Tweet"];
[sheet addButtonWithTitle:#"Cancel"];
sheet.cancelButtonIndex = sheet.numberOfButtons-1;
[sheet showFromRect:self.view.bounds inView:self.view animated:YES];
[sheet release];
In conjunction with this to detect which button is selected:
clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == actionSheet.cancelButtonIndex) { return; }
switch (buttonIndex) {
case 0:
{
[self emailThis];
break;
}
case 1:
{
[self tweetThis];
break;
}
}
This works a treat on the iPhone. But unfortunately it displays incorrectly on the iPad. It looks like it is trying to display the UIPopoverController, but it is positioned center of the navbar with practically no height.
I have looked into using the UIPopoverController, but I cannot seem to find out how to use it with buttons. Is there anyway I can adapt the code above to properly display the buttons, as it's trying to already.
Many thanks,
Ryan
PS: I'm new to objective-c/iOS coding, so please be specific. Thank you :)
EDIT:
I have tried using:
[sheet showFromBarButtonItem:[self share] animated:YES];
But it doesn't work. Here is my code for the button:
UIBarButtonItem *share = [[UIBarButtonItem alloc]
initWithTitle:#"Share"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(loadShare)];
self.navigationItem.rightBarButtonItem = share;
[share release];
Also here is the code in the .h file:
#interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
UIBarButtonItem *share;
}
#property (nonatomic, retain) IBOutlet UIBarButtonItem *share;
Here is the debug error:
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '* -[__NSPlaceholderArray
initWithObjects:count:]: attempt to insert nil object from objects[0]'
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(actionPhotoShare:)] autorelease];
...
-(void)actionPhotoShare:(id)sender
{
actionSheetShare = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:NSLocalizedString(#"ActionSheet_Cancel", #"")
otherButtonTitles:NSLocalizedString(#"ActionSheet_Email", #""),nil];
if (IS_DEVICE_IPAD) {
[actionSheetShare showFromBarButtonItem:sender animated:YES];
}else {
[actionSheetShare showInView:self.view];
}
}
Instead of [sheet showFromRect], use [sheet showFromBarButtonItem], and point it to your Share UIBarButtonItem.
Note: you may need to create an IBOutlet or ivar for your UIBarButtonItem if you don't have one already, but that's extremely simple and I'm guessing you can do that.
Your issue is that you are using showFromRect with the rect being the entire screen. That means the popup is placing the "arrow" the best it can to center on the screen. What you want is either showFromBarButtonItem or pass in the rect (self.shareButtonItem.frame) of the button.

Having trouble getting UIImagePickerController Working

I have two classes: View1 and SelectImage. View1 imports SelectImage. SelectImage is used to present a UIView to the user which allows them to select how to grab a photo from their device. Tapping a button in that list then sends a message to one of the methods below...
In this code:
-(void)importFromCamera:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];
[self presentModalViewController:imagePicker animated:YES];
}
-(void)importFromPhotoLibrary:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[imagePicker setDelegate:self];
[self presentModalViewController:imagePicker animated:YES];
}
-(void)importFromSavedPhotosAlbum:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
UIViewController *viewController = [UIViewController alloc];
[imagePicker setDelegate:self];
[self presentModalViewController:imagePicker animated:YES];
}
the compiler complains:
Receiver type 'SelectImage' for instance message does not declare a
method with selector 'presentModalViewController:animated:'
At each instance of [self presentModalViewController:imagePicker animated:YES];
Not sure what I'm missing. I've looked around and can only find examples that keep everything in one class.
Is it because the class is a UIView and not a UIViewController? I'm pretty sure I have the necessary delegate protocols in place: .
I'm trying to keep this functionality contained in a class to allow other views to use it as well (View2, View3, etc).
Thanks!
Yes. presentModalViewController is a method on UIViewController not UIView
Note that on iOS 5 the preferred method to use is:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
SelectImage class could have a delegate which your UIViewController implements. The action methods of your buttons on SelectImage class would call your delegate (ie. the UIViewController).
SelectImage should be a UIViewController. Call it SelectImageController, then view1 can add it's view like [view1 addSubview:self.selectImageController.view];

Loading an OverlayView from XIB -vs- programmatically for use with UIImagePickerController

I am currently making a camera app for iPhone and I have a strange phenomenon that I can't figure out. I would appreciate some help understanding.
When recreating an overlay view for passing to UIImagePickerController, I have been successfully been able to create the view programmatically. What I haven't been able to do is create the view with/without controller in IB, load it and pass it to the overlay pointer successfully. If I do it via IB, the view is not opaque and obscures the view of the camera completely. I can not figure out why.
I was thinking that the normal view pointer might be assigned when loading from XIB and therefore overwrite the camera's view, but I have an example programmatically where view and overlayView are set equal in the controller class. Perhaps the load order is overwriting a pointer?
Help would be appreciated... kind regards.
This works fine...
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// dislodge the MainView from the MainViewController
//
MainViewController *aController = [[MainViewController alloc] init]; //WithNibName:#"MainView" bundle:nil];
aController.sourceType= UIImagePickerControllerSourceTypeCamera;
aController.delegate= aController;
aController.showsCameraControls= NO;
// Programmatically load the MainView from the Nib and assign it as the OverlayView instead
//
NSArray* nibViews= [[NSBundle mainBundle] loadNibNamed:#"MainView" owner:aController options:nil];
UIView* uiView= [nibViews objectAtIndex:0];
uiView.opaque= NO;
uiView.backgroundColor= [UIColor clearColor];
aController.cameraOverlayView= uiView;
self.mainViewController = aController;
[aController release];
mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
[window addSubview:[mainViewController view]];
[window makeKeyAndVisible];
}
This DOESN'T...
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// dislodge the MainView from the MainViewController
//
MainViewController *aController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
aController.sourceType= UIImagePickerControllerSourceTypeCamera;
aController.delegate= aController;
aController.showsCameraControls= NO;
aController.cameraOverlayView= aController.view;
self.mainViewController = aController;
[aController release];
mainViewController.view.frame = [UIScreen mainScreen].applicationFrame;
[window addSubview:[mainViewController view]];
[window makeKeyAndVisible];
}