Hmm I just thought of this, if I alloced the button like this:
play.pauseButton = UIButton alloc] etc...... Maybe that would fix it. I am sure that I am just doing something stupid here :P
I also made sure I connected it in Interface Builder
Then in CCLayerClass I do this:
Code:
Play *play = [[[Play alloc] init] autorelease];
if(play.pauseButton == NULL) {
NSLog( @"pause button is NULL");
}
play.pauseButtonVisible = YES;
But that NSLog gets called! Why is my pauseButton NULL? I just need to alloc it so it stays alive, is that possible?
Thanks!
You should never muck with the view objects of a view controller outside of that view controller. That breaks the MVC design pattern, and tightly couples the two view controllers together.
A view controller's views are the private property of that view controller. If view controllers start playing with each other's privates, the are effectively married to each other, and you can't change one without changing the other.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
In this case I have to otherwise what I want done will never be possible (Im using Cocos2D also). All I simply want to do is unhide a button at a particular instance but it is NULL.
So how could I fix the button from being NULL? Also I can't call the ViewDidLoad in the other View Controller if you were going to mention a fix otherwise it will mess up the features in my app!
Edit: How about this. If you say I shouldn't control a object from another view controller that the object isn't it, is it possible to call a method in the view controller that does hold the object but without calling the ViewDidLoad?
also you need to either use interface manager to allocate the button or allocate it in viewDidLoad. Once its allocated you should be able to pass it into any function you want and manipulate it however u like.
But I want to avoid calling the ViewDidLoad. Maybe there is a workaround for that too which I am unaware of. I guess I can call it but how would I set a BOOL from my CCLayerClass and then use that BOOL value in the Play class's ViewDidLoad to either do the normal ViewDidLoad stuff or to do nothing?
its not clear what you are trying to do, but whatever is it, you should be able to allocate it in viewDidLoad, then pass it to whatever function you want, which can then pass back a bool. You can then use that bool to modify your button however you want.
If you do your coding in phases, you might have better luck. When getting ready to write code that spans more than one script, i usually do something like this:
Step 1) Get the entire code to work in viewDidLoad of a single script.
Step 2) create a seperate function within the same script that passes info back and forth.
Step 3) Move that function out to the other script where you wanted it in the first place.
In this case I have to otherwise what I want done will never be possible (Im using Cocos2D also). All I simply want to do is unhide a button at a particular instance but it is NULL.
So how could I fix the button from being NULL? Also I can't call the ViewDidLoad in the other View Controller if you were going to mention a fix otherwise it will mess up the features in my app!
Edit: How about this. If you say I shouldn't control a object from another view controller that the object isn't it, is it possible to call a method in the view controller that does hold the object but without calling the ViewDidLoad?
Indeed, add a boolean hideButton property to the view controller.
In your view controller's viewWillAppear method, add code to show/hide the button based on the property.
If another class will ever set the hideButton property while the view controller is visible, create a custom setter that sets the button's hidden property after changing the instance variable.
That way, you can set the property at any time, even if the view controller's views haven't been loaded yet.
That is almost certainly why the button is nil when you're trying to set it (and another reason not do change views from outside the view controller.)
Another reason not to change views from outside the view controller is low memory. In a low memory condition, the system will unload the views from every view controller except the frontmost view controller. If you have the state data for your view objects (button show/hide state, label text if it changes, slider values, etc) saved in instance variables, and have the viewWillAppear method set the values, the view controller recreates it's views and puts them back the way they were supposed to be automatically.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Ok I will do so, but the only part I am confused about is this:
Quote:
If another class will ever set the hideButton property while the view controller is visible, create a custom setter that sets the button's hidden property after changing the instance variable.
What do you mean by that?
And after I do all of this code how would I call my Play view from my CCLayerClass?
Play *class = [[[Play alloc] init] autorelease];
class.buttonHidden = NO;
@synthesize automatically creates 2 methods, a setter and getter. You need to override the setter to not only set the ivar but to change the button's hidden property.
Code:
- (void)setButtonHidden:(BOOL)newButtonHiddenValue {
//assign newButtonHiddenValue to buttonHidden
//assign buttonHidden to the button's hidden property
}
__________________
If you are looking for a quality developer, I'm your man. Give me a PM if you are interested.
@synthesize hideButton;
//This is a custom setter for the hideButton property.
- (void)setHideButton:(BOOL)newValue
{
//set the instance variable to the new value
hideButton = newValue;
//also show/hide the button based on the new value.
//If the view hasn't been loaded, this won't do anything.
pauseButton.hidden = hideButton;
}
Code:
- (void)viewWillAppear:(BOOL)animated
{
//Update the button state in case it was changed
//before the view was loaded
pauseButton.hidden = hideButton;
}
A class outside this view controller will just need to say
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Ok so just to be sure I call it like this correct?
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
That will unhide it. But currently I want the button to be hidden at first so I clicked the hidden property in the viewdidload but it still shows at launch. So I want it to be hidden at launch but then unhidden from the CCLayerClass in one of the methods.
Ok so just to be sure I call it like this correct?
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
That will unhide it. But currently I want the button to be hidden at first so I clicked the hidden property in the viewdidload but it still shows at launch. So I want it to be hidden at launch but then unhidden from the CCLayerClass in one of the methods.
If you want the button to be hidden at first then why are you setting it to hideButton= NO when you create it?
And what do you mean you "clicked the hidden property in viewDidLoad?" That doesn't make any sense.
The code I posted lets you control the state of the button when the view is displayed. If you set it to hideButton = YES, the button will be hidden. So set play.hideButton=YES, not NO.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
If you want the button to be hidden at first then why are you setting it to hideButton= NO when you create it?
And what do you mean you "clicked the hidden property in viewDidLoad?" That doesn't make any sense.
The code I posted lets you control the state of the button when the view is displayed. If you set it to hideButton = YES, the button will be hidden. So set play.hideButton=YES, not NO.
I would have thought that would be obvious.
The view in which the pause button is in is technically holding the EAGLView but I think it is NULL at the point I am trying to change the .hidden property of the button from the CCLayerClass. I explain more below.
I am expecting that this will hide the button:
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = YES;
It did not. I will explain how my views are set up.
I switch views in View 1 my main view, that view isn't either of the two I am talking about now. My Play View has a IBOutlet of a EAGLView and Cocos2D is connected to it by a CCLayerClass. The UIButton is in the Play view above the EAGLView.
This is what I want/did:
I clicked the .hidden property in Interface Builder in my Play class (where the button is) so that when the init method of Cocos2D fires it will hide that button. When the user clicks a button in the CCLayerClass I want it to UN-Hide the button in the Play Class using this code but this doesn't work:
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
The view in which the pause button is in is technically holding the EAGLView but I think it is NULL at the point I am trying to change the .hidden property of the button from the CCLayerClass. I explain more below.
I am expecting that this will hide the button:
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = YES;
It did not. I will explain how my views are set up.
I switch views in View 1 my main view, that view isn't either of the two I am talking about now. My Play View has a IBOutlet of a EAGLView and Cocos2D is connected to it by a CCLayerClass. The UIButton is in the Play view above the EAGLView.
This is what I want/did:
I clicked the .hidden property in Interface Builder in my Play class (where the button is) so that when the init method of Cocos2D fires it will hide that button. When the user clicks a button in the CCLayerClass I want it to UN-Hide the button in the Play Class using this code but this doesn't work:
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
So yea that is my current situation.
This is a great example of why you shouldn't try to change another view controller's views directly.
After you create your play object, it's views don't exist yet. They don't get created until the view controller is about to be displayed.
That is why I told you to add code like the code below to your play view's viewWillAppear method:
Code:
- (void)viewWillAppear:(BOOL)animated
{
//Update the button state in case it was changed
//before the view was loaded
pauseButton.hidden = hideButton;
}
That code will be invoked right before the Play view controller appears on the screen. It will use the saved state of the hideButton property to set the button to the correct shown/hidden state.
A question:
When you run this code:
Code:
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
Is there already a Play object on the screen? If so, you probably shouldn't be creating another one.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Play *play = [[[Play alloc] init] autorelease];
play.hideButton = NO;
Is there already a Play object on the screen? If so, you probably shouldn't be creating another one.
How would I tell? And you say if I already have one on the screen I shouldn't create another one so your saying that I should make it a ivar in my CCLayerClass?
And I did already have that one line of code in my viewWillAppear method