(Cocoa Mac) NSWindowController showWindow allocates/initializes a new NSWindowController? - objective-c

I have a class BrowserWindowController that extends NSWindowController. My app delegate has a BrowserWindowController that it allocates, initializes, and points an instance variable at when the app is launched. Then, it displays its window. The goal is to have a window from a NIB show up.
However, the code I am using ends up allocating TWO BrowserWindowControllers and initializes both. I have used the debugger to track down when BWC's initWithWindow method is called:
browser = [[BrowserWindowController alloc] initWithWindowNibName:#"BrowserWindow"]; //this calls initWithWindow as expected
[browser showWindow:nil]; //this allocates ANOTHER BWC and calls initWithWindow on it!
showWindow is making a new BrowserWindowController. I don't know what points to the new object it makes. It's a huge problem for me. Any way to get around this or make the window show up using a different method? Or could I at least get a pointer to the controller that showWindow creates for whatever reason?

Did you check the condition like this and try?
if !(browser)
{
browser = [[BrowserWindowController alloc] initWithWindowNibName:#"BrowserWindow"]; //this calls initWithWindow as expected
[browser showWindow:nil];
}

Worst solution ever. The problem was that I had a property in my controller called "owner" that was an NSString. NSWindowController already has an "owner" property, and I overlooked that. Somehow, that caused the NIB loader to make a second controller with no accessible pointer to it and do some other weird things.
So I renamed it, and it works now. Thank goodness... I was tearing my hair out with this problem.

Related

why setStringValue call works in viewDidLoad and viewDidAppear but not in other methods?

I am trying to change the value of the label here.
Can anyone explain me why the following method call:
[_detailLabel setStringValue:#"this is new label value"];
works if I make the call from viewDidLoad and viewDidAppear methods, but it doesn't work in the method that I created:
-(void)changeLabelValue : (NSString *) newVal {
[_detailLabel setStringValue:#"this is new label value"];
NSLog (#"Hello from changeLabelValue method");
}
Please note that when I call this method from anywhere from my code, the NSLog message IS displayed but the value of the label is not changed...
Any help is deeply appreciated.
Pointing me to resource where I can learn more on this subject will also do the trick, and will be also deeply appreciated.
Regards, John.
Make sure that changeLabelValue: is being called after viewDidLoad is called (or the view controller has been displayed). If you call it before the view is loaded, _detailLabel will be nil since it hasn't been loaded yet.

How do I override -windowTitleForDocumentDisplayName?

In the Mac Developer Reference for windowTitleForDocumentDisplayName, here, it suggests that a window controller can override this method,
to customize the window title. For example, a CAD application could append β€œ-Top” or β€œ-Side,” depending on the view displayed by the window.
But I can't find any example code showing exactly how to do this. When I override this method in my custom window controller class, it doesn't seem to get called, when I create a new instance of my window controller class. I've been searching the web for a couple of days to find information about this method, but there is hardly any info out there. Much of it is really old - my other question is one of the only recent pages linked to by Google.
Help please!
This method appears to be called only when the NSWindowController's document is actually set to an NSDocument instance.
in your NSWindowController subclass:
- (NSString *)windowTitleForDocumentDisplayName:(NSString *)displayName
{
NSString *newName = [NSString stringWithFormat:#"%# Test", displayName];
return newName;
}
NOTE: this is called from NSDocumentController's openUntitledDocumentAndDisplay: method, so the input displayName will be some variant of "Untitled".

Delegate gets called but the calling viewcontroller is released

Probably a noob question, but I cannot seem to get it right at the moment. I am working on an app where I have an Actionsheet for the confirmation of some basic things. However after the delegate is called for that Actionsheet my initial calling object is released (or not initiated).
In the delegate method I then want to call a method on that object but it just not do anything from that point.
The self.inviteSponsorsFromVC is not initiated anymore in this scenario and I want to call the saveSponsorWithEmail method from it. I cannot just reinitiate it, as the object had some objects in it, it has to use.
Everything works correctly if I just remove the actionsheet and call the saveSponsorWithEmail method directly without using a delegate.
This is my delegate method:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//Get the name of the current pressed button
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:NSLocalizedString(#"Send invitation", nil)]) {
ContactFromAddressBook *contactFromAddressBook = [self.tableData objectAtIndex:selectedIndex.row];
[self.inviteSponsorsFromVC saveSponsorWithEmail:contactFromAddressBook.email andName:contactFromAddressBook.fullName];
}
if ([buttonTitle isEqualToString:NSLocalizedString(#"Cancel", nil)]) {
NSLog(#"Cancel pressed --> Cancel ActionSheet");
}
}
My guess is that at in the delegate method the content of self.inviteSponsorsFromVC is nil. In Objective-C, when you send a message to nil the message is simply ignored (unlike C++, for instance, where you get a crash when you call a method on a NULL object).
As an experiment you can try either one of these:
If you use ARC, make the property self.inviteSponsorsFromVC a strong reference
If you don't use ARC, say [self.inviteSponsorsFromVC retain] at some point before you display the action sheet
Either way, what you need to do is to make sure that the object in self.inviteSponsorsFromVC is not deallocated before you invoke a method in it.
EDIT after your comment
The property declaration is good, it's got the strong attribute on it. In your InviteSponsorsFrom class, try to add a dealloc method and set a breakpoint there to see if the object is deallocated, and where the call comes from.
- (void) dealloc
{
[super dealloc];
}
Also make sure that an instance of InviteSponsorsFrom is created in the first place. I assume you have an initializer somewhere in that class where you can set a breakpoint and/or add an NSLog statement to make sure that the instance is created.

how to call a method from a class in another class

I'm working to a new app for mac osx where i'm using a drag and drop system to let the user to input some files [this part works well] and i have a tabelView where i would like to display the paths of files inputed.
I have the next method in tabelViewController.m:
-(void)add{
NSLog(#"da");
[list addObject:[[Source alloc] init]];
[tableView reloadData];
}
In the DropView.m i included the tabelViewController.h and i'm trying to call the add method but it does nothing:
#import "TableViewController.h"
.....
- (void)concludeDragOperation:(id<NSDraggingInfo>)sender{
[self setNeedsDisplay:YES];
TableViewController *tvc;
[tvc add];
}
Can someone to figure out why it doesn't do anything ?
Edit1:
Ok after I fallow the answers, my concludeDragOperation method looks like this:
- (void)concludeDragOperation:(id<NSDraggingInfo>)sender{
[self setNeedsDisplay:YES];
TableViewController *tvc = [[TableViewController alloc] init];
[tvc add];
[tvc rD];
}
rD is a method from tableViewController which contain the reloadData method.
But it doesn't want to work it don't reload the table view.
Any ideea ???
tvc needs to point to an actual object. [[tvc alloc] init]
Otherwise you are simply calling add on nil. This doesn't cause your program to crash as you might expect in other languages. Try it out and see what happens.
it seems as if you missed a great chunk regarding how OOP and Objective-C work (seriously, no offense there).
What link is there between DropView.m and tableViewController.h do you have?
By typing TableViewController *tvc; all you are doing is creating a pointer. You are neither creating an object nor pointing to an object, you have just simply created a pointer that can eventually point to an object in memory of type tableViewController.
Solution:
What you will need to do, is to somehow create a link between the two classes. For instance, you could create a custom delegate method for DropView that could communicate with any class who uses that custom DropViewDelegate methods. So, you could create a delegate method that tells objects that follow that delegate protocol that you just concluded a drag operation. A tutorial how to do so can be found at my blog [it's a permalink].
I am happy to post code, or you can read it on my blog. Good Luck.

Delegate issues using GameKitHelper - cocos2d

I'm probably over-thinking this, but I've been stuck on it a while, so I figured I'd reach out for some advice/help.
I'm using GameKitHelper (http://www.learn-cocos2d.com/tag/gamekithelper/), thus far, it's been pretty helpful. So, I have the helper initialized on in my "MainMenu" with the protocol implemented, etc:
#interface MainMenu : CCLayer <GameKitHelperProtocol> {
...
GameKitHelper *gkHelper;
}
In the main menu code, I have this:
gkHelper = [GameKitHelper sharedGameKitHelper];
gkHelper.delegate = self;
[gkHelper authenticateLocalPlayer];
Seems pretty strait forward. In fact, it works, exactly as I expect it to. I have the methods it's looking to be in place there (even though most don't have code associated with them (yet?)). My issue is when I actually want to start my game. So, I'm using the onMatchFound() to start the game, which basically works:
-(void) onMatchFound:(GKMatch*)match
{
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.2f scene: [[MultiplayerLoading initWithData:Multiplayer withMultiplayerType:gameTypeToPlay andInitiator:false] scene]]];
}
My issue is when I'm attempting to play the game, the receive delete method fires in the MainMenu NOT the game class, so things aren't being calculated properly.
Is there a way to pass the control to the game layer from the main menu when the onMatchFound fires?
Hopefully this gives enough info, let me know if not.
Thanks everyone!
There's two ways you can make this work. One way is to have a global Singleton class as the GameKitHelper delegate. You can then relay messages via this Singleton class.
Or simply assign the new scene as the GameKitHelper delegate:
-(void) onMatchFound:(GKMatch*)match
{
CCScene* newScene = [MyNewScene scene];
[GameKitHelper sharedGameKitHelper].delegate = newScene;
[[CCDirector sharedDirector] replaceScene:newScene];
}
Also, there seems to be something wrong with how you create the new scene:
[[MultiplayerLoading initWithData:Multiplayer
withMultiplayerType:gameTypeToPlay
andInitiator:false] scene];
It appears you are first calling the init method, then the class method scene which allocates the instance (see the scene implementation). It looks to me like it should rather be:
[[[MultiplayerLoading alloc] initWithData:Multiplayer
withMultiplayerType:gameTypeToPlay
andInitiator:false] autorelease];
Btw, the Cocoa Coding Guidelines recommend not to "link" method parameters with the "and" keyword and using "with" more than once is also quite odd. Cleaned up it should rather be:
[[[MultiplayerLoading alloc] initWithData:Multiplayer
multiplayerType:gameTypeToPlay
initiator:false] autorelease];
Excuse me for being picky. :)
Could this be because your MainMenu is set as the delegate in your GameKitHelper? I'd try setting the delegate to the game inside onMatchFound. Give that a try.