Properties being set to nil?


Dave
 

Hi All,

I have a View Controller that is Instantiated in code from a storyboard file:

myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

I then set some delegates:

[myGameViewController setGameControlDelegate:[self getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[self getGameCommandDelegate]];

These methods just store the delegate in Strong properties, I’ve checked and they are set ok.

However, I put a break point in viewDidLoad: and look at the properties again they have been set to nil!

I’ve checked and the properties in question are only set once in the appropriate setDelagateMethod.

Is there some magic going on? Is it legal to do this?

Thanks in advance for any help?

Dave


Jon Gotow
 

Any chance you're reloading your view controller (when starting a new game or whatever) and not subsequently setting the delegates again?

- Jon

On Jan 16, 2020, at 9:55 AM, Dave <dave@...> wrote:

Hi All,

I have a View Controller that is Instantiated in code from a storyboard file:

myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

I then set some delegates:

[myGameViewController setGameControlDelegate:[self getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[self getGameCommandDelegate]];

These methods just store the delegate in Strong properties, I’ve checked and they are set ok.

However, I put a break point in viewDidLoad: and look at the properties again they have been set to nil!

I’ve checked and the properties in question are only set once in the appropriate setDelagateMethod.

Is there some magic going on? Is it legal to do this?

Thanks in advance for any help?

Dave






Dave
 

Hi,

This is the only place the View Controller is instantiated. One thing I’ve notice is that if I set a breakpoint in ViewDidLoad and print self:

< LTWMacGameViewController: 0x600003500840>

and then again in setGameControlDelegate

<LTWMacGameViewController: 0x6000035082c0>

The addresses are different, so it looks like the View Controller returned by instantiateControllerWithIdentifier is different to the one actually instantiated?

Cheers
Dave


On 16 Jan 2020, at 18:00, Jon Gotow <gotow@...> wrote:

Any chance you're reloading your view controller (when starting a new game or whatever) and not subsequently setting the delegates again?

- Jon


On Jan 16, 2020, at 9:55 AM, Dave <dave@...> wrote:

Hi All,

I have a View Controller that is Instantiated in code from a storyboard file:

myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

I then set some delegates:

[myGameViewController setGameControlDelegate:[self getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[self getGameCommandDelegate]];

These methods just store the delegate in Strong properties, I’ve checked and they are set ok.

However, I put a break point in viewDidLoad: and look at the properties again they have been set to nil!

I’ve checked and the properties in question are only set once in the appropriate setDelagateMethod.

Is there some magic going on? Is it legal to do this?

Thanks in advance for any help?

Dave












Sandor Szatmari
 

I’ve seen this happen if the view controller is instantiated in code and in the NIB (not sure about storyboards)

It gets hooked up correctly one time and things are nil in the other case. Are you subclassing NSViewController and setting it to the class of a view controller in your storyboard? If so, and your also instantiating the view controller in code you’ll see two initializations of the object. One will be good and the other may or may not.

Sandor

On Jan 16, 2020, at 12:20, Dave <dave@...> wrote:


Dave
 

Hi Sandor,

Yes, LTWGameViewController is a subclass of NSViewController and I set the Class in the Storyboard.

When I set a breakpoint in the Set Delegate method it shows the property set ok. Later on it responds to an IBAction and its set to nil. It certainly looks like there are 2 objects! Is this a bug? Is there a work-around?

Thanks a lot for your help.
Dave

On 16 Jan 2020, at 18:36, Sandor Szatmari <admin.szatmari.net@...> wrote:

I’ve seen this happen if the view controller is instantiated in code and in the NIB (not sure about storyboards)

It gets hooked up correctly one time and things are nil in the other case. Are you subclassing NSViewController and setting it to the class of a view controller in your storyboard? If so, and your also instantiating the view controller in code you’ll see two initializations of the object. One will be good and the other may or may not.

Sandor

On Jan 16, 2020, at 12:20, Dave <dave@...> wrote:


Jon Gotow
 

On Jan 16, 2020, at 10:48 AM, Dave <dave@...> wrote:

Yes, LTWGameViewController is a subclass of NSViewController and I set the Class in the Storyboard.

When I set a breakpoint in the Set Delegate method it shows the property set ok. Later on it responds to an IBAction and its set to nil. It certainly looks like there are 2 objects! Is this a bug? Is there a work-around?
The fact that you've got two instances of your LTWGameViewController certainly sounds like a bug. It's difficult to tell without looking at your whole project, but my guess is that you've got one instance loaded from the storyboard, and then you're creating a second one programmatically later. Can you just set an outlet to point to the instance loaded from your storyboard and leave it from that (that's what you should be doing unless you need multiple instances of LTWGameViewController in your app).

- Jon


Dave
 

Hi Jon,

Can you just set an outlet to point to the instance loaded from your storyboard and leave it from that (that's what you should be doing unless you need multiple instances of LTWGameViewController in your app).

I’m not sure what you mean? Do you mean an outlet to the LTWGameViewController in the StartupWindowController?

Here’s what I am doing:

In AppDelegate::applicationDidFinishLaunching

myStoryboard = [NSStoryboard storyboardWithName:kLTWStartupStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWStartupWindowControllerID];
if (myGameWindowController == nil)
{
return;
}
self.pStartupWindowController = myGameWindowController;

[myGameWindowController showWindow:nil];

----------------------

In the StartupViewController:


-(void) viewDidAppear
{
NSStoryboard* myStoryboard;
NSWindowController* myGameWindowController;
LTWMacGameViewController* myGameViewController;
NSString* myGameID;
LTWSudokuAppManager* myAppManager;

//**
//** Instantiate the Game Window Controller
//**
myStoryboard = [NSStoryboard storyboardWithName:kLTWGameStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainWindowControllerID];
if (myGameWindowController == nil)
{
return;
}

//**
//** Instantiate the Game View Controller
//**
myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

//**
//** Create a New Game  
//**
myGameID = [self.pSingletonManager.pSudokuAppManager newGameWithReportDelegate:myGameViewController];

//**
//** Set the Game View Controller Delegates
//**
myAppManager = self.pSingletonManager.pSudokuAppManager;
[myGameViewController setGameControlDelegate:[myAppManager getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[myAppManager getGameCommandDelegate]];

self.pGameViewController = myGameViewController;
self.pGameWindowController = myGameWindowController;
[self.pGameWindowController showWindow:nil];

//**
//** Close the Startup Window
//**
[self.view.window close];


————————————————————

When I run I get this in the log:

initWithCoder: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>
viewDidLoad: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>
initWithCoder: <LTWMacGameViewController: 0x60000350d4a0>
awakeFromNib: <LTWMacGameViewController: 0x60000350d4a0>
setGameCommandDelegate: <LTWMacGameViewController: 0x60000350d4a0>
viewWillAppear: <LTWMacGameViewController: 0x600003514370>
viewDidAppear: <LTWMacGameViewController: 0x600003514370>
catchBug: <LTWMacGameViewController: 0x60000350d4a0>

catchBug is a method that gets called after a delay after the delegate is set.

So it does look like there are 2 instances!


Cheers
Dave



On 16 Jan 2020, at 19:06, Jon Gotow <gotow@...> wrote:

On Jan 16, 2020, at 10:48 AM, Dave <dave@...> wrote:

Yes, LTWGameViewController is a subclass of NSViewController and I set the Class in the Storyboard.

When I set a breakpoint in the Set Delegate method it shows the property set ok. Later on it responds to an IBAction and its set to nil. It certainly looks like there are 2 objects! Is this a bug? Is there a work-around?

The fact that you've got two instances of your LTWGameViewController certainly sounds like a bug. It's difficult to tell without looking at your whole project, but my guess is that you've got one instance loaded from the storyboard, and then you're creating a second one programmatically later. Can you just set an outlet to point to the instance loaded from your storyboard and leave it from that (that's what you should be doing unless you need multiple instances of LTWGameViewController in your app).

- Jon






Dave
 

Looking at the log (and reformatting it a bit):

initWithCoder: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>
viewDidLoad: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>

initWithCoder: <LTWMacGameViewController: 0x60000350d4a0>
awakeFromNib: <LTWMacGameViewController: 0x60000350d4a0>
setGameCommandDelegate: <LTWMacGameViewController: 0x60000350d4a0>

viewWillAppear: <LTWMacGameViewController: 0x600003514370>
viewDidAppear: <LTWMacGameViewController: 0x600003514370>

catchBug: <LTWMacGameViewController: 0x60000350d4a0>

So it looks like the 0x600003514370 instance is the good one and 0x60000350d4a0 the imposter!

On 16 Jan 2020, at 19:38, Dave <dave@...> wrote:

Hi Jon,

Can you just set an outlet to point to the instance loaded from your storyboard and leave it from that (that's what you should be doing unless you need multiple instances of LTWGameViewController in your app).

I’m not sure what you mean? Do you mean an outlet to the LTWGameViewController in the StartupWindowController?

Here’s what I am doing:

In AppDelegate::applicationDidFinishLaunching

myStoryboard = [NSStoryboard storyboardWithName:kLTWStartupStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWStartupWindowControllerID];
if (myGameWindowController == nil)
{
return;
}
self.pStartupWindowController = myGameWindowController;

[myGameWindowController showWindow:nil];

----------------------

In the StartupViewController:


-(void) viewDidAppear
{
NSStoryboard* myStoryboard;
NSWindowController* myGameWindowController;
LTWMacGameViewController* myGameViewController;
NSString* myGameID;
LTWSudokuAppManager* myAppManager;

//**
//** Instantiate the Game Window Controller
//**
myStoryboard = [NSStoryboard storyboardWithName:kLTWGameStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainWindowControllerID];
if (myGameWindowController == nil)
{
return;
}

//**
//** Instantiate the Game View Controller
//**
myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

//**
//** Create a New Game  
//**
myGameID = [self.pSingletonManager.pSudokuAppManager newGameWithReportDelegate:myGameViewController];

//**
//** Set the Game View Controller Delegates
//**
myAppManager = self.pSingletonManager.pSudokuAppManager;
[myGameViewController setGameControlDelegate:[myAppManager getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[myAppManager getGameCommandDelegate]];

self.pGameViewController = myGameViewController;
self.pGameWindowController = myGameWindowController;
[self.pGameWindowController showWindow:nil];

//**
//** Close the Startup Window
//**
[self.view.window close];


————————————————————

When I run I get this in the log:

initWithCoder: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>
viewDidLoad: <LTWMacGameViewController: 0x600003514370>
awakeFromNib: <LTWMacGameViewController: 0x600003514370>
initWithCoder: <LTWMacGameViewController: 0x60000350d4a0>
awakeFromNib: <LTWMacGameViewController: 0x60000350d4a0>
setGameCommandDelegate: <LTWMacGameViewController: 0x60000350d4a0>
viewWillAppear: <LTWMacGameViewController: 0x600003514370>
viewDidAppear: <LTWMacGameViewController: 0x600003514370>
catchBug: <LTWMacGameViewController: 0x60000350d4a0>

catchBug is a method that gets called after a delay after the delegate is set.

So it does look like there are 2 instances!


Cheers
Dave



On 16 Jan 2020, at 19:06, Jon Gotow <gotow@...> wrote:

On Jan 16, 2020, at 10:48 AM, Dave <dave@...> wrote:

Yes, LTWGameViewController is a subclass of NSViewController and I set the Class in the Storyboard. 

When I set a breakpoint in the Set Delegate method it shows the property set ok. Later on it responds to an IBAction and its set to nil. It certainly looks like there are 2 objects! Is this a bug? Is there a work-around?

The fact that you've got two instances of your LTWGameViewController certainly sounds like a bug. It's difficult to tell without looking at your whole project, but my guess is that you've got one instance loaded from the storyboard, and then you're creating a second one programmatically later. Can you just set an outlet to point to the instance loaded from your storyboard and leave it from that (that's what you should be doing unless you need multiple instances of LTWGameViewController in your app).

- Jon







Jon Gotow
 

Oh - there you go. Assuming that myGameWindowController is the parent window controller that manages myGameViewController, it will create an instance of your LTWMacGameViewController class when it loads. Calling [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID] afterwards will create another instance of LTWMacGameViewController that's just floating in memory, not referenced by the window controller.

What you want to do is get the instance of LTWMacGameViewController that's managed by the window controller. Do this instead:

myGameViewController = myGameWindowController.contentViewController;

That'll fix it.

- Jon

On Jan 16, 2020, at 11:38 AM, Dave <dave@...> wrote:

//**
//** Instantiate the Game Window Controller
//**
myStoryboard = [NSStoryboard storyboardWithName:kLTWGameStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainWindowControllerID];
if (myGameWindowController == nil)
{
return;
}

//**
//** Instantiate the Game View Controller
//**
myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}


Dave
 

Hi Jon,

Thanks a lot!

I was just about coming to the same conclusion and was trying to figure out how to get the ViewController from the Window and then your message arrived.

That fixed it! All working well now!

Thanks again
Dave

On 16 Jan 2020, at 20:27, Jon Gotow <gotow@...> wrote:

Oh - there you go. Assuming that myGameWindowController is the parent window controller that manages myGameViewController, it will create an instance of your LTWMacGameViewController class when it loads. Calling [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID] afterwards will create another instance of LTWMacGameViewController that's just floating in memory, not referenced by the window controller.

What you want to do is get the instance of LTWMacGameViewController that's managed by the window controller. Do this instead:

myGameViewController = myGameWindowController.contentViewController;

That'll fix it.

- Jon


On Jan 16, 2020, at 11:38 AM, Dave <dave@...> wrote:

//**
//** Instantiate the Game Window Controller
//**
myStoryboard = [NSStoryboard storyboardWithName:kLTWGameStoryboardName bundle:nil];
myGameWindowController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainWindowControllerID];
if (myGameWindowController == nil)
{
return;
}

//**
//** Instantiate the Game View Controller
//**
myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}




Alex Zavatone
 

If the address is different it is another instance.


On Jan 16, 2020, at 11:20 AM, Dave <dave@...> wrote:

Hi,

This is the only place the View Controller is instantiated. One thing I’ve notice is that if I set a breakpoint in ViewDidLoad and print self:

< LTWMacGameViewController: 0x600003500840>

and then again in setGameControlDelegate

<LTWMacGameViewController: 0x6000035082c0>

The addresses are different, so it looks like the View Controller returned by instantiateControllerWithIdentifier is different to the one actually instantiated?

Cheers
Dave


On 16 Jan 2020, at 18:00, Jon Gotow <gotow@...> wrote:

Any chance you're reloading your view controller (when starting a new game or whatever) and not subsequently setting the delegates again?

- Jon


On Jan 16, 2020, at 9:55 AM, Dave <dave@...> wrote:

Hi All,

I have a View Controller that is Instantiated in code from a storyboard file:

myGameViewController = [myStoryboard instantiateControllerWithIdentifier:kLTWGameMainViewControllerID];
if (myGameViewController == nil)
{
return;
}

I then set some delegates:

[myGameViewController setGameControlDelegate:[self getGameControlDelegate]];
[myGameViewController setGameCommandDelegate:[self getGameCommandDelegate]];

These methods just store the delegate in Strong properties, I’ve checked and they are set ok.

However, I put a break point in viewDidLoad: and look at the properties again they have been set to nil!

I’ve checked and the properties in question are only set once in the appropriate setDelagateMethod.

Is there some magic going on? Is it legal to do this?

Thanks in advance for any help?

Dave