File's owner thinking it is superclass - objective-c

Something very strange is going on with my interface builder. So I created an NSWindowController subclass in Xcode, with the create XIB option enabled. I started coding, and I successfully connected to file's owner.
But, when I run my app, I get the error :
Failed to connect (workspaceControl) outlet from (NSWindowController) to (NSSegmentedControl): missing setter or instance variable
Failed to connect (workspaceField) outlet from (NSWindowController) to (NSTextField): missing setter or instance variable
Could not connect action, target class NSWindowController does not respond to -changeNumberOfWorkspaces:
I don't know why this error is showing up as I have my code set up right:
And the File's owner is set to the right class (AddController):
So why does it try to connect my views to NSWindowController instead of my subclass?
EDIT:
Where I actually use the AddController in code:
AppDelegate.h
AppDelegate.m
It's in appdelegate because it is a menubar app. (In case anyone was wondering)

Because the actual object that is instantiated in your running program is an NSWindowController, not an AddController. You've shown us that AddController is properly declared, and you've shown us that your nib's File's Owner is set to AddController; that's great, and is why you don't get a compile-time warning or error about things being wired up incorrectly. But you haven't shown us where the controller object actually gets instantiated; and examining that would presumably reveal that it hasn't been changed to AddController. So at runtime you've got an NSWindowController, in violation of what you promised to IB would be the case; and so you get runtime errors.

Related

Outlet failed error in NSWindowController

I have simple non document, cocoa app in which I have added new NSWindowController, named Login and I created a .xib file for it. I want this window to be opened first when the app is started.
I have changed the main interface section to my project from MainMenu to Login, and when I run the app, indeed the new login window is started first.
However...none of the outlets work. I get error message for each outlet in my login window that looks like this:
Failed to connect (userNameTextField) outlet from (NSApplication) to (NSTextField): missing setter or instance variable
What I am doing wrong?
I encountered the same error message. The solution in my case may not be directly applicable but perhaps it will help in some way.
I created a TestWindow view controller with associated xib and set up some referencing outlets. I then programmatically created the window with NSWindowController* window = [[NSWindowController alloc] initWithWindowNibName:#"TestWindow"]; and got the same sort of error message. I finally realized that I should write [TestWindow alloc] instead of [NSWindowController alloc] and that fixed everything. It seems so obvious in retrospect but I'm still getting used to what Interface Builder does and doesn't do for you auto-magically.
Your error message says it can't connect from (NSApplication) instead of (YourAppClassName), so I suspect the class that you define your outlets in isn't actually being instantiated.

What are the correct connections for App Delegate and Application

Unannounced, the 2 notices in the image below were discovered while searching for why -applicationShouldTerminate: is not being called in AppDelegate.m on quit (Cmd+Q). It worked some time ago.
Hovering over the two yellow triangles reveals:
NSObject does not have an outlet named delegate.
The action 'terminate:' is not defined on 'NSObject'.
Xcode is not showing errors or warnings and the app builds.
-applicationShouldTerminateAfterLastWindowClosed: IS called within AppDelegate.m when the red dot of the window is clicked.
My experience with Cocoa is thin (learning). I've compared the connections for File's Owner, Application and App Delegate in 2 other projects, and think a missing window outlet might be the cause. The notices above point to something else.
I would like to make sure the connections are correct as a first step. How do I repair this?
Edit: Add image of Main Window Controller connections
Edit 2: Add image of File's Owner connections
In the main NIB of an application, the two placeholders, File's Owner and Application, both end up referring to the same object. That object is the application object, the sole instance of NSApplication or a custom subclass of it. The Application placeholder is always holding the place of the application object because that's its purpose. The File's Owner placeholder is holding the place of whatever object is specified as the NIB's owner when it is loaded at run time. When Cocoa loads the main NIB at application startup, it specifies the application object as the owner. For other NIBs, File's Owner will likely be some other object.
However, Interface Builder doesn't know that a given NIB is the main one. So, it treats those two placeholders independently.
I don't know why Interface Builder has taken to setting the class of the Application placeholder to NSObject. It should really be NSApplication. That's why Interface Builder doesn't realize that the application object has a delegate outlet and an action method -terminate:.
As it happens, the class of File's Owner is properly set to NSApplication.
So, there are two ways to fix this:
Set the class of the Application placeholder to NSApplication or, in the rare case that you're using a subclass, that subclass.
Disconnect those connection from the Application placeholder and connect them to File's Owner instead. This is the way that the standard project templates do it.
For any given main NIB, you should probably standardize on using one or the other but not both. That is, one or the other should have no connections. That way you avoid conflicting or redundant connections.

cocoa could not connect action

I've been fiddling with Objective-C + Cocoa and writing a fairly simple Cocoa application. Then I encountered a runtime error that has no effect on my program execution:
Could not connect the action textField: to target of class BarController
I'm experimenting with pulling some of the windows out of MainMenu.xib and loading them with separate controllers and xib files.
In one window within a new xib I've created a Text Field and linked it to an IBOutlet NSTextField (textField) in a new NSWindowController subclass. It works and I am able to use textField to update the contents of the Text Field.
I am curious why I am getting the above runtime error and I'm hoping that understanding it will clear up some of the magic around the UI construction process.
Not much magic with plain IBOutlets, really - the fun starts when using Bindings or actions sent to some yet unknown target via First Responder and the responder chain :-)
Regarding your error:
Sounds like you've connected an outlet to a target that doesn't exist in your target class?
You might have established a connection to a property in File Owner (or some other proxy object) at some point where the owner's class was e.g. MyAppDelegate.
Then you've moved the window (or other object containing the outlet) to some other .xib and now the owner's class is MyWindowController that doesn't have a property of the same name you've connected your outlet to - and voila, the runtime won't be able to establish the connection for your outlet at runtime.
Just double-check your outlets in the Interface Editor, there's probably already some kind of warning message displayed next to outlets that look fishy.
Delete or reassign them and you're done.

Could not connect the action : to target of class NSApplication

I come from a Cocoa touch background and there's one point I'm stuck on, I'm trying to create a ViewController from scratch and connect objects in my xib to actions in my new ViewController. I changed the file's owner to my ViewController and added outlets, and the compiler seems to be happy with what I've done.
But when I run my application, the connections seem to fail with: 'Could not connect the action start: to target of class NSApplication,' but where is this NSApplication reference hiding? To the best of my knowledge my ViewController has a class of NSViewController.
ViewController : NSViewController
I changed the file's owner to my ViewController and added outlets, and the compiler seems to be happy with what I've done.
Sure, the compiler won't care -- this is a run-time error. It sounds like you're working in your MainMenu.xib file. That file is loaded by the application object. Even though you changed the type of File's Owner in the .xib, the object that's loading the .xib is still the application.
You'll probably want to create a separate .xib file for your view controller to load. You change the type of File's Owner in that file to you view controller class! hook things up to File's Owner, and it should work fine since your view controller really will be the object that's loading the file.

How to hookup a MainWindow.xib to an empty project

Beginning with XCode 4.2, when you create an empty project using XCode 4.2, a MainWindow.xib is no longer created and hooked up for you. I've found an article that describes how to do this and I've done it and it works, but if this process has taught me anything, it has shown me that I have no idea how main(), AppDelegate and the MainWindow.xib exist together.
http://www.trappers.tk/site/2011/06/16/mainwindow-xib/
Why is MainWindow.xib class updated to UIApplication?
Why is an object placed on the xib, and then AppDelegate class is selected for the class?
Why is the delegate outlet of the File Owner connected the AppDelegate object?
Why is the the window outlet of the AppDelegate to the Window?
why does - (BOOL) application:didFinishLaunchingWithOptions: need to be commented out.
I've researched around but, I'm still not 100% sure how everything is loaded up once the application starts, and why this is setup is needed just to have a MainWindow. I have a feeling though that I should probably get all these concepts down to continue to advance in iOS development.
Why is MainWindow.xib class updated to UIApplication?
At the lowest level, nib files are loaded with the method -[UINib instantiateWithOwner:options:]. The File's Owner in a nib file is a placeholder. In Xcode, it isn't a specific object yet. It will resolve to an actual object when the nib file is loaded. Its purpose is to relate, via outlets and actions, objects inside of the nib with the object that loaded the nib. The object passed as the "instantiateWithOwner:" parameter of that UINib method is what the File's Owner placeholder in Interface Builder will resolve to.
UIApplication loads the nib file specified in the info.plist and passes 'self' for the owner parameter when loading the nib file.
By setting the class name, you're just hinting to the tools so that they can suggest the set of actions and outlets you're allowed to establish.
Why is an object placed on the xib, and then AppDelegate class is selected for the class?
When you place the generic object in the xib and change its class to 'AppDelegate' you're telling Xcode to instantiate an instance of 'AppDelegate' when the file is loaded.
Why is the delegate outlet of the File Owner connected the AppDelegate object?
UIApplication has a 'delegate' that it delegates responsibility to and notifies when interesting events occur. When you make this connection, you're setting the delegate property of the application to be the instance that you specified above. From that point on, this instance will receive the delegate messages from UIApplication, like -application:didFinishLaunchingWithOptions:.
Why is the the window outlet of the AppDelegate to the Window?
Outlets are a way to refer to objects inside of a xib. They cause properties or instance variables to be set to refer to the object pointed to by the outlet. When you make this outlet, you're making it so that the app delegate instance you created above has a way to refer to the window that's also created when the xib is loaded.
why does - (BOOL) application:didFinishLaunchingWithOptions: need to be commented out.
It represents the code-focused way to do some of the same things that are happening in the xib, and if they were both present, they would be overwriting each other.
The object placed on the XIB file is the AppDelegate because it delegates all connections in the Interface Builder, meaning if you write a method that when a button is clicked it displays text, that method would be connected to either the App Delegate or the File's Owner, preferably the delegate. The File's Owner, since it is the UIApplication, connects to the delegate because it assigns that certain object to be the App Delegate. Sorry that I couldn't answer the rest of your questions, they didn't really make sense.
Hope this helps