This is a fun one... I have an application that has a help screen and is displayed as a modal view. The main view has an action that occurs when the device is shaken. I do not want the action to occur (sounds are played) when the help screen has been displayed.
I have tried a few things... here is my code:
To display the help screen:
- (IBAction)helpButtonPressed:(id) sender {
helpViewController = [[HelpViewController alloc] init];
[self presentModalViewController:helpViewController animated:YES];
}
To release the help screen:
- (IBAction)buttonPressed:(id) sender {
[self dismissModalViewControllerAnimated:YES];
}
I tried the following with no success:
if ([helpViewController.view isHidden ]) {
NSLog(#"Shake -- helpView is loaded");
} else {
NSLog(#"Shake -- helpView is not loaded");
}
if ([helpViewController isViewLoaded]) {
NSLog(#"Shake -- helpView is loaded");
} else {
NSLog(#"Shake -- helpView is not loaded");
}
if ([self isViewLoaded]) {
NSLog(#"Shake -- helpView is loaded");
} else {
NSLog(#"Shake -- helpView is not loaded");
}
What I was thinking is if there is a function to allow me to detect if the help view is showing, I will return without playing the sounds when the device is shaken....
Any ideas?
I'm assuming that the view controller which loads the modal controller is also the view controller that responds to the shake action. If that's the case, then you can use the parent view controller's modalViewController property to see whether the modal controller is active:
if(self.modalViewController != nil) {
// Modal view controller is active; do nothing
NSLog(#"Shake -- helpView is loaded");
return;
} else {
// No modal view controller; take action
NSLog(#"Shake -- helpView is not loaded");
[self performSomeAction];
}
Related
I had a view controller which is initialised in appdelegate.I was added that viewcontroller to the navigation controller with addsubview methode,inorder to show it above the navigation bar.Now i am adding another viewcontrollers view as the subview of this view.Now when i am pressing a button on the subview i need to perform some methodes in the superview.I tried this way`
appdelegate.viewcontroller =(ViewController*)self.view.superview;
}
if(appdelegate.viewcontroller==nil)
{
NSLog(#"appdelegate viewcontroller nil");
}
else
{
[appdelegate.viewcontroller setmessage:#""];
}
`But it is giving me error like
[UIView setmessage:]: unrecognized selector sent to instance.Can anybody point me in where i am going wrong?
for (UIView* next = [self.view superview]; next; next = next.superview)
{
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]])
{
[(UIViewController*)nextResponder viewWillAppear:YES];
}
}
When I try to dismiss my UIImagePickerController, it crashes the app. the error is: "Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'preferredInterfaceOrientationForPresentation must return a supported interface orientation!'"
I have the preferred interface orientation set in my view controller.
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
- (BOOL) shouldAutorotate {
return YES;
}
Here is the method I'm calling to bring up the camera, this works fine for adding the camera, but like I said, crashes when I try to remove the camera.
-(IBAction)addCamera:(id)sender
{
self.cameraController = [[UIImagePickerController alloc] init];
self.cameraController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraController.cameraViewTransform = CGAffineTransformScale(self.cameraController.cameraViewTransform,
1.13f,
1.13f);
self.cameraController.showsCameraControls = NO;
self.cameraController.navigationBarHidden = YES;
self.wantsFullScreenLayout = YES;
ar_overlayView = [[UIView alloc] initWithFrame:CGRectZero];
self.view = ar_overlayView;
[self.cameraController setCameraOverlayView:ar_overlayView];
[self presentViewController:cameraController animated:NO completion:nil];
[ar_overlayView setFrame:self.cameraController.view.bounds];
}
-(IBAction)back:(id)sender
{
[ar_overlayView removeFromSuperview];
[cameraController dismissViewControllerAnimated:NO completion:nil];
}
Alright, found the solution, it was really simple, I just changed my back method to:
[self dismissModalViewControllerAnimated:YES];
Now my camera goes away and I can see my original view when I press the back button.
I still haven't figured out what was causing the original problem as I've gone through the info.plist and the methods for supported orientations, but this accomplishes what I wanted.
I'm still curious as to what was causing the error though if anyone has any ideas.
You can try remove this method:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
It will fix it.but sometimes it will lead to reduce stateBar height.
You cannot remove a UIViewController's main view from its superview.
Instead of this:
self.view = ar_overlayView;
Try this:
[self.view addSubview:ar_overlayView];
Then you will be able to remove it from the superview correctly.
You should be using the didFinishPickingMedieWithInfo method similar to below and use [self dismissModalViewControllerAnimated:YES];
-(void) imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
NSLog(#"Camera");
}
else {
NSLog(#"Album");
}
[self dismissModalViewControllerAnimated:YES];
}
I don't think you need to add ar_overlayView to the current view yourself if it's a camera overlay.
Here's what your code is doing now:
Add ar_overlayView to the current view
Add ar_overlayView as the camera's overlay view
Show the camera view (modal)
At this point, ar_overlayView is being displayed twice. When you send it the removeFromSuperview message on dismissing the camera view, it might be getting confused since it's in two view hierarchies at the same time.
Skipping the self.view = ar_overlayView; or [self.view addSubview:ar_overlayView]; lines should fix the problem.
Also, dismissViewControllerAnimated:completion: should be sent to the same object that presentViewController:animated:completion was called on (self in this case):
-(IBAction)addCamera:(id)sender
{
// -- snip -- //
ar_overlayView = [[UIView alloc] initWithFrame:self.cameraController.view.bounds];
[self.cameraController setCameraOverlayView:ar_overlayView];
[self presentViewController:self.cameraController animated:NO completion:nil];
}
-(IBAction)back:(id)sender
{
[self dismissViewControllerAnimated:NO completion:nil];
}
I have 15 buttons on my app, which are displayed as an image. When I click on an image the getEventContact function is called which brings up a modal view controller. In this next view a contact is selected - the modal view is dismissed and the setEventContact function is run (to return the selected contact (which is its own class)).
Is there a way to determine the previous sender which triggered the getEventContact function as it could be one of 15 buttons.
-(IBAction)getEventContact:(id)sender {
[self performSegueWithIdentifier:#"selectContact" sender:self];
}
-(void)setEventContact:(Contact *)selectedContact
{
//do something
}
Cheers.
SomeType *someVariable;
-(IBAction)getEventContact:(id)sender
{
someVariable = sender;
[self performSegueWithIdentifier:#"selectContact" sender:self];
}
-(void)setEventContact:(Contact *)selectedContact
{
//not a real method
[someVariable someMethod];
}
I have some code to clean up in my viewWillDisappear:, which I only want to use when the view is moving back to the parent view controller.
- (void)viewWillDisappear:(BOOL)animated
{
if ([self isMovingFromParentViewController] || [self isBeingDismissed]) {
NSLog(#"isMovingFromParentViewController or isBeingDismissed");
// clean up
}
[super viewWillDisappear:animated];
}
The view can be presented in two ways: it can be pushed by a navigation controller, or presented as a modal view controller (from the same navigation controller). If it's pushed, then popped (pressing the back button), my clean-up code runs. If it it presented as a modal view controller, then dismissed, the code doesn't run.
I dismiss like so:
[rootViewController dismissModalViewControllerAnimated:YES];
My question is: why isn't isBeingDismissed set when I dismiss my view controller?
If this is the first view controller in a modal navigation controller that's being dismissed, calling self.isBeingDimissed() from viewWillDisappear: returns false.
However, since the entire navigation controller is being dismissed, what actually works is self.navigationController?.isBeingDismissed(), which returns true.
As #Yuval Tal mentioned, this flag does not work when you're dismissing controller that is embeded inside navigation controller. Here's an extension that I use:
extension UIViewController
{
var isAboutToClose: Bool {
return self.isBeingDismissed ||
self.isMovingFromParent ||
self.navigationController?.isBeingDismissed ?? false
}
}
It can be easily extended when you find another case when standard .isBeingDismissed won't work. And if you find, let us, let me know in comments.
Your issue is how you are dismissing your modal view. How is rootViewController being defined?
When I call [self dismissModalViewControllerAnimated:YES] then [self isBeingDismissed] evaluates to true.
When I call [parentViewController dismissModalViewControllerAnimated:YES] then [self isBeingDismissed] evaluates to true, whereby parentViewController is the UIViewController that presented the modal view (note: not a UINavigationController).
If by some chance you came here trying to use isBeingDismissed on a non-modally presented view controller, you can always check the topViewController property of your navigationController, for instance:
if navigationController?.topViewController != self {
return
}
viewController.isBeingPresented == NO;
[rootVC presentViewController:viewController animated:NO completion:^{
viewController.isBeingPresented == NO;
viewController.isBeingDismissed == NO;
[viewController dismissViewControllerAnimated:NO completion:^{
viewController.isBeingDismissed == NO;
}];
viewController.isBeingDismissed == NO; // is not work
}];
viewController.isBeingPresented == YES; // is work
viewController.isBeingPresented == NO;
[rootVC presentViewController:viewController animated:NO completion:^{
viewController.isBeingPresented == NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
viewController.isBeingDismissed == NO;
[viewController dismissViewControllerAnimated:NO completion:^{
viewController.isBeingDismissed == NO;
}];
viewController.isBeingDismissed == YES; // is work
});
}];
viewController.isBeingPresented == YES; // is work
i got a 3 view controller - Register, Login, Profile
and i got a UISegmentedControl that i can switch views by from Register to main and from Login to main too.
but when i'm in Register view for Example id like to switch users to profile view after finishing registration.
and here's the Code..
-(IBAction) switchView :(id)sender{
switch (segControl.selectedSegmentIndex) {
case 0:
{
HangmanViewController * main =[[HangmanViewController alloc]initWithNibName:nil bundle:nil];
main.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:main animated:YES];
[main release];
}
break;
case 1:
break;
case 2:
{
Profile *profile2 = [[Profile alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:profile2 animated:YES];
[profile2 release];
}break;
default:
break;
}
}
and i Already imported the .h file of Profile Class..
so what's wrong !!!!
Thanks.
i don't understand you question perfectly hope this will help you.
- (IBAction)SegmentControll:(id)sender {
if (SegmentControll.selectedSegmentIndex==0) {
//your main view
}
if (SegmentControll.selectedSegmentIndex==1) {
//your Profile view
}
}
Do you want to switch users to profile view only after Successfully finishing registration/login otherwise show alert ?
then you may try this :
in your .h file
NSString *count;
in your .m file
#Synthesize count;
in your ViewdidLoad
count=#"1";
//so here default value of count is 1
// after Successfully finishing registration/login make count =2
count=#"2";
In your SegmentControl Action make this condition :
- (IBAction)SegmentControll:(id)sender
{
if (SegmentControll.selectedSegmentIndex==0)
{
if (count isEqualToString:#"2") {
//your main view
}
else
// alert for login/Register
}
if (SegmentControll.selectedSegmentIndex==1) {
//your Profile view
}
if (SegmentControll.selectedSegmentIndex==2) {
//your Register view
}
}