I'm using ECSliding and I have this problem!
I have a topView and two menus,
left (LeftViewController)
right (RightViewController)
both UIViewController.
I want to give a reference to the right view controller, to the left view controller, in the AppDelegate.
I did in LeftViewController.h:
#import "RightViewController.h"
#class RightViewController;
#property (strong, monatomic) RightViewController *rightView;
in didFinishLaunchingWithOptions in AppDelegate.m :
RightViewController *rightViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Right"];
LeftViewController *leftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Left"];
leftViewController.rightView = rightViewController;
but I get this error in AppDelegate.m on self.storyboard:
Property 'storyboard not found on object of type 'AppDelegate *
How can I solve this problem?
Don't statically give them a reference to each other. Instead, when they are part of the sliding view controller self.slidingViewController will be a valid reference and you can navigate based on the relationships that actually exist:
self.slidingViewController.underLeftViewController
When using it, you should check the class and cast the reference:
LeftViewController *leftController = self.slidingViewController.underLeftViewController;
if ([leftController isKindOfClass:[LeftViewController class]]) {
leftController. ...;
}
First of all AppDelegate doesn't have a property storyboard it's a UIViewController property.
Second if you want to load the main storyboard and instantiate a view controller you should try the following:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"YourStoryboardName" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"YourViewController"];
Also make sure you properly set the view controllers identifier.
Related
I'm working on an app and I need to pass data between view controllers. I know this is a common question but I couldn't find an answer for my problem : I'm able to pass data from the FirstViewController (MasterViewController in my case) to the SecondViewController (SettingsViewController) but not the reverse. What happens is that I call a method from the FirstViewController in my SecondViewController.m file. This works and it logs the data. But when I quit the SecondViewController (using [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];) the data is reset.
I tried using other methods to pass data but it didn't work. I'm using this code to pass data:
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
I also tried replacing [vc setPorts:SelectedPorts]; with vc.selectedCellIndexes = SelectedPorts; but the same problem occurs.
the setPorts method is declared in the FirstViewController.h file and SelectedPorts is a variable I declared in SecondViewController.m (it's not nil I checked).
Here's the setPorts: in FirstViewController.m :
- (void) setPorts:(id)selectedPorts {
selectedCellIndexes = selectedPorts;
NSLog(#"selectedCellIndexes : %#", selectedCellIndexes);
}
This logs the good value but when I log it in viewWillAppear in FirstViewController.m it's reset to the value it has before I called the method from SecondViewController.m.
Just to clarify, if I DON'T quit the SecondViewController.m, the data isn't reset.
I did read all your comments, and I really thanks you for your help. for convenience, I used a global variable.
Thanks for your help.
You have a list of ports in MasterViewController and you expect to use it in the SettingsViewController.
The MasterViewController can hold this list and SettingsViewController should have an access to it.
In SettingsViewController, have a setSelectedPort method:
#property (nonatomic, retain) id selectedPorts
- (void) setPorts:(id)selectedPorts;
The method saves the selected ports list into a property.
In MasterViewController, call the SettingsViewController and give it the list.
SettingsViewController *vc = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:nil];
[vc setSelectedPorts:yourValue];
When the list is modified inside the SettingsViewController, the list of ports contained in MasterViewController won't move even if you leave the SettingsViewController.
In secondViewController, You create protocol
#import <UIKit/UIKit.h>
#protocol sampleDelegate <NSObject>
- (void)passValue:(id)selectedPorts
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id <sampleDelegate> passDelegate;
#end
In viewDidLoad or wherever method as per your need, call method like this,
[self.passDelegate passValue:selectedPorts];
In FirstViewController.h,
Import the delegate <sampleDelegate>,
#import "SecondViewController.h"
#interface FirstViewController : UIViewController<SampleDelegate>
#end
In FirstViewController.m,
-(void)passValue:(id)selectedPorts
{
id receivedValues = selectedPorts;
}
and set self in your SecondViewController allocation,
SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.passDelegate = self;
There is nothing unusual in the getting result. By doing
MasterViewController *vc = [[MasterViewController alloc] initWithNibName:#"MasterViewController" bundle:nil];
[vc setPorts:SelectedPorts];
You are creating a new instance of MasterViewController from your SecondViewController. This is not the same from which you navigated to the SecondViewController. So you wont get the expected result. Since you are setting the ports([vc setPorts:SelectedPorts]) to the newly created instance of the Master.
Instead of creating a new instance,just hold the reference of the MasterViewController in SecondViewController in a property and assign it before moving to second VC. As a beginner I suggested this way. But using delegate is the prefferred way passing data back.
Either use delegate methods to communicate with the master VC from the modal VC, or you could do something like this if you want to retrieive some manipulated objects from the modal VC.
Set the object(s) as properties in the modal view controller's .h-file (so they are public).
Using unwind segues, in the master VC, just do this:
-(IBAction)exitModalVC:(UIStoryboardSegue*)segue
{
SomeObject *obj = ((YourModalVC*)segue.sourceViewController).someObject;
//Do what you want with obj
}
EDIT:
This will only work if you are using unwind segue (which is a neat way of dismissing modal VC when using story board)
And you are using this, which is not unwind segues:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
You were creating a new instance of the first view controller from the 2nd view controller not accessing the same instance of the original caller. That was the reason why while you could see the logs but data were not there when you got back to the original caller - your MasterViewController.
You need to use delegate method. Check my answer for this SO.
This is problem related to object ownership.
Follow the below steps:
As per understanding you want reverse value from "SecondViewController" to "FirstViewController"
Don't create new object of FirstViewController in SecondViewController, it will not work.
Create object of "FirstViewController" in "SecondViewController.h" file.
#property (nonatomic,strong) FirstViewController *firstViewController;
When you navigate from FirstViewController to SecondViewController, please pass the "self".
e.g. SecondViewController *vc = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
vc.firstViewController = self;
If you want pass the reverse value to FirstViewController then in SecondViewController.m file.
[self.firstViewController setPorts:SelectedPorts];
And in FirstViewController.m refresh your controls with latest values.
Try above code will defiantly work as per your requirement.
I have a UIViewController(Say A). A separate nib file was loaded as popup on this view controller. When popup was closed by clicking a UIButton, I want to load another view controller(Say B) in UIStoryBoard. All the UIViewControllers were in storyboard.
I tried with delegates pattern. the delegate method returns self.storyboard as nil.
Please suggest how to handle (either performsegue from A to B or pushing new instance of B on navigation controller from nib file)
Here is code I used for delegate:
**In CustomViewNewPrescription.h file:**
#class CustomViewNewPrescription;
#protocol CustomViewNewPrescriptionDelegate <NSObject>
-(void)SaveCustomViewNewPrescription;
#end
#interface CustomViewNewPrescription : UIView{
id<CustomViewNewPrescriptionDelegate>delegate;
}
#property(nonatomic,strong) id<CustomViewNewPrescriptionDelegate>delegate;
**in .m:**
- (IBAction)btnCancel:(UIButton *)sender{
[self.delegate SaveCustomViewNewPrescription];
}
delegate was synthesized and initialised.
**In AddNewRx.h:**
#interface AddNewRx : UIViewController<CustomViewNewPrescriptionDelegate>{
}
**in AddNewRx.m:**
-(void)SaveCustomViewNewPrescription{
//either self performseguewithidentifier .... (or)
RxViewController *obj1 = [[self.navigationController storyboard] instantiateViewControllerWithIdentifier:#"RxViewController"];
[self.navigationController pushViewController:obj1 animated:YES];
}
In SaveCustomViewNewPrescription, self.storyboard giving nil values
Please suggest how to load another view controller in SaveCustomViewNewPrescription.
Instead of:
RxViewController *obj1 = [[self.navigationController storyboard] instantiateViewControllerWithIdentifier:#"RxViewController"];
Try:
UIStoryboard *yourStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
RxViewController *obj1 = [yourStoryboard instantiateViewControllerWithIdentifier:#"RxViewController"];
I try this:
ViewController.h
#class SecondView;
#interface Introduccion : UIViewController{
SecondView *second;
}
-(IBAction)AnimatecreditsPage:(id)sender;
#end
ViewController.m
-(IBAction)AnimatecreditsPage:(id)sender{
second = [[SecondView alloc]initWithNibName:#"SecondView" bundle:nil];
second.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:second animated:YES];
}
Im using Storyboards, and i already linked my viewcontroller with the corresponding classes, when i press the button, the iphone simulator just crash.. im using a navigation controller and tab bar controller.
Image of the viewcontroller
THANKS!! :)
Please Help Me.
The way you're trying is crashing because you're pointing to a xib that doesn't exist. Since with storyboards you can have multiple view controllers you have to add an identifier to the view controller you wish to use in the attributes inspector section of interface builder. This then allows you to use the following code to programmatically instantiate what ever view controller in your storyboard has the ID you specify.
second = [self.storyboard instantiateViewControllerWithIdentifier:#"someID"];
Instead of:
second = [[SecondView alloc]initWithNibName:#"SecondView" bundle:nil];
All I need is to view a UIView controller in same storyboard file manually with code. I use storyboard to make all forms and connections. My application starts in navigation controller, which provides me access to UIView (LoginViewController) and then it goes to tab bar controller, which provides 4 UIViews. According to every UIView I have .h and .m files. I know about segue method, it is simple, but I need manual method. Maybe I am doing something wrong.
I was trying to use this method for pushing view controller in IBAction:
[self.view pushViewController:LoginViewController animated:YES];
But it makes an error:
Unexpected interface name ‘LoginViewController’: expected expression
It took a lot of time to figure out what is wrong, but I had not succeed.
Here is my RollEnemyController.m file:
// RollEnemyController.m
#import "RollEnemyController.h"
#import "LoginViewController.h"
#implementation RollEnemyController;
#synthesize AttackButtonPressed;
- (IBAction)AttackButtonPressed:(id)sender {
LoginViewController* controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.view pushViewController:controller];
}
#end
And this is header file:
// RollEnemyController.h
#import <UIKit/UIKit.h>
#interface RollEnemyController : UIViewController
- (IBAction)RollButtonPressed:(id)sender;
#property (weak, nonatomic) IBOutlet UIButton *AttackButtonPressed;
#end
I'm guessing that you are using a UINavigationController. Then you can simply do like this:
LoginViewController *controller = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
Update:
If you are using a UIStoryboard, you can set the identifier of your new viewcontroller, and then push it onto your navigationController. To set the identifier, choose your view, open the Attributes Inspector, and set the identifier ("LoginIdentifier" in my example). Then you can do this:
LoginViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"LoginIdentifier"];
[self.navigationController pushViewController:controller animated:YES];
As a sidenote, I see that you are using capital characters for your methods. You should probably try to avoid that, and instead use lowered first-characters in your method names. And since you say you are learning Objective-C, you should check out this awesome thread here on SO: link.
Update 2:
Here is a zip file with a project showing how to do this. :-)
hello try to use this code
Storyboard put ID = "xxx * Name Desire"
mark use StoryboarID
UIStoryboard * storyboard = self.storyboard;
DetailViewController * detail = [storyboard instantiateViewControllerWithIdentifier: # "xxx * Name Desire"];
[self.navigationController pushViewController: detail animated: YES];
In this statement:
[self.view pushViewController:LoginViewController animated:YES];
it seems you are trying to push a class. You should push an object, your actual controller:
LoginViewController* controller = [[LoginViewController alloc] init...];
[self.view pushViewController:controller animated:YES];
this will at least compile, and if all the rest is fine, also give you the second controller.
EDIT:
I missed one point. You are pushing the view controller on to a view. That makes no sense, you should push the controller on to the navigation controller:
<AppDelegate> *del = (AppDelegate*)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:controller animated:YES];
This is true, at least, if you created your project from the Navigation-based template (which creates an application delegate with a reference to the navigation controller). Otherwise, please provide details about how you create the navigation controller.
You mentioned in a comment that you're using UIStoryboard. Are you aware of UIStoryboardSegue? All you have to do it control-drag from the button to the next view controller to establish a segue. Then you can choose the type of transition. Be aware that your view controllers need to be part of a UINavigationController in the storyboard to perform a "Push" animation.
Im working off the seismic xml iphone example.
In that example there is simply the application delegate which has a rootViewController of type UITableViewController.
I wanted to modify it slightly so that I would have a navigationController and use its rootViewController as the table view. My root view controller class for my navigation controller is named "firstLevelViewController"
In the sample code it says
[rootViewController.tableView reloadData];
I want to say [navController.firstLevelViewController.tableView reloadData]
but I get errors saying "request for member firstLevelViewController in something is not a structure or union"
How can I reference the rootViewController of the navigationcontroller from the main app delegate?
There isn't a firstLevelViewController property in a UINavigationController. If you want to access the current controller you can use
UITableViewController* firstLevelViewController = navController.topViewController;
assert([firstLevelViewController isKindOfClass:[UITableViewController class]]);
[firstLevelViewController.tableView reloadData];
If firstLevelViewController means the view controller at the bottom you can use
UITableViewController* firstLevelViewController = [navController.viewControllers objectAtIndex:0];
....
Access the rootViewController like this:
Objective-C
YourViewController *rootController =(YourViewController*)[[(YourAppDelegate*)
[[UIApplication sharedApplication]delegate] window] rootViewController];
Swift
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let viewController = appDelegate.window!.rootViewController as YourViewController