Make application startup with size and position it was when it was closed - xcode

I'm currently creating a application that, when it reopens need to have the same size and screen position as just before it was closed.
I hope that it is just a checkmark in interface builder that i haven't noticed.
Thanks! :-)

You should implement Application Persistence.
Read more here.
When a user logs out, Lion offers them the option to restore all open apps to their current state when logging back in. To support this feature in your app you must determine for each window whether its state should be preserved using the -setRestorable: method. Cocoa will then take care of saving the state (size, position, etc.) of your windows and their associated window controllers, giving you the option to write out additional state information of custom objects associated with the windows.
To restore your application’s state when it is relaunched, every window must specify a so-called restoration class through the +restoreWindowWithIdentifier:state:completionHandler: class method (defined in the NSWindowRestoration protocol). The restoration class is then responsible for instantiating the window and its associated objects (such as the window controller). See the User Interface Preservation topic in the Mac OS X Application Programming Guide for a step by step guide.

Close to a checkbox. Set the window's frame auto-save name. That's a key naming a value in the app's preferences (which is managed by NSWindow) under which the window's frame is stored and retrieved.

Store size and position in NSUserDefaults.For example you store a cgpoint in Nsuserdefaults
as follows
CGPoint *point=CGPointMake(34,67);
NSUserDefaults* def=[NSUserDefaults standardUserDefaults];
NSString* mypointstr=NSStringFromCGPoint(point);
[def SetObject:mypointstr:forkey:#"mypoint"];
to get this next time the app starts
NSString* myprevstr=[def Objectforkey:#"mypoint"]
CGPoint* point=CGPointFromString(myprevstr);

Related

Why aren't the init and windowControllerDidLoadNib: method called when a autosaved document is automatically open ?

I have a NS(Persistent)Document.
I run my application via Xcode, then create a new document (without any data), and then quit my application.
In this case, I can check that the init and windowControllerDidLoadNib: are called
If I re-run my application with Xcode, then the previous document is automatically open.
But, I can check that neither init nor windowControllerDidLoadNib: are called.
Why is it so ?
What you're seeing is window restoration. As that document (part of the Document-Based App Programming Guide) puts it:
The document architecture implements the following steps in the window restoration process; the steps correlate to the numbers shown in Figure 5-2:
The NSWindowController method setDocument: sets the restoration class of document windows to the class of the shared NSDocumentController object. The NSWindow object invalidates its restorable state whenever its state changes by sending invalidateRestorableState to itself.
At the next appropriate time, Cocoa sends the window an encodeRestorableStateWithCoder: message, and the window encodes identification and status information into the passed-in encoder.
When the system restarts, Cocoa relaunches the app and sends the restoreWindowWithIdentifier:state:completionHandler: message to the NSApp object.
Apps can override this method to do any general work needed for window restoration, such as substituting a new restoration class or loading it from a separate bundle.
NSApp decodes the restoration class for the window, sends the restoreWindowWithIdentifier:state:completionHandler: message to the restoration class object [in this case, the document controller's class —Peter], and returns YES.
The restoration class reopens the document and locates its window. Then it invokes the passed-in completion handler with the window as a parameter.
Cocoa sends the restoreStateWithCoder: message to the window, which decodes its restorable state from the passed-in NSCoder object and restores the details of its content.
[Figure 5-2, and a paragraph explaining that views, other responders, and the document get saved and restored, too]
When the app is relaunched, Cocoa sends the restoreStateWithCoder: message to the relevant objects in turn: first to the NSApplication object, then to each NSWindow object, then to the NSWindowController object, then to the NSDocument object, and then to each view that has saved state.
The window restoration protocol is used for non-document-related windows, too, but the document machinery handles most of the dirty work for you. If you need to do anything on either side (probably both sides) of window restoration, override encodeRestorableStateWithCoder: and restoreStateWithCoder: in your document. The former is where you save transient information like selections, and the latter is where you restore that information in the resurrected document and its window(s).
The presence of coders implies that the document is initialized using initWithCoder: rather than init, though this isn't a documented fact (in the context of window restoration) that you should rely upon.

Cocoa bindings only update when window focus changes

I am using MonoMac to build a desktop download manager for Mac in C#.
My XIB has a Table View, whose columns are bound to an NSArrayController. The array controller is connected to my Main Window Controller through an IBOutlet. The array holds a bunch of HttpDownload objects, which derive from NSObject. These HttpDownload objects contain properties such as TotalSize, TotalDownloaded, Bandwidth, etc. I have decorated these properties with an [Export] attribute.
In the controller I add some HttpDownload objects to the NSArrayController using the AddObject method. A background process, started with Task.Factory.StartNew() begins the download asynchronously and updates the bound properties such as TotalDownloaded and Bandwidth as data is received.
I can see these new values being reflected in the Table View, but only once I've "forced" a UI update, for instance by causing the window to lose focus, gain focus, or by clicking on a button within the window.
I have tried setting Continuously Updates Value in IB, but this makes no difference (and reading the docs, I didn't think it should).
Does anyone know to make the UI update the bound values in "real time", instead of only when a window event occurs?
I figured this out shortly after I posted this question.
It seems that we need to manually call WillChangeValue() and DidChangeValue() for at least one of the keys that are being updated, for instance, when I updated the total downloaded:
WillChangeValue("DownloadedBytes");
DownloadedBytes += bytesRead;
DidChangeValue("DownloadedBytes");
In my case, calling these methods for just one of the updated keys seems to be enough to force an update of all the bound values.
For reference, in Objective-C these selectors are called [self willChangeValueForKey:#"keyname"] and [self didChangeValueForKey:#"keyname"].

newbie: multi-window (not Document based), is this design sound?

I'm a newbie and wanted to know if I'm on a relatively correct path.
I have a CoreData application, but not Document based (it's not a document but a central DB with many window/view possible).
Two type of window exist (B and T) to view different aspect of the data.
Since it's possible to open many B or T windows simultaneously (to show different part of the same aspect) I decided to create two subclass of NSWindowController (B_Controller, T_Controller) each with his own nib file (B.xib, T.xib).
In my AppDelegate, whenever some menu/shortcut is activated I allocate the corresponding controller, initWithWindowNibName:, show the window and enabled the File->Close menu.
Questions:
Is it correct to have one controller per window ? Or better/possible to have only one controller for all window of the same type ?
vague newbie question. Maybe this response:
NSWindowController is for one window only.
if you want a central place for all window use your AppDelegate.
if you want a central place for all window of some kind, create new class to do just that.

How do YOU implement a setup screen?

As per the tags indicate I'm developing in Xcode for the iPad.
So, I have a New Game setup screen that sits between my main menu screen and the actual game screen. The new game setup screen is supposed to allow the user to customize their game by selecting the number of players, choosing an avatar for each and setting their names. What I've done is I've setup the continue button to write all the settings to a appData.plist file before moving onto the actual game screen. When the game screen appears (the viewDidLoad method) it reads from the plist to add the players to the table with their respective Avatars and so forth.
The question is, is this the right way to pass the data from a new game setup screen to the game screen? Should I use some method to gather the information from the screen and pass it along to the game screen without writting to some file? I guess the ultimate question is how you're supposed to pass data from one view controller to another? I'm using some plist file to write to and then read from when the board appears. I get a sneaking suspicion that this is not the right way to do this. However, I figure at some point I need to save this data to file anyway since I have to be able to restore the state of my app in the even that it gets closed or interrupted. But what is YOUR preferred method to accomplish this?
You can always use the built-in settings screen for your app by making use of the Settings.bundle too. This is very easy and allows you to use the default iPad settings screen for your application settings, rather than setting up a hand-made one.
For passing through information, the information I need is usually a single object (in your case maybe Player.m) and so I create a property in the next view to hold this. And before showing the view I then do (for instance):
GameViewController *gameView = [[GameViewController alloc] initWithNibName:#"GameViewController" bundle:[NSBundle mainBundle]];
gameView.player = player;
[self.navigationController pushViewController:gameView animated:YES];
[gameView release];

cocoa document based application with shared windows?

I'm developing a document based app. Each document has three windows (and hence three window controllers). I'd like to set it up so that two of the three windows are shared between different open documents (swapping views as needed). Is this possible? Can anyone point me in the right direction (documentation or examples)?
Thanks!
In that case, these shared window controllers should not be owned by any document (since each document would then have its own pair of the “shared” windows), but should be independent, probably owned by the app delegate or the document controller. You may also want to make the windows panels, as an Inspector would be.
You'll want to have each controller track which window is main, and update its window accordingly when the main window changes, because the new main window may have a different document.
Pretty much any tutorial on how to make an Inspector window will help you here.
It looks like you need to override -makeWindowControllers in your NSDocument subclass to create the controllers you want, invoking -addWindowController: on the NSDocument subclass to add your shared window controllers.
I haven't yet had to do this, but those are the methods I'd be looking at.
From Apple's NSDocument class reference:
makeWindowControllers
Subclasses may override this method to create the initial window controller(s) for the document.
- (void)makeWindowControllers
Discussion
The base class implementation creates an NSWindowController object with windowNibName and with the document as the file’s owner if windowNibName returns a name. If you override this method to create your own window controllers, be sure to use addWindowController: to add them to the document after creating them.
This method is called by the NSDocumentController open... methods, but you might want to call it directly in some circumstances.
It is possible, but it'll take a non-trivial amount of work from your side. In summary here's what you need to do:
Override setDocument: in the window controller and maintain the associations that it has to each document.
Make sure that each window controller (NSWindowController) disassociates itself from the document before the window is closed. The same goes for each view controllers that may be handling views inside the window.
Subclass the document controller (NSDocumentController) and take care of document closing to make sure that multi-document windows are detached from documents before any of the documents are closed. NSDocumentController is a singleton and thus you need to add an instance in your MainMenu.xib file to replace the default one.
You can read my step-by-step guide how to add support for multi-document window controllers here.

Resources