Adding a UIViewController before UIImagePickerController - xcode

I have the following code to load a UIImagePickerController which works fine.
UIImagePickerController *mediaUI = [[UIImagePickerController alloc] init];
mediaUI.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
mediaUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
mediaUI.delegate = self;
[controller presentModalViewController: mediaUI animated: YES];
return YES;
I would like to load a modal view with some help information on how to use the UIImagePickerController:
UIStoryboard *storyboard = self.storyboard;
HelpViewController *svc = [storyboard instantiateViewControllerWithIdentifier:#"HelpViewController"];
[self presentViewController:svc animated:YES completion:nil];
How can I display the UIImagePickerController after the user dismisses the HelpViewController view?

Don't be tempted to move directly from HelpViewController to UIImagePickerController, you need to get there via your mainViewController.
Let's put your code into a method...
- (void) presentImagePicker {
UIImagePickerController *mediaUI = [[UIImagePickerController alloc] init];
mediaUI.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
mediaUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeMovie, nil];
mediaUI.delegate = self;
[controller presentModalViewController: mediaUI animated: YES];
return YES;
}
(Note that presentModalViewController:animated is depracated since ~iOS5, and you should really replace it with
[controller presentViewController:mediaUI animated:YES completion:nil];)
Let's call your viewControllers mainVC, helpVC and imageVC. There are two ways you can implement this.
method 1 - performSelector
The quick-and-slightly-dirty solution is to do this in your helpVC's dismiss button method:
- (IBAction)dismissHelpAndPresentImagePicker:(id)sender
{
UIViewController* mainVC = self.presentingViewController;
[mainVC dismissViewControllerAnimated:NO completion:
^{
if ([mainVC respondsToSelector:#selector(presentImagePicker)])
[mainVC performSelector:#selector(presentImagePicker)];
}];
}
It's slightly dirty because you need to ensure that presentImagePicker is implemented in mainVC - the compiler will give you no warnings if it is not. Also you are running a completion block after it's object has been dismissed, so there's no certainty it's going to work (in practice, it does, but still...)
Note that you have to assign the pointer self.presentingViewController's to a local variable (mainVC). That's because when helpVC is dismissed, it's presentingViewController property is reset to nil, so by the time you get to run the completion block you cannot use it. But the local variable mainVC is still valid.
method 2 - protocol/delegate
The clean way to do this is to use a protocol in helpVC to declare a delegate method, and make mainVC the delegate. This way the compiler will keep track of everything and warn you if it is not correctly implemented.
Here are the steps to do that:
In helpVC.h add this protocol above the #interface section:
#protocol helpVCDelegate
- (void) dismissHelpAndPresentImagePicker;
#end
In helpVC.h interface section declare a property for its delegate:
#property (nonatomic, weak) id <helpVCDelegate> delegate;
(the <helpVCDelegate> tells the compiler that the delegate is expected to conform to the protocol, so it will have to implement dismissHelpAndPresentImagePicker)
In helpVC.m your method can now look like this:
- (IBAction)dismissHelpAndPresentImagePicker:(id)sender
{
[self.delegate dismissHelpAndPresentImagePicker];
}
In MainVC, when you create HelpVC (=svc in your code), set MainVC as it's delegate:
HelpViewController *svc = [storyboard instantiateViewControllerWithIdentifier:#"HelpViewController"];
svc.delegate = self;
[self presentViewController:svc animated:YES completion:nil];
And be sure to implement the delegate method dismissHelpAndPresentImagePicker
- (void) dismissHelpAndPresentImagePicker
{
[self dismissViewControllerAnimated:NO completion:^{
[self presentImagePicker];
}];
}
Personally I would always use method 2. But I offered up a that solution earlier today to a similar question, and the questioner seemed to think protocol/delegate was overcomplicated. Maybe my answer just made it seem so, I have tried to simplify it here.

Related

Why is my window:willPositionSheet:usingRect: delegate method not called?

I need to reposition a NSAlert window. I found out already, that to do that I need to implement the (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect method in the delegate.
My code where I trigger the Alert Window is in the following method:
- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame {
NSAlert* jsAlert = [[NSAlert alloc] init];
[jsAlert addButtonWithTitle:#"OK"];
[jsAlert setMessageText:#""];
[jsAlert setInformativeText:message];
[jsAlert setAlertStyle:NSWarningAlertStyle];
// [jsAlert setDelegate:self];
[jsAlert beginSheetModalForWindow:sender.window modalDelegate:self didEndSelector:#selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
There I set the modalDelegate so self, where self is the AppDelegate. I implemented the following method in the AppDelegate:
- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect {
NSLog(#"we are here: %s", __func__);
return NSMakeRect(0, 0, 100, 100); // just fake
}
This method won't be called. From what I've found in the documentation this should work though and I cannot comprehend why it doesn't.
I also tried the following, i.e. making the AppDelegate comply to the NSWindowDelegate-protocol (and the NSAlertDelegate protocol, when commenting in the uncommented line in the first code snippet).
#interface AppDelegate : NSObject <NSApplicationDelegate, NSAlertDelegate, NSWindowDelegate>
I read everywhere that this should just work. What am I doing wrong here?
The only thing left to do was to actually register the AppDelegate as NSWindowDelegate like this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// [...]
[self.window setDelegate:self];
// [...]
}
This sounds very trivial, but then I needed a hell lot of time to find that out, as all examples I saw didn't do it. They just set modalDelegate to self which in my case should be the AppDelegate.
I hope this helps someone out there...

Make Actionsheet button open another ViewController?

Someone gave me this code, is it correct? if so how do i use it? I am a noob so can you explain in simpler terms for me? Thanks guys :)
- (IBAction)OpenActionSheetButton:(id)sender {
UIActionSheet *actionsheet = [[UIActionSheet alloc]initWithTitle:#"There is no going back,
are you sure???" delegate:self cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Continue" otherButtonTitles:nil, nil];
[actionsheet showInView:self.view];}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:
(NSInteger)buttonIndex
{
if(buttonIndex == 0)
{
UIViewController *controller = [self.storyboard
instantiateViewControllerWithIdentifier:#"storyboardViewIdentifier"];
//storyboardViewIdentifier is the ViewController identifier you specify in the
storyboard
//PUSH
[self.navigationController pushViewController:controller animated:YES];
//Modal
[self presentViewController:controller animated:YES completion:Nil];
}
}
I'm not sure with the case with storyboard, but with the case of XIB, I need to set UINavigationController object as rootviewcontroller, so that I can push from one viewcontroller to another, I think in storyboard it may be the same, if so, see these answers, first and second to set navigation controller as rootviewcontroller in storyboard environment.

IBAction,button and camera

I have a button in my interface declared in .h file
#interface UserProfileVC : UIViewController <UIImagePickerControllerDelegate>{
IBOutlet UIButton *camera;
}
#property (nonatomic,retain) IBOutlet UIButton *camera;
-(IBAction)cameraPress:(id)sender;
And in my .m file i have:
-(IBAction)cameraPress:(id)sender{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
// [picker setDelegate:self];
[picker setAllowsEditing:YES];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:picker animated:YES];
[picker release];
}
But I have this error:
*** -[UserProfileVC performSelector:withObject:withObject:]: message sent to deallocated instance 0x7bc2a40
Can someone help me? I can't understand what is the mistake.
Thanks
As per the code from ur last comment,
-(void)showDetails:(id)sender{
NSLog(#"Annotation Click");
details= [[UserProfileVC alloc] initWithNibName: #"Details" bundle:nil ];
details.Nome=note.title;
addNavigationController = [[UINavigationController alloc] initWithRootViewController:details];
[self.navigationController presentModalViewController:addNavigationController animated:YES];
}
I can suggest you following.
If you look at the UIViewController class reference document, you will find below notes
presentModalViewController:animated:
Presents a modal view managed by the given view controller to the user. (Deprecated. Use presentViewController:animated:completion: instead.)
So I would suggest you to use presentViewController:animated:completion. I dont find it relevant to error "message sent to deallocated instance" but still check if u could solve your problem.
Also I dont know Why u wrote this line
addNavigationController = [[UINavigationController alloc] initWithRootViewController:details];
If you simply want to show UserProfileVC in the current UINavigationController then I would suggest you to remove addNavigationController line & write only
[self.navigationController presentViewController:details animated:YES completion:NULL];

Using a calendar in Xcode 4.2 iPhone

I have been learning Xcode 4.2 for a bit now and still can't get my head round on how the create a calendar so i really hope you guys can help me sort out my errors and maybe tell me what the next step in the code is to get this working i really appreciate your time thanks.
This is the storyboard
.h there are no errors here
#import <UIKit/UIKit.h>
#import <EventKitUI/EventKitUI.h>
#interface FirstViewController : UIViewController <EKEventEditViewDelegate> {
}
-(IBAction) createEvent;
#end
.m this is where the errors are
#import "FirstViewController.h"
#import <EventKitUI/EventKitUI.h>
#implementation FirstViewController
-(IBAction) createEvent {
//Get the event store object
EKEventStore *eventStore = [[EKEventEditViewController alloc] INIT];
//Cretae the EditViewController
EKEventEditViewController* controller = [[EKEventEditViewController alloc] INIT];
controller.eventStore = eventStore;
controller.editViewDelegate = self;
[self presentModalViewController:controler animated:YES];
[controller release];
}
//delegate method for EKEventEditViewDelegate
-(void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action {
[self dismissModalViewControllerAnimated:YES];
}
Errors:
EKEventStore *eventStore = [[EKEventEditViewController alloc] INIT];
Receiver type 'EKEventEditViewController' for instance message does not declare a method with selector 'init'
EKEventEditViewController* controller = [[EKEventEditViewController alloc] INIT];
Receiver type 'EKEventEditViewController' for instance message does not declare a method with selector 'init'
[controller release];
'release' is unavailable: not available in automatic reference counting mode 2
That's all the errors hope you guys can tall me whats wrong i really appreciate it :)
It's init, not INIT.
You need to get rid of the [controller release]; if you're using ARC.
So, change to this:
-(IBAction) createEvent {
//Get the event store object
EKEventStore *eventStore = [[EKEventStore alloc] init];
//Cretae the EditViewController
EKEventEditViewController* controller = [[EKEventEditViewController alloc] init];
controller.eventStore = eventStore;
controller.editViewDelegate = self;
[self presentModalViewController:controler animated:YES];
}

Make AppDelegate's Navigation Controller accessible from DetailViewController of SplitView

My DetailView of a SplitView has a Map with Annotations. Upon clicking an Annotation the entire window (and not just the DetailView) should go to another view. Unfortunately that doesn't work.
This is how I'm creating my NavigationController in my AppDelegate
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
This is how I'm creating the SplitView
left = [[MapSplitViewLeft alloc] initWithStyle:UITableViewStylePlain];
right = [[MapViewController alloc] init];
splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:left,right, nil];
self.view = splitViewController.view;
left.right = right;
[left release];
[right release];
And that's what's being called when clicked on an Annotation:
- (void)showDetails:(id)sender {
NSLog(#"Yes it works");
VenueViewController *vviewcontroller = [[VenueViewController alloc]
initWithNibName:#"VenueViewController" bundle:[NSBundle mainBundle]];
AppDelegate *del = (AppDelegate *)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:vviewcontroller animated:YES];
}
When I click on the Annotation I only get "Yes it works" but nothing else is happening.
Thanks so much for any advise.
Every UIViewController has the property "navigationController". Try with your current ViewController to push the new Viewcontroller.
[self.navigationController pushViewController:vviewcontroller animated:YES];
edit: Sorry, you mean the entire window! I think that would not work.
edit2: Maybe this answer can help you how to add a view over window in uiviewcontroller But i think thats that view is not on your navigationController-Stack

Resources