I am trying to show a UIImagePickerController from a button click. When I click the button, I get a SIGABRT at the line:
[self presentModalViewController:camera animated:YES];
from the code block:
camera = [[UIImagePickerController alloc]init];
[camera setSourceType:UIImagePickerControllerSourceTypeCamera];
[camera setDelegate:self.view];
camera.showsCameraControls = NO;
camera.navigationBarHidden = YES;
camera.wantsFullScreenLayout = YES;
camera.toolbarHidden = YES;
camera.cameraOverlayView = bottomArrow;
[self presentModalViewController:camera animated:YES];
where camera is the name of the UIImagePickerController defined as such:
UIImagePickerController *camera;
in the #interface.
My interface declaration is:
#interface cameraViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> {
Can someone see what I'm doing wrong?
Besides the good point made by #Vikings, always check if your device has a camera before trying to use it:
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[camera setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[camera setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
Make sure you are using the both the Navigation Controller Delegate and the Image Picker Controller Delegate. The Image Picker is actually a Navigation Controller, which is why you have to implement its delegate.
#interface YourViewController : UITableViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
Also, set the delegate correctly, not to the view, but the View Controller.
camera.delegate = self;
The delegate needs to be set to the View Controller, and not the View Controller's View.
Check out the code below:
(1) You do not need to hide the navigation bar, because there is not one
(2) You do not need to hide the toolbar, because there is not one
(3) You do not need to specify wantsFullScreenLayout, because a Modal View Controller will always take up the full screen
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.showsCameraControls = NO;
// Comment out the line below to make sure it is not causing a problem.
// This just expects a view, so if bottomArrow is a view you should be fine
picker.cameraOverlayView = bottomArrow;
[self presentModalViewController:picker animated:YES];
Also, I did not realize you were loading this code in viewDidLoad, this will crash, because the View Controller itself is not finished it's transition, so you cannot begin another transition. Instead use viewDidAppear for the same effect:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
// Place code here
}
Do not put your code in viewDidLoad create one IBAction and put your code inside that function.
and set delegate to your view controller. and in .h file make sure that your wrote
<UIImagePickerControllerDelegate>
[camera setDelegate : self];
Related
I have page-based app. On each page I have 3 uibuttons at the top, uiscrollview with alphabet (uibuttons to sort data in uitable) at the right and uitableview at the center. How to show cell's detail view? If it is necessary to add uinavigationcontroller I can't do this. If I adds it, it disables interaction with my table, buttons and scrollview.
And another question is how to show new data in tableview and scrollview when goes to next page??
I have rootViewController class and DataViewController class.
rootViewController listing:
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#end
#implementation RootViewController
#synthesize pageViewController = _pageViewController;
#synthesize modelController = _modelController;
#synthesize navContr = _navContr;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
//[self presentModalViewController:navContr animated:YES];
self.pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil] autorelease];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = [NSArray arrayWithObject:startingViewController];
[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];
self.navContr = [[UINavigationController alloc] initWithRootViewController:self.pageViewController];
[self.view addSubview:self.navContr.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[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;
for (UIGestureRecognizer *recognizer in self.pageViewController.gestureRecognizers){
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){
[recognizer setEnabled:NO];
}
}
}
After few manipulations it works but I need help to get it work fine!
So now it looks like this
Next question: how do I remove the brown space at the top???
::UPDATE::
Problem solved. It needs just to set y-axis position of UINavigationController to -20 ;)
i'm not sure if this link about creating navigation-based project may help you.. (http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html)
From that tutorial, there's a class called SampleViewController, subclass of UIViewController. You might want to put a tableView in SampleViewController.xib file. Then in your SampleViewController.h file, add an IBOutlet UITableView* yourTable property and synthesize it. Connect it to your tableView in your .xib file. //Or you may do it programmatically
in your SampleViewController.h, make your interface header look like this.. I think you already know this...
#interface SampleViewController:UIViewController < UITableviewDelegate, UITableViewDatasource >
in your SampleViewcontroller.m, under viewDidLoad method, set the table delegate and datasource to self:
yourTableView.delegate = self;
yourTableView.datasource = self;
Afterwhich, you implement tableView delegate and datasource methods... //you already know those since you were already able to show a tableview ;)
one of these methods is the "tableview:didSelectAtIndexpath:" --> this is the part wherein you can put your code when you click one of the cells.
Let's assume you have the DetailsViewController Class, this is the class you would like to show after clicking a cell and show its details.
DetailsViewController Class must have a variable that will accept the data you would like to show. Let's say, an NSString *detailsMessage; //do the #property and #synthesize thing...
Let's go back to SampleViewController.m file, under tableview:didSelectAtIndexpath: Method:
inside that Method.. put these codes.
DetailsViewController *detailsVC = [[DetailsViewController alloc] init];
detailsVC.detailsMessage = #"The Data you want to pass.";
[self.navigationController pushViewController:detailsVC animated:YES];
I hope this helps. :(
There may be other ways but by far the easiest way is to use a navigation controller. In fact, it is built to do exactly this.
If you don't want the navigationBar then you can hide it in the viewWillAppear function.
[self.navigationController setNavigationBarHidden:YES animated:YES];
Then you can add an other UIViewController to push when the user selects a cell.
Having read your OP again I'm not sure how you are adding your navigationController.
To use a navigationController you create it and load it at start time. You then create your current viewController (the one with the buttons and table etc...) and set this as the rootViewController of the navigationController.
Then you display the navigationController.
Could you explain how you are adding your navigationController as it may help understand what is going wrong.
Thanks
::EDIT::
OK, my assumption was correct.
The way you are using the navigation controller is not how it was intended.
OK, so at the moment your AppDelegate file will have a method Application didFinishLaunching...
It will look something like this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
You should change it so that it is like this...
first add a property to your appDelegate...
#property (nonatomic, strong) UINavigationController *navigationController;
Then change the didFinishLaunchingMethod to this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
This will still show you MainViewController but it will now be contained within a navigationController.
Next in your MainViewController function viewWillAppearAnimated add the line...
[self.navigationController setNavigationBarHidden:YES animated:animated];
This will then hide the navigationBar at the top of the view so you still have access to your buttons.
The you need a new ViewController and xib file (for example DetailViewController).
When the user selects a table row you need to then do something like...
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//pass in details of which row was selected.
[self.navigationController pushViewController:detailView animated:YES];
This will then display your new view and new viewController. You will also need to write a way of passing the data in (set up a property on the DetailViewController).
Hope this helps.
I'm not sure how to do this. So I originally had a ViewController that had one .xib, with one main view. I present it like this:
DogViewController *dvc = [[DogViewController alloc] initWithNibName:#"DogViewController" bundle:nil];
dvc.modalPresentationStyle = UIModalPresentationFormSheet;
dvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:dvc animated:YES];
[dvc release];
So that works fine. However now from a button press in the DogViewController.xib, I want to dismiss the current form sheet, and show another form sheet with some additional questions before proceeding. So I started by adding another view to in my original .xib of DogViewController, then got stuck in the logic of how to dismiss the first one, and show the second one. I'm assuming I need some outlet to the new view in the same .xib, but from there I'm lost. Thanks.
The way to do this would be to set it up with a UINavigationController as Mathiew mentions. However, if you really want to transition between two views on one view controller, you can refer to this sample code from Apple:
http://developer.apple.com/library/ios/#samplecode/ViewTransitions/Introduction/Intro.html
The code uses ImageViews to demonstrate the effect but I don't see why you can't use views instead :)
You can add a view within the other view in front of all of the other objects and just use its hidden property to control whether it's shown or not.
Why don't you use a navigation controller in your modal view, create another xib and do a [self.navigationController pushViewController:secondViewController animated:YES];
If you have a good reason, you can set a second view outlet secondView and use code like
UIView* superview = [self.view superview];
[self.view removeFromSuperView];
[superview addSubview:self.secondView];
Very simple solution is to hold reference to MainViewController and call methods on it that swap between two view controllers.
Like this:
#implementation MainViewController
- (void)showDogViewController {
[self dismissModalViewControllerAnimated:YES];
DogViewController *dvc = [[DogViewController alloc] initWithNibName:#"DogViewController" bundle:nil];
dvc.modalPresentationStyle = UIModalPresentationFormSheet;
dvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
dvc.mainViewController = self;
[self presentModalViewController:dvc animated:YES];
[dvc release];
}
- (void)showCatViewController {
[self dismissModalViewControllerAnimated:YES];
CatViewController *cvc = [[CatViewController alloc] initWithNibName:#"CatViewController" bundle:nil];
cvc.modalPresentationStyle = UIModalPresentationFormSheet;
cvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cvc.mainViewController = self;
[self presentModalViewController:cvc animated:YES];
[dvc release];
}
}
#end
#implementation DogViewController
- (void)showCatViewController {
[mainViewController showCatViewController]
}
#end
#implementation CatViewController
- (void)showDogViewController {
[mainViewController showDogViewController]
}
#end
Here's my goal:
I'd like to show the UIImagePickerController from a TabBarController and once the photo is taken, I want the "Use" button to take me another view controller.
My problem:
I have MainCameraTabController which inherits from UIViewController and serves as the class that orchestrates the launching of UIImagePickerController and the picker's delegate. When the picker is finished, I try to launch another a different ViewController from MainCameraTabController but I get the error,
*** Assertion failure in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:
If I put a timed delay between when the UIImagePickerController is dismissed and when I launch the next controller, it works okay but I'd like to do this more elegantly.
Is there a better way to structure my class inheritance so that I can have MainCameraTabController display the Picker and then a 2nd view controller?
// #
// # 1. Create the tab bar and add the MainCameraTabController:
// #
// tab1Controller and tab3Controller are also created
cameraTabController = [[MainCameraTabController alloc] init];
tabBarController = [[UITabBarController alloc] init];
NSArray *tabViewControllers = [NSArray arrayWithObjects:tab1Controller,
cameraTabController
tab3Controller, nil];
tabBarController.viewControllers = tabViewControllers;
self.window.rootViewController = self.tabBarController;
// #
// # 2. MainCameraTabController interface & implementation
// #
#interface MainCameraTabController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
{
}
- (void)showCamera;
#end
#implementation MainCameraTabController
// #
// # 3. Show the camera when the view loads
// #
- (void)viewDidLoad
{
[self startCameraController:self usingDelegate:self];
}
- (void)showNextController
{
FollowupController *fc = [[FollowupController alloc] initWithNibName:#"SomeView" bundle:nil];
// THIS IS THE PROBLEM
[self presentModalViewController:cameraPicker animated: YES];
}
- (BOOL)startCameraController:(UIViewController *)controller
usingDelegate:(id <UIImagePickerControllerDelegate, UINavigationControllerDelegate>)pickerDelegate
{
UIImagePickerController *cameraPicker = [[UIImagePickerController alloc] init];
// configure the cameraPicker
// #
// # Apple's doc specifies that UIImagePickerController must be launched with
// # presentModalViewController
// #
[controller presentModalViewController:cameraPicker animated: YES];
}
// UIImagePickerControllerDelegate method called when photo taking is finished
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// work to handle the photo
// Dismiss the picker
[[picker parentViewController] dismissModalViewControllerAnimated: YES];
[picker release];
[self showNextController];
}
#end
And on a related note, I checked to see what the picker's parentViewController is when
imagePickerController:didFinishPickingMediaWithInfo
is invoked and the parent is not MainCameraTabController but instead UITabBarController. Not sure why this is the case.
Because of the animation when dismissing the view, you need delay for the animation to finish before it can execute the next animation. You can solve this by setting the animated to NO. This will cut the animation and execute the next one immediately.
For the views, i had the similar experience, what i did was to switch the sequence of the views. I launched the view that i want to show after the picker first, in the viewDidload method, i created and display the picker so after the picker is dismissed, it will show the view that i want. If you want to make them look natural you could always play with the hidden property of the view to smoothen the flow.
I need help figuring out how to change out the view in my application. I have a wonderfully working view that I have finished and now I'd like to be able to switch the view to a brand new, blank white screen to display.
I have these files:
HelloAppDelegate.h,
HelloAppDelegate.m,
HelloViewController.h, and
HelloViewController.m
Then, I added a new View Controller so now I have two more files:
SecondViewController.h and
SecondViewController.m
In my first view (HelloViewController), I have a button. When the user presses this button, I'd like SecondViewController to show up. So, in my HelloViewController.m, I have an action method
-(IBAction)switchToSecondView:(id)sender {
}
In this method, how can I go about initializing my second view and displaying it?
Thanks in advance!
If you want to do something like flipping view, making it modal and then returning back to the main view do following:
Define a delegate to indicate that secondary view finished its work
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish;
#end
In main view do following:
- (void)flipsideViewControllerDidFinish {
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)showInfo {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
In secondary view do following:
- (IBAction)done {
[self.delegate flipsideViewControllerDidFinish];
}
I am very new to Obj-C and learning iphone development.
My question is how to add subview from app delegate.
Lets say I added subview called "MainView" from "applicationDidFinishLaunching" method.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aViewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = aViewController;
[aViewController release];
[window addSubview:mainViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
"MainView.xib" file has a button to show its child view. When the button is clicked, it calls "showChildView" method.
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.view insertSubview:childViewController.view atIndex:0];
}
From this code, when app launches, it shows "MainView" with a button. But when I clicked the button, the button is still visible as well as the content from the "ChildView.xib" file too.
How can I hide the "MainView" when I pressed the button and show only the contents of the "ChildView"?
Thanks for your help in advance.
well, you have to remove the original view first, before inserting the new subview, do it this way
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.mainViewControlle.view removeFromSuperView];
[self.view insertSubview:childViewController.view atIndex:0];
}
Hope this helps.
You might want to check out the Utility App sample -- it demonstrates switching between two views with animation and adding/removing views from parent views.
you might want to create a navigation controller in the main view and than push the childviewcontroller onto it when invoking showChildView. You'll get the back navigation button for free that way