I am trying to implement a simple UISplitViewController where when in portrait mode the master view is hidden and appears with a button in a popover.
My AppDelegate is set up like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
self.splitViewController =[[UISplitViewController alloc]init];
self.rootViewController=[[RootViewController alloc]init];
self.detailViewController=[[FirstDetailViewController alloc]init];
UINavigationController *rootNav=[[UINavigationController alloc]initWithRootViewController:rootViewController];
UINavigationController *detailNav=[[UINavigationController alloc]initWithRootViewController:detailViewController];
self.splitViewController.viewControllers=[NSArray arrayWithObjects:rootNav,detailNav,nil];
self.splitViewController.delegate=self.detailViewController;
splitViewController.presentsWithGesture = NO;
// Add the split view controller's view to the window and display.
[self.window setRootViewController:self.splitViewController];
[window makeKeyAndVisible];
return YES;
}
in FirstDetailViewController I set up a button like this:
UIImage *buttonImage = [UIImage imageNamed:#"button-menu.png"];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setImage:buttonImage forState:UIControlStateNormal];
aButton.frame = CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
[aButton addTarget:self action:#selector(showNavigation) forControlEvents:UIControlEventTouchUpInside];
aBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aButton];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
showNavigation looks like this:
-(void)showNavigation{
NSLog(#"I am in show navigation and pc=%#",self.popoverController);
[self.popoverController presentPopoverFromRect:self.view.frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
When I initially load the app and press the button I get an NSLog of
I am in show navigation and pc=(null)
And the pop over dosen't show. Now when I rotate the device to landscape mode, and then back to portrait, the master view hides and shows as expected, and the button now works in portrait mode.
Here is the code that handles the rotation:
- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
[[self navigationItem] setLeftBarButtonItem:aBarButtonItem];
[self setPopoverController:pc];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
}
// Called when the view is shown again in the split view, invalidating the button and popover controller.
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
[[self navigationItem] setLeftBarButtonItem:nil];
[self setPopoverController:nil];
self.appDelegate.rootPopoverButtonItem = aBarButtonItem;
}
How do I get the popovercontroller to not be null before any rotation occurs?
Ok turns out I had an if in my willHideViewController which did not include the [self setPopoverController:pc]; line. duh!
Related
I have a split view app that should show a menu button when the device is in portrait orientation and the Master view is hidden.
When the app launches in portrait mode, this function is executed:
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc {
barButtonItem.title = #"Menu";
self.popoverController = pc;
self.rootPopoverButtonItem = barButtonItem;
// Get current detail view (splitVC-->detailNavVC-->currentVC).
UINavigationController *detailNav = [self.splitController.viewControllers objectAtIndex: 1];
UIViewController <SubstitutableDetailViewController> *detailViewController = [detailNav.viewControllers objectAtIndex: 0];
[detailViewController showRootPopoverButtonItem: rootPopoverButtonItem];
}
This function in turn launches the function in TitleViewController.m:
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the toolbar.
NSMutableArray *itemsArray = [toolbar.items mutableCopy];
[itemsArray insertObject: barButtonItem atIndex: 0];
[toolbar setItems:itemsArray animated:NO];
}
All of this code seems to run correctly, but no menu button is showing. Any ideas? Thanks.
I seemed to have solved the problem by adding the following line after setting the toolbar items:
[self.view reloadInputViews];
I am trying to create a camera overlay that can recognize swipe gestures to push to other views.
I am wondering if I can still use the UIImagePicker or if I have to use the AVCaptureSessionManager.
Also i would prefer to create the overlay view in the story board is there a way to do that?
can I select a view inside the storyboard controller be the camera overlay and simply present the UIImagePicker on view did load?
I've never used the Storyboard to create a camera overlay, but I have created a xib which works fine. You can create the overlay viewController in the normal (xib) way, complete with gesture recognizers, then you can handle them directly in that VC or use a delegate (most likely the VC which presented the camera).
Some code -
-(void)setupCamera
{
self.picker = [[UIImagePickerController alloc] init];
_picker.sourceType = UIImagePickerControllerSourceTypeCamera;
_picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.overlay = [[OverlayViewController alloc] init];
_overlay.delegate = self;
_picker.cameraOverlayView = _overlay.view;
_picker.delegate = self;
[self presentViewController:self.picker animated:YES completion:nil];
}
The overlay -
-(id)init
{
self = [super initWithNibName:#"OverlayViewController" bundle:nil];
if (self)
{
// set up stuff
}
return self;
}
... & some code which handles the swipe -
-(IBAction)swipe:(UISwipeGestureRecognizer *)sender
{
// swipe stuff
[self.delegate doSwipeStuff]; // if you want the delegate to handle it
}
Hope this helps.
I've spend hours on this and can't get it to work. Hope that someone can help me.
I have a UIPageViewController which works perfectly when I add it to my default view when the application starts. This is what I do:
//Step 1
//Instantiate the UIPageViewController.
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
//Step 2:
//Assign the delegate and datasource as self.
self.pageViewController.delegate = self;
self.pageViewController.dataSource = self;
//Step 3:
//Set the initial view controllers.
ContentViewController *contentViewController = [[ContentViewController alloc] initWithNibName:#"ContentViewController" bundle:nil];
contentViewController.labelContents = [self.modelArray objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:contentViewController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview: self.pageViewController.view];
Now I want to use a navigation controller in my initial view which then pushes the UIPageViewController on the stack, when the user clicks on a button. This works too, but when I'm in landscape mode the UIPageViewController shows only one page (which is horizontally streched) and not two, as it should be. I need to rotate the device to portrait and then back to landscape mode to force the UIPageViewController to show both pages.
I'm adding the UIPageViewController to the navigation controller with:
[self.navController pushViewController:self.pageViewController animated:NO];
When i debug my code I see that without the navigation controller the delegate methods of the UIPageViewController are called on startup. When I push the UIPageViewController on the navigation controller they're not called until I rotate the device.
Does anyone know how to solve this? Thanks in advance for any help/tips on this.
Figured this out with help from this thread.
The key is setting the spineLocation on the pageViewController when you create it through the options dictionary:
options = [NSDictionary dictionaryWithObject: [NSNumber numberWithInteger:UIPageViewControllerSpineLocationMid]
forKey: UIPageViewControllerOptionSpineLocationKey];
And this option should be put inside of a check to see what the current interface orientation is.
In the above mentioned thread, the interface orientation is checked by a ternary operator; I put it in an if-statement so that I can use the same opportunity to tack an extra UIViewController onto the viewControllers array.
If the interface orientation is portrait, 'options' will still be nil when the pageViewController is created, and so it'll go on to create it in portrait mode with only one viewController.
Here's my whole viewDidLoad code in BookViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
_modelController = [[ModelController alloc] init];
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0
storyboard:self.storyboard];
NSMutableArray *viewControllers = [NSMutableArray arrayWithObjects:
startingViewController,
nil];
NSDictionary *options;
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
DataViewController *secondViewController = [self.modelController viewControllerAtIndex:1
storyboard:self.storyboard];
[viewControllers addObject:secondViewController];
options = [NSDictionary dictionaryWithObject: [NSNumber numberWithInteger:UIPageViewControllerSpineLocationMid]
forKey: UIPageViewControllerOptionSpineLocationKey];
}
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:options];
self.pageViewController.delegate = self;
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
// Set the page view controller's bounds
self.pageViewController.view.frame = self.view.bounds;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
}
I am trying to build a view where a user can select an image and it is retained within that view after navigating away from the view and coming back again. As a simple test app, I have created two view controllers. The first view controller has a forward button and uses a modal segue to go to the second view controller. The second view controller has a back button (modal segue back to first view controller) a Choose button and a Image button. So far I have configured the choose button to use the imagepickercontroller to select an image from the library and display onto the button which works no problem. The issue is that when i press the back button and the forward again back to the same screen the image isn't retained i have to reselect it. The intention is for the user to be able to take a picture or video of themselves performing an action and then select it within this app and have the picture displayed there for future reference.
My coding is as follows:
ViewController.h
#interface ViewController : UIViewController
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
{
IBOutlet UIButton *selectFromPhotoLibraryButton;
IBOutlet UIButton *displayPictureButton;
}
#property (nonatomic, retain) UIButton *selectFromPhotoLibraryButton;
#property (nonatomic, retain) UIButton *displayPictureButton;
- (IBAction)selectPicture;
#end
ViewController.m
#implementation ViewController
#synthesize selectFromPhotoLibraryButton;
#synthesize displayPictureButton;
-(IBAction)selectPicture
{
if([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypePhotoLibrary])
{
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info
{
UIImage *image = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
[displayPictureButton setImage:image forState:UIControlStateNormal];
[self dismissModalViewControllerAnimated:YES];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *) picker
{
[picker dismissModalViewControllerAnimated:YES];
}
Please let me know if you require any of the other bits of code (its only the default app stuff, no further modification).
As looking to your problem
I think you have to store selected image in NSUserDefault as archived data or something like that.
When u come back to second view then check first in NSUserDefault for image is saved or not.
If u got it then assign it to UIImage object by unarchiving.
As I have not implemented it so can't be sure.
I've just set something like this up myself, I have the chosen image immediately placed in a UIImageView.
First, set up your view controller as a UIImagePickerDelegate:
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
Then wherever you want to init the UIImagePicker, alloc, init and set its delegate to self:
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[self presentViewController:imagePicker animated:YES completion:nil];
And then I have the image picker storing the UIImage into the ImageView and also into the NSUserDefaults.
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo: (NSDictionary *)info {
UIImage *image = [[info objectForKey:UIImagePickerControllerOriginalImage] retain];
[userDefaults setObject:image forKey:#"image"];
[userDefaults synchronize];
[self dismissViewControllerAnimated:YES completion:^{
[self updatePreviewImage:image];
}];
}
- (void) imagePickerControllerDidCancel:(UIImagePickerController *) picker {
[self dismissViewControllerAnimated:YES completion:nil];
}
I hope this works for you, and anyone else that view this post.
I'm using a split view for an iPad app.
In my RootViewController.m file I assign two UIBarButtonItems like this
- (void)viewDidLoad
{
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 300.0);
// add a save button
saveButton = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSave
target:self action:#selector(saveAction:)] autorelease];
self.navigationItem.rightBarButtonItem = saveButton;
// add a cancel button
cancelButton = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(cancelAction:)] autorelease];
self.navigationItem.leftBarButtonItem = cancelButton;
}
These buttons show up nicely when I use UITableViewStylePlain styling for the table view. But if I use UITableViewStyleGrouped, then the buttons disappear. Here is how I set my grouped style
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithStyle:UITableViewStyleGrouped];
return self;
}
Regardless of the presence or absence of the buttons, the size of the header remains the same.
I'm clueless as to why this happening.
all help greatly appreciated
Dhoti