Button Action Issue in IOS - ios6

This is the code i have used.
In View Controller A:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(50, 50, 70, 40)];
[button setTitle:#"Next View" forState:UIControlStateNormal];
[button addTarget:self action:#selector(nextView) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
-(void) nextView
{
SecondviewController *secondView = [[SecondviewController alloc] init];
[self.view addSubview:secondView.view];
}
In View Controller B:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(50, 50, 70, 40)];
[button setTitle:#"Previous View" forState:UIControlStateNormal];
[button addTarget:self action:#selector(previousView) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
-(void) previousView
{
[self.view removeFromSuperview];
}
Issue: When i click the button in the view controller B, its not switching back to the view controller A...

You are not switching viewControllers, you are taking the view from viewController B and adding it as a subview to viewController A.
Here:
SecondviewController *secondView = [[SecondviewController alloc] init];
[self.view addSubview:secondView.view];
You need to navigate to the new view Controller... Replace it with this for example
SecondviewController *secondViewController = [[SecondviewController alloc] init];
[self presentViewController:secondViewController animated:YES completion:NIL];
(it's best to include 'controller' when naming controllers to avoid confusion with their views)
Then to return, you need to dismiss the presented viewcontroller...
In ViewControllerB replace this:
[self.view removeFromSuperview];
With
[[self presentingViewController] dismissViewControllerAnimated:YES completion:NIL];
This is sending a message back from the presented viewController - viewController B - to the presenting viewController, viewControllerA which does the actual dismissing.

instead of adding a the second subview to the first subview, you need to present or push the view controller in the stack. You are just simply adding it as a subview.
SecondviewController *secondView = [[SecondviewController alloc] init];
[self presentViewController:secondView animated:NO completion:nil];
In the second view controller when you dismiss it you can just simply dismiss/pop it from the stack.
[self dismissViewControllerAnimated:YES];

Related

Restoring first responder after dismissing popoverview

I have a text view on the main view controller. I have a bar button item on the view controller's navigation bar. When the app starts, I perform the following actions:
Tap the text view to begin editing and to show the keyboard.
Tap the bar button to show a popover view.
Without dismissing the popover view, I dismiss the keyboard.
Dismiss the popover view by tapping any other view on the screen.
Before iOS 11, the keyboard will NOT show up again after Step 4. However, in iOS 11, it will show up. It seems that in iOS 11, it restores the first responder after dismissing the popover view.
Here are my questions:
Is it a bug, or some changes in iOS 11?
If it is new, then how can I prevent the keyboard from showing after dismissing the popover view?
Also see the following videos:
For iOS 11:
https://www.dropbox.com/s/88wyv0y0idsmu5c/iOS%2011.mov?dl=0
For iOS 10.3:
https://www.dropbox.com/s/11gg6h39mcgb0fs/iOS%2010.3.mov?dl=0
Here are some codes:
#import "MainViewController.h"
#interface MainViewController ()
#property(nonatomic, retain)UITextView *textView;
#end
#implementation MainViewController
#synthesize textView = _textView;
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
self.textView = [[UITextView alloc] init];
self.textView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.textView];
self.textView.backgroundColor = [UIColor blueColor];
NSDictionary *dict = #{#"textView" : self.textView};
NSArray *vCons = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-3-[textView]-3-|" options:0 metrics:nil views:dict];
NSArray *hCons = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-3-[textView]-3-|" options:0 metrics:nil views:dict];
[self.view addConstraints:vCons];
[self.view addConstraints:hCons];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
#import "ViewController.h"
#import "MainViewController.h"
#interface ViewController ()
#property(retain,nonatomic)MainViewController *mainVC;
#end
#implementation ViewController
#synthesize mainVC = _mainVC;
- (void)viewDidLoad {
[super viewDidLoad];
self.mainVC = [[MainViewController alloc] init];
UINavigationController *navigCon = [[UINavigationController alloc] initWithRootViewController:self.mainVC];
self.mainVC.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Button" style:UIBarButtonItemStylePlain target:self action:#selector(showPopover)];
[self.view addSubview:navigCon.view];
}
-(void)showPopover {
UIAlertController *alertCon = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *action1 = [UIAlertAction actionWithTitle:#"Action 1" style:UIAlertActionStyleDefault handler:nil];
UIAlertAction *action2 = [UIAlertAction actionWithTitle:#"Action 2" style:UIAlertActionStyleDefault handler:nil];
[alertCon addAction:action1];
[alertCon addAction:action2];
[alertCon setModalPresentationStyle:UIModalPresentationPopover];
UIPopoverPresentationController *popPresenter = [alertCon popoverPresentationController];
popPresenter.barButtonItem = self.mainVC.navigationItem.rightBarButtonItem;
[self presentViewController:alertCon animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
I just had this issue on iOS 11 with a swift app. Calling [textView resignFirstResponder] any time before dismissing the new controller was the only fix. [view endEditing] was not enough.

How to figure out use a modal segue instead of push segue

I have this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"segueFotosAloj"]) {
localGallery = [[FGalleryViewController alloc] initWithPhotoSource:self];
[self.navigationController pushViewController:localGallery animated:YES];
}
I want to use modal segues, so I can't have a PushViewController statement if I remove that line the Gallery don't load the images, how can I do it use a modal segue? (I don't want use push segue because I'm getting some errors about the navigationcontroller stack)
Here is an example code for modal segue. Just change the name of the view controller to the name of the view controller you are using in your project.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"segueFotosAloj"])
{
SomeViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"SomeIdentifier"];
[self.navigationController presentViewController:controller animated:YES completion:nil];
}
}
P.s, someViewController is the name you have to change.

Calling two different controllers from the same button based on a condition

I had the following code working before iOS6, but I cannot find an easy way to do it with iOS6, storyboards and Xcode 4.5
-(IBAction) ButtonPressed:(id)sender{
if(condition == 1]) {
FirstController *firstController = [[FirstController alloc]initWithNibName:nil bundle:nil];
firstController.delegate = self;
firstController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:firstController animated:NO completion:nil];
[firstController release];
}
SecondController *secondController = [[SecondController alloc]initWithNibName:nil bundle:nil];
secondController.delegate = self;
secondController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:secondController animated:NO completion:nil];
[secondController release];
}
This used to work fine. If I leave the code as is in iOS6, none of the controllers will show properly. Trying to transition the controller navigation to the storyboard does not help matters either since it appears I can have only one action to trigger a transition using a modal segue from ButtonPressed to either the one or the other.
Embedding the first controller in the viewdiload of the second controller has its own problems. If it is on the viewdidload will not work properly as other have experienced. If I put it on viewdidappear, the second controller will show up first creating an unpleasing UI. Any ideas?
A view controller can only present one view controller at a time. A different approach is required. For example, you can use a navigation view controller for what you wish to accomplish. If the user is logged in, you set the upload view controller as the root view controller of the navigation view controller. If the user is not logged in, you set the root view controller as the login view controller. When the user logs in, the login view controller will notify in its delegate that the user logged in, and you can then push the upload view controller into the navigation stack.
- (IBAction)buttonPressed:(id)sender{
UINavigationController* nvc;
if(condition == 1) {
FirstController *firstController = [[FirstController alloc]initWithNibName:nil bundle:nil];
firstController.delegate = self;
firstController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
nvc = [[UINavigationController alloc] initWithRootViewController:firstController];
[firstController release];
}
else {
SecondController *secondController = [[SecondController alloc]initWithNibName:nil bundle:nil];
secondController.delegate = self;
secondController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
nvc = [[UINavigationController alloc] initWithRootViewController:secondController];
[secondController release];
}
[self presentViewController:nvc animated:YES completion:nil];
[nvc release];
}
//Login view controller delegate method
- (void)loginViewControllerDidLoginSuccessfully:(FirstController*)loginViewController{
SecondController *secondController = [[SecondController alloc]initWithNibName:nil bundle:nil];
secondController.delegate = self;
secondController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[secondController.navigationItem setHidesBackButton:YES];
[loginViewController.navigationController pushViewController:secondController animated:YES];
[secondController release];
}

How to mimic UIAlertView modal behavior with custom view?

I have a view that pops up a UIAlertView if the name field for an item entry isn't populated when you attempt to save. I wanted to display my own custom alert view instead. I load it with a xib:
- (void)enterNameAlert {
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"AddNameAlertView" owner:self options:nil];
enterNameAlertView = [subviewArray objectAtIndex:0];
enterNameAlertView.frame = CGRectMake(232, 417, 303, 171);
enterNameAlertView.alpha = 0.0;
[self.view addSubview:enterNameAlertView];
[self.view bringSubviewToFront:enterNameAlertView];
//fade view in
[UIView animateWithDuration:.50f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
enterNameAlertView.alpha = 1.0;
} completion:NULL];
[UIView commitAnimations];
}
However, you can still click on all the other elements on the view while the alert is displayed. Ideally, I'd like to make the alertview modal. As a hack, I just set xxxx.enabled = NO to all the other elements while the alertview is up, and switch them back to xxxx.enabled = YES when you press OK on the alert.
There has to be a better way to cancel all touches to self.view but not to self.enterNameAlertView.
If I do self.view.userInteractionEnabled = NO it cancels all touches to self.view as well as self.enterNameAlertView.
Any ideas?
I think the solution for your problem is that you have to introduce one more view in between your custom alert view and orignal view, once the alert comes you need to bring that view on your self.view and hide (or remove) it when your alert is dismissed, i have already done this and it work like charm for me. Hope this helps you too :)
Got it. I used a UIScrollView with interaction enabled. That stops touches from outside the custom alertview from being passed to the main view underneath.
- (void)enterNameAlert {
//pop a UIScrollView behind the alert so that the user can't touch the controls behind it
shadowScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 768, 1024)];
shadowScrollView.userInteractionEnabled = YES;
shadowScrollView.backgroundColor = [UIColor blackColor];
shadowScrollView.alpha = 0.0;
[self.view addSubview:shadowScrollView];
[self.view bringSubviewToFront:shadowScrollView];
//put the alertview in front of the disabled view to make it act like a modal view
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"AddNameAlertView" owner:self options:nil];
enterNameAlertView = [subviewArray objectAtIndex:0];
enterNameAlertView.frame = CGRectMake(232, 417, 303, 171);
enterNameAlertView.alpha = 0.0;
[self.view addSubview:enterNameAlertView];
[self.view bringSubviewToFront:enterNameAlertView];
//animate view in
[UIView animateWithDuration:.50f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
shadowScrollView.alpha = .6;
enterNameAlertView.alpha = 1.0;
} completion:NULL];
[UIView commitAnimations];
}

UITapGestureRecognizer won't trigger in IOS 6

The following code worked fine is IOS 5, but now handleTapGesture doesn't even get called in IOS 6. What changed?
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
[self addGestureRecognizer:tap];
}
return self;
}
- (void)handleTapGesture:(UITapGestureRecognizer *)recognizer
{
MessageNib *cell = self;
MessageView *view = (MessageView *)[[[NSBundle mainBundle] loadNibNamed:#"MessageView" owner:self options:nil] objectAtIndex:0];
view.message = cell.message;
[[NSNotificationCenter defaultCenter] postNotificationName:NEW_SUB_PAGE object:view];
}
I guess you have to set the numberOfTaps after alloc init
tap.numberOfTapsRequired = 1;
Or the other possibility is initWithCoder was not called.
Ended up just putting a "phantom" button (aka button with no content) over my item I wanted tappable and attached a Touch Up Inside event to the button which calls my tap gesture code.
This is a decent momentary hack anyway.

Resources