NSWindowRestoration issue - cocoa

I am having a difficult time implementing this new "feature" of Mac OS X 10.7. For the most part, my application works without my having to do anything. Files reopen on launch as expected. If the file is deleted however, my application opens to nothing and a new, blank document needs to be opened via the File menu.
So, what I have done so far is when a new window is created, I call
[myWindow setRestorationClass:(Class < NSWindowRestoration >)self];
with self being my NSDocument class.
Since restoreWindowWithIdentifier:state:completionHandler: is a class method I can't call my windowController creation method [self makeWindowControllers] from within it nor could I call [self initWithType:error] to create a new document if the one being sent has been deleted. How does one tell if the document being sent has been deleted from within this method?
I've read all I can find on Apple's site and elsewhere on this issue and am getting nowhere. Realize my core understanding of this is lacking and I apologize for that. I appreciate any help. Thank you.

As far as I understand the problem I think you have to enable in your app delegate
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender;
{
return YES;
}
Did you try that?

Related

setValue:forUndefinedKey:]:

FinalViewWithSending *newView = [[FinalViewWithSending alloc]initWithNibName:#"FinalViewWithSending" bundle:nil];
newView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:newView animated:YES]; //it crashes here with a thread 1 error, SIGABRT error..
It says:
"Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[<FinalViewWithSending 0x1bef70> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key loginButton.'"
There is no variable called loginButton so Im not sure why i am getting an error...
Thank you
You are getting the error because there is no property called loginButton. Check your .xib file. There is almost certainly a bad link to a FinalViewWithSending object (likely File's Owner) that specifies loginButton even though it doesn't exist in the class code.
Phillip Mills is correct.
The answer here, for anyone searching, is to edit the storyboard and remove any link to the undefined key specified. You have to edit the storyboard file in an external editor: Right click on the storyboard listing in the hierarchy and then click on "show in finder" or what have you. Open in a text editor, remove said links by searching, save and return to Xcode. No more issue.
This happens when you remove something from the view controller improperly.
Agreeing here - Phillip Mills is correct.
Someone mentioned opening the storyboard up in a text editor - this isn't necessary.
Just click on the storyboard, go to the Connections Inspector. If you've got a problematic outlet, you'll see an exclamation marker next to the outlet. Delete it.
Since this is the first search result for this error, I decided to write an answer for rookies like me.
You are going to get this error if you have Ctrl dragged connections from Buttons which generates code in your ViewController and then you delete just the code without removing the connection.
I got this error because I had accidently added a few buttons as Outlets, when I wanted to add them as Actions. I deleted the code that got generated but the bad connections were still there.
To find and remove them, View->Utilities->Show Connections Inspector
Then click through the different buttons you have and click the x to remove the bad connections.
If you have any localizations, search for bad links in all the storyboards (expand storyboard to find localized storyboards).
This was my situation. I was looking for bad links in one storyboard and they were in the localized one.
You can try the way I used to fix my setValue:forUndefinedKey:]: problem.
I had the same problem:
I had previously made a connection using storyboards from a textfield to a header file. I later decided I wanted to rename my object's connection, unfortunately, I didn't break the connection properly. If this problem was the same as mine, a connection existed to a button previously, and the code in the header was deleted, but the connection was not.
Check the object connections in the view you are segueing to.
You can use associated objects to avoid subclassing. As for the setValue:forKey: and setValue:forUndefinedKey:, take a look in the header file (NSKeyValueCoding.h) for details.
According to your description,
Find newView in your interface builder and right click it,
you will see something like loginButton which is abnormal.
Today I was working and I presented this same error, I used the response of Phillip Mills was correct and I had some labels in one ViewController.xib that were not being assigned links, i have five bad links, once assigned links, everything works perfectly, thanks answer of Phillip Mills.
Go to the connection inspector of your xib of FinalViewWithSending view controller & remove the reference of login button. After that it will run. Try It... :)
Probably, you earlier created the LoginButton, Cmd+Shift+F and find the "LoginButton" and remove the Referencing Outlet and Re-build.
This reply might be late relative to the time the question was asked but I just had this issue and I tried all solution posted here but none worked.
Here is my solution which could help anyone in the future.
Firstly the problem, :I used a custom cell class and made my connections, everything worked fine with my app then, I renamed my custom cell class ran my app but crashed with setValue:forUndefinedKey:] error.
My solution : Clicked .xib file, selected Identity inspector and typed the new named class in Custom Class -> Class tag.
App error resolved.

Error: Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIApplication 0x6887a30> setValue:forUndefinedKey:]

The full error is: Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key.
So I have been trying what other people have been saying with similar problems. I have tried getting rid of every mention of landscapeView in the project, including the Connections in the FIle's Owner in the ViewController_iPhone.xib and then I started fresh by making outlets in the super class ViewController (since I want to use landscapeView and portraitView for iPad also) then I set up connections in ViewController_iPhone.xib and ViewController_iPad.xib to the UIView named Landscape in each respectively, and I still get this error.
I'm just starting out in app development so I'm trying to make a template for an app that is supportive of all orientations on both iPhone and iPad. Thanks for any help
EDIT: Here is a link to all my app delegate h and m and main.m : I am getting the Applications are expected to have a root view controller at the end of application launch error
EDIT 2: So I also tried to make landscapeView a property of ViewController and I made a setter method in ViewController.m but it still has the same problem.
I've found the most common place this error happens is when you instantiate a view from a xib from within a class that is not the xib's owner.
What I mean by this is you might be calling something similar to this:
[[NSBundle mainBundle] loadNibNamed:#"MyView" owner:self options:nil];
You're changing the owner, so you have to be sure that the class that self refers to has all the IBOutlet properties needed by "MyView". Usually this is done in Interface Builder, but in this case you're setting your owner programmatically, which means you can't make the connections in IB. When the IBOutlets aren't there, the app tries to make those connections and fails, giving the error you see.
My advice (without knowing any more info than you've given so far) is to check to see if you've made this call without having the proper IBOutlets.
I had to remove the NIB or XIB (or whatever they are this iteration) for the Main Interface.
It sure would be nice if Apple fully tested the broken software before unleashing it on the unsuspecting public. They could have handled the problem in any number of ways; but instead they chose a runtime crash and obscure [meaningless] error message.
Two main reason is follow
your iboutlet may break please check in storyboard or IB.
if you don't select module for custom class, see into your storyboard.
What I found is I deleted a WebView in viewcontroller.h , but haven't delete the xib file that point to this WebView !

Xcode 4.2 Template Changes - UIApplication & MainWindow.xib

Background: Up until Xcode 4.2, new projects created using any of the templates would contain a MainWindow.xib and therefore pass nil as the fourth argument of UIApplicationMain(). Starting in Xcode 4.2 all the templates instantiate the application delegate by passing the class string as the fourth argument and do not build the application's window in a xib.
It is trivial to accomplish this setup in 4.2, and of course it works as expected: create xib setting File's Owner to UIApplication and wire up the delegate, specify it in Info.plist, nil fourth argument in main().
Question: Why is Apple encouraging instantiating the application delegate and building the UIWindow in code now instead of the "old way?" What are the benefits?
Considerations: I would expect this new template behavior if you elect to use storyboarding as a way to manage the UI, but if you uncheck "Use Storyboards" I would have expected the old pass-nil-and-use-MainWindow.xib template.
This question was asked in a roundabout way here, but the answers are a little thin on discussion.
You're asking why Apple is doing something? There can be no definitive answer, unless Apple has spoken out explicitly, which they have not done.
Personally I find the new approach considerably more elegant, transparent, and bulletproof. As you rightly say, in the old approach the main nib was loaded automatically by the runtime in response to the Info.plist setting, and everything else that happened was done through the nib, in particular the instantiation of the app delegate and the window and the associated wiring (the app delegate must be made the application delegate, the window must be made the app delegate's window), except that then we come back to the code in the app delegate for final presentation of the interface.
This was hard to understand; it took a great deal of verbiage for me to describe it in my book. It was also easy to break. The nib has to know the name of the app delegate class, so if you didn't like those funny long names that were created by default, you could easily mess everything up when you changed them.
Now, however, the app delegate is simply named App Delegate and is instantiated in code by UIApplicationMain(), as you rightly say; and everything else is also done in code as a direct follow-on: the app delegate is instantiated and didFinishLaunching is called, whereupon we create the window in code, assign it to our property in code, load the nib if there is one in code, set the window's rootViewController in code, and show the interface in code as before.
Thus the bootstrapping is directly exposed to view because it's all code. This makes it easier to understand and to modify without breaking anything. It's almost as if previously the template designer was just showing off as to how much stuff could be made to happen magically and automatically behind the scenes; now everything happens out in the open, explicitly.

How does Xcode setup a document based application?

I am learning Cocoa and my understanding from reading the documentation is that when an application starts the following happens:
A shared application instance is created.
The main nib file is looked up from the applications property list so that the application knows which nib to load.
the run loop is started.
This is fine and makes sense for s single windowed application however I am confused by what xcode does when a document based application is created.
In this case there are two nib files; the first contains the application menu and the second contains the window which represents the NSDocument subclass. when I run the application a new document window is opened automatically.
Based on my understanding of how the application works outlined above I don't understand how my application knows to open the document window once the menu nib has been looked up from the property list. There is no code generated to do this as far as I can see (except for the windowNibName method but where is this called from?)
Can anyone tell me what xcode does differently so that the application knows that it is document based and therefore needs to open a document window?
Update:
What I am trying to understand is how Xcode knows how to do something different if my application is set up as a document based application rather than a single window application. As far as I am aware there is no setting to specify this and Xcode doesn't appear to generate any code to give this different behaviour.
From reading the documents over the last couple of days I think I know how this works but am not sure:
_NSApplication_has a delegate method applicationOpensUntitledFile which is called by the applications delegate.
NSDocumentController is set as the applications delegate by default and the default implementation looks for the presence of the CFBundledTypeInfo to determine if the document is document based or not and responds as is appropriate for the application (I.E. YES for document based application and NO for single window applications).
The majority of the time when a single window application is created the application delegate is replaced by a custom AppController anyway which usually wont contain a definition for the applicationOpenUntitledFile method as it is not appropriate for the type of application.
Hopefully any Cocoa experts can confirm if my understanding is correct or if I am barking up the wrong tree.
When you create a document-based application, you get a few things:
A subclass of NSDocument
A new xib file for this document, in addition to MainMenu.xib
A CFBundleDocumentTypes entry in Info.plist, which tells the app about your NSDocument subclass
When your app opens, the shared NSDocumentController will create a new untitled document using the CFBundleDocumentTypes information.
For more information, read The Document-Based Application Project Template and the rest of the document-based applications guide.
I assume your right. If you create a non based document application, add the document types informations in the -Info.plist and set the delegate of NSApplication in the main.m as following
int main(int argc, const char * argv[])
{
[[NSApplication sharedApplication] setDelegate:[NSDocumentController sharedDocumentController]];
[[NSBundle mainBundle] loadNibNamed:#"MainMenu" owner:NSApp topLevelObjects:nil];
[NSApp run];
}
The behaviour seems to be the same as the the default Document-Based Application template.
No, your assumption is not right, look at the implementation of GNUstep version, in the NSApplication's finishLaunching method:
NSDocumentController *sdc;
sdc = [NSDocumentController sharedDocumentController];
if ([[sdc documentClassNames] count] > 0)
{
didAutoreopen = [sdc _reopenAutosavedDocuments];
}
So it create a instance of NSDocumentController automatically.

Xcode & IB - Window Controller Method

I have 2 windows in an xcode project, A and B. A is to capture information, B is to display. I built the windows in IB.
I would like to create a method to control the submit from window A to close window A, and display window B fullscreen.
I am completely new to OBJ C and Cocoa, so Please explain this or provide example code...
If I want to do this, I know I need to create a file from within IB with my A and B to add to my project to add the code, or do I simply add a cocoa file .h and .m to the project. If so, what tells IB that these files correspond to the windows I already created in IB. Once the IBAction is completed I know how to link in IB, but I am at a loss as to how to proceed.
So from what it sounds, you need to declare (in .h):
- (IBAction) closeWindowA:(id)self;
Then tell your application what closeWindowA really does (in. m):
- (IBAction) closeWindowA {
// your code goes here. Look up method(s) for closing the window - don't know them by heart
}
Then, just connect your Button or whatever is triggering the action in Interface builder using the draggable connections. Hope this helps - I also have to recommend 'Cocoa Programming for Mac OSX' by Aaron Hillegas. Helps tremendously in understanding these kinds of things.

Resources