In Xcode 4 I've created a SplitView project, so I have a DetailViewController and a RootViewController.
In RootViewController's viewDidLoad(), I have added a cancel button on the left side like this
// add a cancel button on the left side
cancelButton = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self action:#selector(cancelAction:)] autorelease];
self.navigationItem.leftBarButtonItem = cancelButton;
When the RootViewController is displayed and I click on the cancel button, I want to close the RootViewController. In my cancelButton handler I've tried calling
#if 0
[self dismissModalViewControllerAnimated:YES];
#else
[self.navigationController popViewControllerAnimated:YES];
#endif
but neither one of them work for me. I've tried googling for hours but have still not found a solution.
Can someone please tell me how to close the RootViewController?
thanks for your help
I'm assuming you're trying to close popover of RootViewController in portrait orientation because in landscape it doesn't make sense.
You can do it like this:
1) cancel button handler:
-(void)cancelAction {
[self.detailViewController.popoverController dismissPopoverAnimated:YES];
}
2) popoverController is private in detailViewController so you must make it public (or add method to detailview that will have access to popoverController property and call this method from cancelAction in RootViewController):
2.1) delete
#property (nonatomic, retain) UIPopoverController *popoverController;
from
#interface DetailViewController ()
...
#end
2.2) add
#property (nonatomic, retain) UIPopoverController *popoverController;
inside
#interface DetailViewController : UIViewController
Related
First I subclass UIView named MyTextEditorView for overwrite it's inputAccessoryView as readwrite property.
#property (retain, readwrite) UIView *inputAccessoryView;
And I initial UIInputView as display view,then add one UIView as subview;
UIInputVIew *myInputAccessoryView = [[UIInputView alloc] initWithFrame:CGRectMake(0,0,screenWidth,44)];
[myInputAccessoryView addSubview:myDisplayView];
[self setInputAccessoryView:myInputAccessoryView];
[self reloadInputViews];
And I have overriden canBecomeFirstResponder for return YES;
- (BOOL)canBecomeFirstResponder
{
return YES;
}
When I first initial MyTextEditorView in my viewController1 and make it become first responder,then inputAccessoryView automatically appear.But when I push another viewController2 from this viewController1 and back to viewController1 ,inputAccessoryView will not automatically appear after make it become first responder.
However,when I add some code as following:
UIInputVIew *myInputAccessoryView = [[UIInputView alloc] initWithFrame:CGRectMake(0,0,screenWidth,44)];
[myInputAccessoryView addSubview:myDisplayView];
[self setInputAccessoryView:myInputAccessoryView];
[self resignFirstResponder];
[self reloadInputViews];
[self becomeFirstResponder];
After then, this inputAccessoryView can automatically appear in any case.But this confused me and anyone can help me raise why the inputAccessoryView can't appear automatically?Thanks in advance!!!
I test this question on both iOS7 and iOS8. And I find it's an iOS8 bug.After I replace UIActionSheet with UIAlertController on iOS8 platform, this works well.
I guess that UIActionSheet as subclass of UIView is different from UIAlertController as subclass of UIViewController which maybe conflicts with my editor
I have the following files:
Main.storyboard
This is the same as the default storyboard created when creating a new project with a few additions: There is a button in the view which is connected to the button outlet of the view controller (instance of ViewController) and the doTheThing: action on the view controller.
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (weak) IBOutlet NSButton *button;
#property (weak) NSViewController *controller;
#end
#implementation ViewController
- (IBAction)doTheThing:(id)sender {
if (self.controller) {
NSLog(#"Removing %#", self.controller);
[self.controller.view removeFromSuperview];
[self.controller removeFromParentViewController];
} else {
self.controller = [[NSStoryboard storyboardWithName:#"Another" bundle:[NSBundle mainBundle]] instantiateInitialController];
[self addChildViewController:self.controller];
[self.view addSubview:self.controller.view];
NSLog(#"Adding %#", self.controller);
}
}
#end
Another.storyboard
A simple storyboard containing a single scene (view controller + view) that is set to the initial controller and is an instance of AnotherViewController. There is a label in the view that is not connected to any outlet.
AnotherViewController.m
#import "AnotherViewController.h"
#interface AnotherViewController ()
#property (weak) IBOutlet NSTextField *label;
#end
#implementation AnotherViewController
- (void)dealloc {
NSLog(#"Deallocing AnotherViewController %#", self);
}
#end
When I run the app and click the button, it adds the view controller and view from Another.storyboard, and when I click the button again they are removed and the instance of AnotherViewController is deallocated.
However, if I connect the label in Another.storyboard to the label outlet on the AnotherViewController, the deallocation never occurs. Why is this and what can I do to fix it?
Edit: I do have a few workarounds, but they aren't very desirable and I would prefer to understand why the recommended way (storyboards and outlets) isn't working properly.
Undesirable workaround 1: Do the same thing but load the view controller and view from a XIB file. This works as expected, but ideally I would be able to do the same thing using storyboards.
Undesirable workaround 2: Bind all my outlets manually in code in the view controller's viewDidLoad method. This is just tedious and ugly as it requires iterating through all the view's subviews and comparing identifiers.
Apple have confirmed (via bug report) that this is a known issue and will be fixed in OS X 10.10.3.
Title: UIDocumentInteractionController dismissing the popup when clicking anywhere in the navigation bar.
My code works find. It works well in my iPhone and iPad simulator for the most part. It does what I want., however, my issue is dismissing the default popup menu. It goes away if I click in the view area, it goes away if I pick an option in the popup, and it also goes away if I click in the tab bar area. This is good. However if I click anywhere in the navigation bar it stays put. And if I click any of the items in the navigation bar it crashes. I would like the default popup to dismiss if I click in the navigation bar as well.
outputURLViewController.h
#import <UIKit/UIKit.h>
#interface outputURLViewController : UIViewController<UIDocumentInteractionControllerDelegate,UIPopoverControllerDelegate>
{
IBOutlet UIWebView *previewWebView;
}
#property (nonatomic, strong) NSString *outputURLString;
#property (nonatomic, strong) NSString *outputURLName;
#property (nonatomic, retain) UIWebView *previewWebView;
#property (nonatomic, strong) UIDocumentInteractionController *docController;
- (IBAction)actionButton:(id)sender;
#end
outputURLViewController.m
#import "outputURLViewController.h"
#interface outputURLViewController ()
{
NSArray *myButtonArray;
UIBarButtonItem *myActionButton;
}
#end
#implementation outputURLViewController
#synthesize outputURLString;
#synthesize outputURLName;
#synthesize previewWebView;
- (void)viewDidLoad
{
[super viewDidLoad];
//Creates my action put and put it in the right side of navigation bar
myActionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(actionButton:)];
myButtonArray =[[NSArray alloc] initWithObjects:myActionButton, nil];
self.navigationItem.rightBarButtonItems = myButtonArray;
NSURL *url = [[NSBundle mainBundle] URLForResource:outputURLString withExtension:#"pdf" subdirectory:#""];
//displays my document in the webview
[previewWebView loadRequest:[NSURLRequest requestWithURL:url]];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
//action that display my options in a default popup menu
- (IBAction)actionButton:(id)sender
{
NSURL *url = [[NSBundle mainBundle] URLForResource:outputURLString withExtension:#"pdf" subdirectory:#""];
if (url) {
self.docController = [UIDocumentInteractionController interactionControllerWithURL:url];
self.docController.delegate = self;
[self.docController presentOptionsMenuFromBarButtonItem:myActionButton animated:NO];
}
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application{}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application{}
//dismiss my popup menu in the view, but not the navigation bar when click
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller{}
#end
As you can see it very simple default popup menu code. It does what I want. I just trying to figure how to prevent it from crashing when a navigation item button is click before the popup is dismissed.
My Error that I get is:
Terminating app due to uncaught exception 'NSGenericException', reason: '-[UIPopoverController dealloc] reached while popover is still visible.'
My DocumentInteractionControllerDidDismissOptionsMenu: does work when I click in the view or any where else except the navigation bar. So is there away to prevent anyone from clicking another button in the navigation bar until the uidocumentinteractioncontroller is dismissed or have it dismiss when they tap in the navigation bar area? Or is this a normal bug that doesn't have a fix?
Decide to hide the navigation items when the popup is active.
I used this code in the myActionButton section
if ( IDIOM == IPAD ) {
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.hidesBackButton = YES;
}
and this code in my documentInteractionControllerDidDismissOptionsMenu
if ( IDIOM == IPAD ) {
self.navigationItem.rightBarButtonItem = myActionButton;
self.navigationItem.hidesBackButton = NO;
}
I'm trying to get a reference to my detailViewController in application didFinishLaunchingWithOptions: method. But here I am faced with a problem.
I have next Views structure is storyBoard (for iPad):
UISplitViewController --> UINavigationController --> UITableViewController --> detailViewController
I created segue with "push" style between UITableViewControllerCell and detailViewController
Screenshot: http://picturepush.com/public/13071076
I'm trying to get a reference to detailViewController in this way:
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
DetailViewController *detailViewController = [navigationController.viewControllers lastObject];
But in result I got reference to my UITableViewController, instead of acceptable
DetailViewController. The navigationController.viewControllers count is 1 but there should be 2 (I think so).
I hope for your help.
Since you created a segue with push style, the detailViewController will only be loaded after you tap on a table view cell. It will not be loaded on the app didFinishLaunchingWithOptions method.
I would suggest you try to make the detailViewController as a property in your table view controller.
#property (nonatomic, strong) UIViewController *detailViewController;
Then in your app didFinishLaunchingWithOptions method, you can access the property:
UITableViewController *tableViewController = [navigationController.viewControllers lastObject];
DetailViewController *detailViewController = tableViewController.detailViewController;
But you will need to avoid using perform segue function and push the detail view controller whenever it is needed with the usual pushViewController method.
[self.navigationController pushViewController:self.detailViewController animated:YES];
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.