First of all, apologize for my english.
I'm a beginner in iOS development, I'm doing an App which have 3 viewControllers (MainViewController, CenterViewController and ActionViewController).
In a first VC (MainVC) I have a button, this button takes you to the CenterVC using UIModalTransitionStylePartialCurl.
In a second VC (CenterVC) I have and other button that takes you to the ActionVC, but here is a problem. I can see the ActionVC but this VC is presented bellow MainVC with the Curl effect.
I have tried to solve using this code inside of the IBAction in a CenterVC:
- (IBAction)actionReveal:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
ActionViewController *actionVC = [[ActionViewController alloc]initWithNibName:#"ActionViewController" bundle:nil];
[self presentViewController:actionVC animated:YES completion:^{}];
}];
}
Please, anyone can help me with the problem?
Try using this using navigation controller :
[UIView beginAnimations:#"animation" context:nil];
//put this instance to navigation controller
[self.navigationController pushViewController: detailController animated:NO];
// Animate the navigation controller
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:NO];
// Set animation time
[UIView setAnimationDelay:0.01];
[UIView setAnimationDuration:0.3];
// Commit animation
[UIView commitAnimations];
I have solved the problem. Write the solution here in case anyone has had the same problem.
mainVC.h:
#import <UIKit/UIKit.h>
#import "OXDcurlViewController.h"
#interface OXDmainViewController : UIViewController <OXDcurlViewControllerDelegate>
#property (strong, nonatomic) IBOutlet UIButton *curlButton;
- (IBAction)curlReveal:(id)sender;
#end
mainVC.m:
#import "OXDmainViewController.h"
#import "OXDcurlViewController.h"
#import "OXDsecondViewController.h"
#interface OXDmainViewController ()
#end
#implementation OXDmainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)curlReveal:(id)sender {
OXDcurlViewController *curlVC = [[OXDcurlViewController alloc]initWithNibName:#"OXDcurlViewController" bundle:nil];
curlVC.modalTransitionStyle = UIModalTransitionStylePartialCurl;
curlVC.delegate = self;
[self presentViewController:curlVC animated:YES completion:^{}];
}
-(void)presentSecondVC{
OXDsecondViewController *secondVC = [[OXDsecondViewController alloc]initWithNibName:#"OXDsecondViewController" bundle:nil];
secondVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:secondVC animated:YES completion:^{}];
}
#end
curlVC.h:
#import <UIKit/UIKit.h>
#protocol OXDcurlViewControllerDelegate <NSObject>
#optional
-(void)presentSecondVC;
#end
#interface OXDcurlViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIButton *actionButton;
#property (nonatomic, weak) id<OXDcurlViewControllerDelegate> delegate;
- (IBAction)actionReveal:(id)sender;
#end
curlVC.m:
#import "OXDcurlViewController.h"
#import "OXDsecondViewController.h"
#interface OXDcurlViewController ()
#end
#implementation OXDcurlViewController
#synthesize delegate;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)actionReveal:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate presentSecondVC];
}];
}
#end
Thanks to all who have helped me.
David Álvarez Medina
Related
I have two VC. I need to call the delegate function when the 2nd VC is dismissed.
In my 1st VC or main VC I have given the following code in .h file.
#interface FirstVC : ....<SecondVCDelegate>
-(void)didDismissViewController:(UIViewController*)vc;
But for some reason SecondVCDelegate in this is not detected.
while presenting 2nd VC from first I have given this .m file of 1st VC.
SecondVC *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:^{}];
in 2nd VC .h file
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondVC : ...
#property (nonatomic) id<SecondVCDelegate> delegate;
#end
in 2nd VC .m file I have dismissed using the below code
[self dismissViewControllerAnimated:YES completion:nil];
Could you point out what I did wrong with possible explanation. Thanks in advance.
This is the working code on xcode 9 :
ViewController.m :
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController () <SecondVCDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)action:(id)sender {
SecondViewController *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:nil];
}
-(void) didDismissViewController:(UIViewController *)vc{
NSLog(#"working controller : %#", vc);
}
#end
SecondViewController.h :
#import <UIKit/UIKit.h>
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id<SecondVCDelegate> delegate;
#end
SecondViewController.m :
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)didmissAction:(id)sender {
[self dismissViewControllerAnimated:true completion:^{
[_delegate didDismissViewController:self];
}];
}
#end
On your 2nd VC .m do like this
First synthesize delegate below implementation
#synthesize delegate;
after that use it on viewController dismiss:
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController: self];
}];
Why the string value is getting null value. Someone please find the error?
How can i fetch the string value when the method is getting called from SecondViewController do i need a another string or someone please suggest some corrections.
I need this string to be have some value
#property (nonatomic,strong) NSString *str;
When the following method is getting called.
[view getTotal];
Label is in the first view controller.
Thanks in advance.
In ViewController.m
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController ()
{
NSInteger total;
}
#property (weak, nonatomic) IBOutlet UILabel *lbl;
#property (weak, nonatomic) IBOutlet UIButton *btn;
#property (nonatomic,strong) NSString *str;
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",_str);
self.lbl.text = _str;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(#"viewDidAppear called");
[self viewDidLoad];
}
-(id)initWithInitialNumber:(NSInteger)initialNumber{
total = initialNumber;
return self;
}
-(void)addNumber:(NSInteger)newNumber{
total += newNumber;
}
-(NSInteger)getTotal{
NSLog(#"Number is: %ld",total);
self.str = [NSString stringWithFormat:#"%ld",total];
NSLog(#"%#",self.str);
return total;
}
- (IBAction)btnAct:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *SC = [sb instantiateViewControllerWithIdentifier:#"SC"];
[self presentViewController:SC animated:YES completion:nil];
}
-(NSString *)str{
return _str;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In SecondViewController.m
#import "SecondViewController.h"
#import "ViewController.h"
#interface SecondViewController ()<Sendata>
{
NSInteger *num;
}
#end
#implementation SecondViewController
- (IBAction)backBtn:(id)sender {
ViewController *VC = [self.storyboard instantiateViewControllerWithIdentifier:#"VC"];
[self presentViewController:VC animated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
ViewController *view = [[ViewController alloc]initWithInitialNumber:10];
view.delegate = self;
[self Print:#"Hello"];
[view addNumber:2];
[view getTotal];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)Print:(NSString *)str{
NSLog(#"%#",str);
}
#end
What I can understand from your code is that you are presenting secondViewController from ViewController on a button click. On Second view controller you want to add two numbers and show them on Firstview controller again.
what I can see from your code , you are pushing the new instance of ViewController every time. So thevalue you are intialising in your view didLoad in diffrent object then the one your pushing again on button action of back. IF you can modify you code like this , it will work :
#interface ViewController ()
{
NSInteger total;
}
#property (weak, nonatomic) IBOutlet UILabel *lbl;
#property (weak, nonatomic) IBOutlet UIButton *btn;
#property (nonatomic,strong) NSString *str;
- (id)initWithInitialNumber:(NSInteger)initialNumber;
- (void)addNumber:(NSInteger)newNumber;
- (NSInteger)getTotal;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",_str);
self.lbl.text = _str;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(#"viewDidAppear called");
[self viewDidLoad];
}
-(id)initWithInitialNumber:(NSInteger)initialNumber{
total = initialNumber;
return self;
}
-(void)addNumber:(NSInteger)newNumber{
total += newNumber;
}
-(NSInteger)getTotal{
NSLog(#"Number is: %ld",total);
self.str = [NSString stringWithFormat:#"%ld",total];
NSLog(#"%#",self.str);
return total;
}
- (IBAction)btnAct:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *SC = [sb instantiateViewControllerWithIdentifier:#"SC"];
[self.navigationController pushViewController:SC animated:YES];
}
-(NSString *)str{
return _str;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
#interface SecondViewController ()
{
NSInteger *num;
ViewController *viewController;
}
#end
#implementation SecondViewController
- (IBAction)backBtn:(id)sender {
[self.navigationController popViewControllerAnimated:YES]
}
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *VCs = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
if ([[VCs objectAtIndex:[VCs count] - 2] isKindOfClass:[ViewController class]])
{
ViewController *view = [[VCs objectAtIndex:[VCs count] - 2]
view.delegate = self;
[self Print:#"Hello"];
[view addNumber:2];
[view getTotal];
}
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)Print:(NSString *)str{
NSLog(#"%#",str);
}
#end
I have taken the instance of ViewController already present in navigation stack , changed the values and on back I have pop out the SecondViewController.
I have created two views within my project. I want to be able to click a button on my main view and the other view (ChooseCar) will pop up allowing the user to pick something then it will reopen the old view (ViewController) with the information entered. I have done the code for it but for some reason when I click the button the screen just goes black with nothing happening, i'm pretty sure it's something very simple I just can't get my head around it.
I will attach the code for the views below, thanks.
ViewController.h
//
// ViewController.h
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ChooseCar.h"
#interface ViewController : UIViewController <ChooseCarDelegate>
- (IBAction)chooselocation;
#property (strong, nonatomic) IBOutlet UILabel *wherelocation;
#end
ViewController.m
//
// ViewController.m
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
ChooseCar *acController = [[ChooseCar alloc] init];
// acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
ChooseCar.h
//
// ChooseCar.h
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#end
ChooseCar.m
//
// ChooseCar.m
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import "ChooseCar.h"
#interface ChooseCar ()
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
#implementation ChooseCar
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Its easy to do:
1)I believe your ChooseCar vc is created in storyboard.
if yes, you should set the Storyboard ID like this:
2)In your ViewController.m, update your chooselocation method to this:
- (IBAction)chooselocation {
//ChooseCar *acController = [[ChooseCar alloc] init];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseCar *acController = [sb instantiateViewControllerWithIdentifier:#"ChooseCar"];
[self presentViewController:acController animated:YES completion:nil];
}
EDIT
If you want to pass a value by delegate:
at the base of my give.
1)cut this code #property (nonatomic, weak) id <ChooseCarDelegate> delegate; from your ChooseCar.m to ChooseCar.h , make sure the ChooseCar.h like this:
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
2) In the ViewController.m, you should abide the protocal, and set caController's delegate.
#import "ChooseCar.h"
#import "ViewController.h"
#interface ViewController () <ChooseCarDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
//ChooseCar *acController = [[ChooseCar alloc] init];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseCar *acController = [sb instantiateViewControllerWithIdentifier:#"ChooseCar"];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
3)If you want to pass the value, you should take this code to your action:
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
Replace your code with the following:
ViewController.h
#import <UIKit/UIKit.h>
#import "ChooseCar.h"
#interface ViewController : UIViewController <ChooseCarDelegate>
- (IBAction)chooselocation;
#property (strong, nonatomic) IBOutlet UILabel *wherelocation;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
ChooseCar *acController;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
acController = [self.storyboard instantiateViewControllerWithIdentifier:#"ChooseCar"];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
[acController dismissViewControllerAnimated:true completion:nil];
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
Also set the storyboard id in storyboard. For more details see the attached screenshot:
ChooseCar.h
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
ChooseCar.m
#import "ChooseCar.h"
#interface ChooseCar ()
#end
#implementation ChooseCar
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
// [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backButtonClicked:(id)sender {
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
I want to cancel the second view controller with a UIBarButtonItem, but I just don't get the code right. Please help.
Viewcontroller.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface ViewController : UIViewController <SecondViewControllerDelegate>
#end
Viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[SecondViewController class]]) {
SecondViewController *vc2 = segue.destinationViewController;
vc2.delegate = self;
}
}
-(void)dismissViewController
{
NSLog(#"dismissed");
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Secondviewcontroller.h
#import <UIKit/UIKit.h>
#protocol SecondViewControllerDelegate <NSObject>
- (void) dismissViewController;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id <SecondViewControllerDelegate> delegate;
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender;
#end
BackbarButton means cancelbutton
Secondviewcontroller.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self.delegate dismissViewController];
}
#end
You can dismiss in secondViewController,I do not see the meaning of Delegate in your code
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:true completion:nil];
}
If you use show segue,and you have a navigationController with these two ViewControllers,Use
- (IBAction)dismiss:(id)sender {
[self.navigationController popViewControllerAnimated:true];
}
I am trying to show a modal view controller(view1) inside another viewController(view2)
View1
#interface View1 : UIViewController
#property (weak) id delegate;
- (IBAction)closeButtonTapped:(id)sender ;
#end
#protocol View1Delegates <NSObject>
#optional
- (void)viewControllerDidFinish: (View1 *) viewController;
#end
#implementation View1
-(void)dealloc
{
}
- (void)viewDidLoad {
}
- (IBAction)closeButtonTapped:(id)sender {
[self.delegate viewControllerDidFinish:self];
}
#end
And I use the following code inside view2
#implementation View2
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)onOpenView1Tapped:(id)sender
{
View1 *view1 = [self.storyboard instantiateViewControllerWithIdentifier:#"view1"];
NavViewController *nav = [[NavViewController alloc] initWithRootViewController:view1];
view1.delegate = self;
[self presentViewController:nav animated:NO completion:NULL];
}
- (void) viewControllerDidFinish: (View1 *) viewController
{
[self dismissViewControllerAnimated:NO completion:NULL];
}
The problem is that the NavViewController calls its dealloc method but view1 never calls it at all after dismiss. This means that view1 will remains in memory .
How can I free the memory of view1 ?