I am following this tutorial: http://www.appcoda.com/ios-programming-sidebar-navigation-menu/
However, I need to be able to access the side menu from the classes view controller as seen in the image . While my first view controller is a login screen that the user needs to login to a a server with. To fix the problem I have made a property inside the reveal view controller #property (strong, atomic, retain) NSString *SWSegueFrontIdentifier;. Then I use the getters and setters to assign which view controller is should to/from. I assign the first value sw_first in view controller and everything is fine. In ViewDidLoad of the classmates view controller, seen in the second image, i assign sw_front. However, even when that is set in the same function, if i try to print the property from the reveal controller, it ends up returning null. However, if I manually switch the SWSegueFrontIdentifier inside the view controller to sw_front it segues just fine, but ends up skipping my view controller, which is my login controller. I just need a way for the side menu to be accessed from my classmates view controller and have not had any luck, because it seems most things on www.cocoacontrols.com are made to use without storyboards and I can't seem to get them to work.
This code returns null:
[self.revealViewController setSWSegueFrontIdentifier:#"sw_front"];
tempMenuButton.target = self.revealViewController;
tempMenuButton.action = #selector(revealToggle:);
NSLog(#"reveal view controller prop2: %#", self.revealViewController.SWSegueFrontIdentifier);
Any ideas on what I can do to get this to work?
EDIT: Only thing that I can think of is some sort of memory retention problem, but I can't seem to figure it out.
after declaring the property
#property (strong, atomic, retain) NSString *SWSegueFrontIdentifier;
ave you used a synthesize to create the getters and setters
#synthesize SWSegueFrontIdentifier = _SWSegueFrontIdentifier;
and then you just do it like this
self.revealViewController.setSWSegueFrontIdentifier =#"sw_front";
This is what I came up with.
Related
I am trying to use storyboards in my application. I began well, I have added two view controllers with a button to go from the first to the second.
The problem is in this second view controller: the objects I add on it and link with the code do not work. When I set a breakpoint in the view controller code, the 'self.property' is set to nil, whereas it should be instantiated by the storyboard.
I have been looking for an answer for hours, and I really don't understand the problem, since all the rest seems to be good.
I have tried to write the property in the code (strong/nonatomic, nonatomic/retain and even weak/nonatomic), to link the object directly to the code so that it creates the property automatically, but I never get anything else than "nil" with breakpoints.
viewController.h:
#interface NMLoadingViewController : UIViewController
{
__weak IBOutlet UIProgressView *imageProcessingProgressView;
}
#property (weak, nonatomic) IBOutlet UIProgressView *imageProcessingProgressView;
#end
.m:
#synthesize imageProcessingProgressView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// Custom initialization
NSLog(#"INIT.");
}
(amont other lines of irrelevant code)
If I set the breakpoint to the "INIT." line, my imageProcessingProgressView is nil. I can't see a reason for that, I guess I have missed a very little detail...
(Note that I have tried this with other objects, like a UILabel, but it did not work either. Stranger, when I had two objects, one of them had an adress which was not nil, but still it was corrupted and did not show the right object.)
Edit: It was a lot of trouble for nothing... The problem is about the Variable View in XCode, which show my variable to "nil", whereas a log shows me a correct object...
Remove this...
{
__weak IBOutlet UIProgressView *imageProcessingProgressView;
}
...and make the property strong.
Change your log message to...
NSLog(#"INIT: %#", self.imageProcessingProgressView);
...and see if you still have a problem. If you do, then take another look at your storyboard connections.
Make sure NMLoadingViewController is the class on your viewController
First try out the answer by #Eric because I do believe that is the real issue.
Also, make sure that you are actually using the interface builder to hook the controls back to the view controller. This is done by dragging a line from the control back to the property of the view controller.
I have two view controllers, one is MainViewController, the other is SetupViewController. I want a UILabel on MainViewController to set the text to the contents of a UITextField from the SetupViewController when a button is pressed in the SetupViewController.
In SetupViewController, I have this in the IBAction:
- (IBAction)donePressed:(id)sender {
MainViewController *mvc = [[MainViewController alloc] init];
[mvc.testLabelOnMVC setText:testTextFieldOnSVC.text];
[release mvc];
}
testLabelOnMVC (and testTextFieldOnSCV, with respective terms) is
#property (nonatomic, retain) UILabel *testLabelOnMVC;
and is also synthesized.
Every time I try, it doesn't work. Nothing happens, nothing changes. I have no errors or warnings. Can anyone help me out?
The view of your MainViewController does not exist until you reference the MainViewController's view property (which forces viewDidLoad to execute). You must reference the view (or otherwise force the view to be constructed) before you attempt to modify any UI objects in the MainViewController.
You are allocating a new MainViewController when you press the button, then you are setting the text of the label on this new controller, not on the MainViewController that your app is showing.
To fix this, create either and IBOutlet or iVar that points to the original MainViewController and set the text on that instead.
Easiest way is to create a #property in the main view controller and write the text in there. Then just read it in the second MVC's viewDidLoad.
The only views that MainViewController should worry about are the ones that it owns; it shouldn't be trying to access the view hierarchy managed by SetupViewController. Likewise, SetupViewController should not directly modify views in MainViewController's view graph.
The right way to do what you're asking is for the two controllers to talk to each other, either directly or via the data model. For example, let's say that your MainViewController instantiates SetupViewController. If that's the case, it'd be natural for mvc to set itself as svc's delegate, so that svc sends it a messages like -setupController:didUpdateTestStringTo:. MainViewController's implementation of that method could then save the new test string somewhere and update it's testLabel field.
Another example: MainViewController instantiates SetupViewController. SetupViewController contains a field where the user can enter a new value for the test string. Before exiting, SetupViewController writes the contents of that field into NSUserDefaults or some other common data storage. When control returns to MainViewController, that object reads the shared data and updates itself as necessary, including setting the new value for testLabel.
There are other variations on the same theme, but the common thread here is that neither view controller has to directly access views that it doesn't own.
You can change the text of the label if the view is already loaded. Instead of initializing the viewcontroller, retrieve it from the view stack if you are using navigation controller.
I dont know if your viewController is already loaded or not.
I'm building an app that uses a TabBar controller in which one of the view controllers an NSMurableArray is set (and potentially modified). I then need to use that same array to populate a table on one of the other views when it is selected. I've looked into using a singleton (as was provided as an answer to this question on this website already) but haven't had much luck.
Would a singleton be the best way to go or is there a better way of doing it? I'd appreciate any help/examples if possible?
You have several options for doing this, here are 2...
1.) have the NSMutableArray be a property of the one view controller so the other one can access it like viewController1.mutableArray. To do just add #property (nonatomic, retain) NSMutableArray *mutableArray to your viewController class (using whatever name you want).
2.) Pass the array through a method from the first viewController to the other and keep a reference to that array in the other class.
You can 'attach' controllers to each other, just like you 'attach' ui elements to controllers. E.g., declare variable
IBOutlet ReferencedController *referencedMenu;
and then in Interface Builder draw a line between referenced and referencing controllers.
Do I understand you correctly?
Thanks for your help, in the end this is how I have done it:
UIViewController *tmpNamesListVC = [self.tabBarController.viewControllers objectAtIndex:1];
self.names = [tmpNamesListVC names];
When it builds i'm getting a 'UIViewController may not respond to -names' warning but everything compiles and runs as it should.
I've recently been doing a lot of Objective-C programming, and just got back into doing more iPhone development. I've done a lot of programming using MVC in other languages/frameworks, but I just want to make sure I'm using MVC properly in my iPhone Development.
I created a new iPhone Utility Application, which creates two views: MainView and FlipsideView. Both have a controller (FlipsideViewController and MainViewController) and XIB file of their own.
What I've been doing is putting the IBOutlet UIControl myControl variables in my MainView.h or FlipsideView.h files and then tying the controls in Interface Builder to those variables. Then I put any IBAction SomeAction myAction methods in the MainViewController.h and FlipsideViewController.h files and tying the events to those methods in Interface Builder.
This seems to be conceptually correct, but seems to cause problems. Say I have a button that when clicked it changes a label's text. So the Controller doesn't have a clue of what the variable name of the label is in the OnTouchUp event handler for my button. So I make a #property for it. But since the MainViewController.view property isn't of type MyView, I get warnings or errors whenever I try to access those properties from the view controller.
I am doing this correctly? Is there a better way to do this? If this is correct, how do I properly work with those variables without getting warnings or errors?
Thanks
Here's some code showing what I'm doing:
MainView.h
#import ...
#interface MainView : UIView
{
IBOutlet UILabel* label;
IBOutlet UIButton* button;
}
#property UILabel* label;
#property UIButton* button;
#end
MainViewController.m
-(void) buttonTouchUp:(id) sender
{
self.view.label.text = #"The button was pressed!"; //This gives error because label is not in the view structure or union
[self.view label].text = #"The button was pressed!"; //This gives a warning
}
I know I can cast the view to be of the right type, but that seems like a hack job.
I know I can live with the warning, but a warning says to me that I'm doing something that I probably shouldn't be doing. I don't believe the SDK would set me up to do have to do something like that all the time.
I must just be misunderstanding what the View is supposed to be and I'm using it incorrectly.
Most code I've seen and written myself keeps all the outlets and the actions on the controller. The button sends a message to the controller (via IBAction), then the controller updates the label (via IBOutlet). In other words, putting outlets on your views is unusual.
Views shouldn't be connected to other views unless they have some special relationship, like maybe back/forward buttons that target a UIWebView... but even then, you find out you need a controller to enable/disable the buttons as appropriate.
I have been having huge issues with this, so I drew a diagram...
alt text http://tomsfil.es/7bdead0a.png
I successfully get to the CLASS A - METHOD B but at that point, IBOutlet Z is Nil? :(
Any ideas?
note
Somebody told me it might be an Overrelease and to use NSZombieEnabled but that confused me
It's all a matter of when you call the class. Right after you create a view controller with initWithNibName, nothing is actually wired up yet - it's only after the view is created that IBOutlets are created and wired in.
One trick is that you can simply ask the view controller for .view, like so:
myViewController.view;
Then the view will be created and the IBOutlet will exist. A better method though, is to create properties on the view controller that you set, and then either in viewDidLoad, or in viewWillAppear you use those properties to set values for your outlets.