I have a UIViewController calling another view Controller with a defined loadView method. I’ve been trying many options without success to solve the problem of the loadView method not called.
Any help is appreciated.
Thanks.
MArcos
Caller UIViewController
#import "MyAlbumViewController.h"
#interface ViewController : UIViewController
#end
implementation
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidAppear:(BOOL)animated{
UIViewController*albumVC = [[MyAlbumViewController alloc] init];
[self.navigationController pushViewController:albumVC animated:YES];
}
#end
Called UIViewController
#interface MyAlbumViewController : NIToolbarPhotoViewController <NIPhotoAlbumScrollViewDataSource>
#end
Implementation
#import "MyAlbumViewController.h"
#implementation MyAlbumViewController
- (void)loadView{
[super loadView];
self.photoAlbumView.dataSource = self;
// Set the default loading image.
self.photoAlbumView.loadingImage = [UIImage imageWithContentsOfFile:
NIPathForBundleResource(nil, #"NimbusPhotos.bundle/gfx/default.png")];
self.title = NSLocalizedString(#"Loading...", #"Navigation bar title - Loading a photo album");
[self loadAlbumInformation];
}...
The idea of loadView is to completely override the method, and not call super
What you are doing is exactly what the viewDidLoad method is for, it doesn't matter if you loaded it from a nib file or whatever
And I quote from your own post, in your ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
I was pushing view controller with:
[self.navigationController pushViewController:albumVC animated:YES];
I just changed to:
[self presentViewController:albumVC animated:YES completion:nil];
UIViewController Navigation Controller
navigationController The nearest ancestor in the view controller
hierarchy that is a navigation controller. (read-only)
#property(nonatomic, readonly, retain) UINavigationController
*navigationController Discussion If the receiver or one of its ancestors is a child of a navigation controller, this property
contains the owning navigation controller. This property is nil if the
view controller is not embedded inside a navigation controller.
Related
I have two view controllers in my project ViewController and SecondViewController and my ViewController has a button which performs a popover segue to SecondViewController then in my SecondViewController I have a button which I would like to use to a call a method from ViewController and I assumed it was possible using [self presentingViewController] but that pointer is set to nil so I'm not quite sure how to call a method in the first ViewController inside the SecondViewController after a popover segue.
This is the code for my ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
- (IBAction)dosegue:(id)sender;
-(void)tobecalledfromseguepopover;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
}
-(void)tobecalledfromseguepopover{
NSLog(#"Called from segue popover");
}
- (IBAction)dosegue:(id)sender {
[self performSegueWithIdentifier:#"segueforpopup" sender:self];
}
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface SecondViewController : UIViewController
- (IBAction)returntocaller:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController()
#end
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)returntocaller:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
ViewController* caller = (ViewController*)[self presentingViewController];
if(caller!=nil){
[caller tobecalledfromseguepopover];
}else{
NSLog(#"nil");
}
}];
}
#end
My UI
So any ideas on how I can call tobecalledfromseguepopover inside SecondViewController after the segue? Also is there a way for SecondViewCOntroller to know it's being called from a segue popover?
The usual thing is a delegate architecture. Give the popover a delegate property and set it to self in your prepareForSegue. Now the popover knows where to find the first view controller.
This is often combined with a protocol so that the popover knows the name of the method to be called without worrying about the class of the first view controller, but that part isn’t crucial, especially in Objective C.
What I did:
I am using scrollview to view some UIView(s), with paging enabled.
In last page in subview of scrollView I added a button.
I also wrote a function which is in subclass of UIView ,which is invoked when we press that button.
I want to view storyboard when I press that button.
You need to implement protocol method for custom UIView class.
For example;
#import <UIKit/UIKit.h>
#protocol YourCustomViewDelegate <NSObject>
- (void)buttonTapped;
#end
#interface YourCustomView : UIView
#property (nonatomic, strong) id< YourCustomViewDelegate > delegate;
#end
And the .m file you can call buttonTapped delegate method.
- (void)myCustomClassButtonTapped:(id)sender
{
[self.delegate buttonTapped];
}
For proper work;
set your custom view delegate to self in your custom view controller.
add buttonTapped method to that view controller
And do what you want in that method. Present/Push view controllers like the other answers explained.
Edit
I will try to illustrate very simple usage of protocols, hope it will help you.
#import "MyViewController.h"
#import "YourCustomView.h"
#interface MyViewController ()<YourCustomViewDelegate> // this part is important
#end
#implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
YourCustomView *customView = // initialize your custom view, I suppose that you already did it
customView.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)buttonTapped
{
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
}
Take a look at this
YourViewController *obj=[[YourViewController alloc]init];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:obj];
[[[UIApplication sharedApplication]keyWindow].rootViewController presentViewController:nav animated:YES completion:NULL];
try like this
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* initialView = [storyboard instantiateInitialViewController];
Firstly you need to set a storyboard Id to your ViewController, namely "mainVC". Then you could pus/present it using below code :-
YOUR_VIEW_CONTROLLER_CLASS *viewCon =[storyboard instantiateViewControllerWithIdentifier:#"mainVC"]; //mainVC is just a example and u will have to replace it with your viewController storyboard id
//Pushing VC
[self.navigationController pushViewController:viewCon animated:YES];
//OR presenting VC
[self presentViewController:viewCon animated:YES completion:nil];
Also in case if you want your another storyboard to be initiated then below,
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil]; //Change MainStoryboard with your storyboard id
hope this will help
the way i perceive your question is
->Rightnow your inside you are in UIView class and inside it there is a button by clicking it you want to push or present a ViewController and offcourse from inside your UIView class you cant push or present your view Controller. So
you can do one simple thing first inside action method make a ref(forward declaration) or you can make a whole new object of your ViewController class in which your UIView is present right now , then call a function(which exist in your ViewController) like
//function inside your uiview calss
- (void)btnaction
{
[_objCSInformationViewController pushViewController];
}
// function inside your view controller
-(void)pushViewController
{
yourViewController *objViewController = [[yourViewController alloc]initWithNibName:#"yourViewController" bundle:nil];
[strong.navigationController pushViewController:objViewController animated:YES];
}
I am creating an iOS app. On a view controller there are several buttons.
One of them is the AButton, here you have my header file:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController
- (IBAction)Aaction:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *AButton;
#end
I want to open another view controller when AButton is tapped:
#import "FirstViewController.h"
#import "EntradasTableViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (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)Aaction:(id)sender {
EntradasTableViewController *detailViewController =[self.storyboard instantiateViewControllerWithIdentifier:#"entradasViewController"];
detailViewController.categoriaDescription = #"A";
[self.navigationController pushViewController:detailViewController animated:YES];
}
#end
I have declared the StoryBoard identifier as follows:
But after tapping on the button nothing happens, no exception is thrown and the view controller detailViewController is not shown.
Any help is welcome.
NEW IMAGED ADDED:
Here is a screenshot where I am declaring the action for the button in the storyboard:
The problem is that your FirstViewController instance is not in a navigation interface. Therefore when your FirstViewController says self.navigationController, that's nil. Therefore this line:
[self.navigationController pushViewController:detailViewController animated:YES];
...involves sending a message to nil. In Objective-C, sending a message to nil does nothing. So that's why nothing happens.
I'm fairly new to Objective-C, programming. The one thing, I'm currently putting up with is passing a value from the first ViewController to the next one.
I've read this entry here and it didn't help me. Which is funny, since his answer has nearly 500 votes, so I must be the problem. What I did was the following.
I opened my PreviewViewController.m and added the following line #import "MainViewController.h" since I wanted to pass a value from the PreviewViewController to the `MainViewController. Then, when I switch the layouts ( which successfully works ) I want to pass a value.
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
mainViewController.userId = #"539897197";
As you can see, I want to pass the userId. For that, I also created a property in the MainViewController.h
#property ( nonatomic, strong ) NSString *userId;
Now, In my MainViewController.m I want to access the userId. But when I log it, the console tells me it is null. However, when I set the variable right before the NSLog it works, so it seems like the passing is the problem.
Additionally in the MainViewController.m I have the following line
#synthesize userId = _userId;
but even when I removed that line and changed the NSLog to NSLog(#"%#",self.userId); the same problem occurred.
How can I successfully pass the variables? Which step am I doing wrong?
EDIT
This is how I switch the layouts
UIViewController *viewController = [[MainViewController alloc]init];
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
mainViewController.userId = #"539897197";
[self presentViewController:viewController animated:YES completion:NULL];
Why not create a custom initializer and pass it in that way? Something like
- (id)initWithUserId:(NSString *)aUserId {
self = [super initWithNibName:#"MainViewController" bundle:nil];
if (self) {
self.userId = aUserId
}
return self;
}
Then you can just do:
MainViewController *mvc = [[MainViewController alloc] initWithUserId:#"1234"]
[self presentViewController:mvc animated:YES completion:nil];
If you are using storyboard then you should use prepareForSegue: method to pass data between view controllers. First Create the segue from your PreviewViewController to MainViewController, just control drag from your view controller to next viewcontroller to create segue. Use UINavigationController if you are using push segue. Use this method to segue and pass data
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"yourSegueIndentifier"]){
MainViewController *mvc = (MainViewController *) segue.destinationViewController;
mvc.userId = #"539897197";;
}
}
UIViewController *viewController = [[MainViewController alloc]init];
MainViewController *mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
mainViewController.userId = #"539897197";
[self presentViewController:mainViewController animated:YES completion:NULL];
use mainViewController rather than viewController when presenting the view controller
Here we have two ways for passing data.
First is Custom Delegate
Second is NSNotification
Here we have two view controllers.
ViewController
and
SecondViewController
in SecondViewController
.h
#import <UIKit/UIKit.h>
#class SecondViewController;
#protocol SecondViewControllerDelegate <NSObject>
- (void)secondViewController:(SecondViewController *)secondViewController didEnterText:(NSString *)text;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign)id<SecondViewControllerDelegate> delegate;
#property (nonatomic, strong) IBOutlet UITextField *nameTextField;//It must connect as outlet connection
- (IBAction)doneButtonTapped:(id)sender;
#end
.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
//Either use NSNotification or Delegate
- (IBAction)doneButtonTapped:(id)sender;
{
//Use Notification
[[NSNotificationCenter defaultCenter] postNotificationName:#"passingDataFromSecondViewToFirstView" object:self.nameTextField.text];
//OR Custom Delegate
[self.delegate secondViewController:self didEnterText:self.nameTextField.text];
[self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
in ViewController
.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface ViewController : UIViewController<SecondViewControllerDelegate>
#property (nonatomic, strong) IBOutlet UILabel *labelName; //You must connect the label with outlet connection
- (IBAction)gotoNextView:(id)sender;
#end
.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//addObserver here...
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textFromPreviousViewControllerNotificationReceived:) name:#"passingDataFromSecondViewToFirstView" object:nil];
// Do any additional setup after loading the view, typically from a nib.
}
//addObserver Method here....
- (void)textFromPreviousViewControllerNotificationReceived:(NSNotification *)notification
{
// set text to label...
NSString *string = [notification object];
self.labelName.text = string;
}
- (IBAction)gotoNextView:(id)sender;
{
//If you use storyboard
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
//OR If you use XIB
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.delegate = self;
[self.navigationController pushViewController:secondViewController animated:YES];
}
//Calling custom delegate method
- (void)secondViewController:(SecondViewController *)secondViewController didEnterText:(NSString *)text
{
self.labelName.text = text; //Getting the data and assign the data to label here.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
For your understanding the code I create a simple passing data from one second view controller to first view controller.
First we navigate the view from first view controller to second view controller.
After that we send the data from second view controller to first view controller.
NOTE : You can either use NSNotification or Custom Delegate method for sending data from One View Controller to Other View Controller
If you use NSNotification, you need to set the postNotificationName for getting data in button action method.
Next you need to write addObserver in (sending data to your required View Controller) ViewController and call the addObserver method in same View Controller.
If you use custom delegate,
Usually we go with Custom Protocol Delegate and also we need to Assign the delegate here.
Very importantly we have to set the Custom Delegate Method in the Second View Controller.Because where we send the data to first view controller once we click the done button in second view controller.
Finally we must call the Custom Delegate Method in First View Controller, where we get the data and assign that data to label.Now you can see the passed data using custom delegate.
Likewise you can send the data to other view controller using Custom Delegate Methods
I tried and got the solution for passing the value between viewcontroller.
MainViewController *mainVC = [[self storyboard] instantiateViewControllerWithIdentifier:#"MainViewController"];
mainVC.userId = #"539897197";
[self presentViewController:mainVC animated:YES completion:Nil];
or using this way . You don`t use the storyboard use the following its working fine
MainViewController *mainVC = [[MainViewController alloc] init];
mainVC.userId = #"539897197";
[self presentViewController:mainVC animated:YES completion:Nil];
I have a normal view controller with xib, m, and h file. I want when the view loads for it to automatically call a method. In my current M file I have the code call another view, this is just so I can see if the checkIfLogged method is working. When the app loads it doesn't call the other view it stays in its own view. How can I get the checkIfLogged method called when the viewloads? Actually I would prefer the method to be called before the view is even loaded if that is possible.
Here is my M file.
#import "ViewController.h"
#import "LoginView.h"
#interface ViewController ()
#end
#implementation ViewController
-(void) viewDidLoad{
[self checkIfLogged];
}
- (void) checkIfLogged
{
LoginView *loginView = [[LoginView alloc] initWithNibName:#"LoginView" bundle:nil];
[loginView setModalPresentationStyle:UIModalPresentationFormSheet]; //you can change the way it is presented
[loginView setModalTransitionStyle:UIModalTransitionStyleCoverVertical]; //you can change the animation
[self presentViewController:loginView animated:YES completion:nil]; //show the modal view
}//end checkIfLogged
#end
Here is my H file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
-(IBAction)checkIfLogged;
#end
First, call [super viewDidLoad]; as the first line in your viewDidLoad implementation.
Second, you shouldn't attempt to present a view controller from viewDidLoad. Your UIViewController's view is not part of the view hierarchy at this point. Present the view controller from viewDidAppear: instead.