What is causing the compile error: Illegal NSTableView data source? - xcode

After some 'cleaning' of a working app, the main window appears as designed in the MainWindow.xib.
I deleted a MainWindowViewController object in IB. (was beneath Font Manager)
MainWindow.xib has it's Custom class set to MainWindowViewController
The table uses Content Mode - View Based
The two required methods ARE included in that implementation file
included in header file
Table view connection has been made to File's Owner
EDIT: Does the full error message give a clue? Why the NSApplication?
*** Illegal NSTableView data source (<NSApplication: 0x100607ad0>).
What am I missing? What should I check to resolve?
Image included to help visualize.
EDIT 2: (New info)
I deleted the data source & delegate connection from the table view and the error disappeared. The same IB designed window opens with an empty table view.

My 'project' is more complicated than the documentation covers. How to add a Window Controller to the Cocoa/Core Data template and utilize this controller is not easily found.
The most pronounced symptom was that the code in the intended controller was not being executed. The 2 required delegate methods were present. awakeFromNib wasn't being called either.
After more research, it appears the 'missing link' is the (previously deleted) NSObject set to the custom class of MainWindowViewController or MainWindowController in the nib file. I'm still looking for why this needs to be or why connecting to the File's Owner doesn't make the connection.
On the one hand, we can set the File's Owner to the custom class (MainWindow)ViewController or (Main)WindowController and connect the contained views to File's Owner. This doesn't work as I expected.
On the other hand, (apparently correct) we can add an NSObject to the MainMenu.xib file, set it's custom class to the (MainWindow)ViewController or (Main)WindowController and then connect outlets to the subviews to this object. The step of adding this object in IB is the only way I could find of connecting the window to the controller.

Related

Quartz Composer "Binding Controls to Input Ports" in Xcode 4.x

I am trying to follow "Binding Controls to Input Ports" of Quartz Composer Programming Guide.
The document says :
5.Click “Bind to” and then choose Patch Controller in the “Bind to” popup menu.
6.Enter patch in the Controller Key text field.
7.Enter text.value in the Model Key Path text field.
In my project of Xcode (4.2 &) 4.3, the Controller Key text field is disabled. The Model Key Path text field requires an object of QCPatch class, which I don't think I have a clue.
Should I install Xcode 3.x and handle this & convert to 4.x? Any advice ?
I am experiencing the same issues, however via the kineme forums I have found a work around:
using the Object Controller instead of the Qc Patch Controller:
make a new cocoa project...
add quartz framework via buid phases tab and import the framework to your project either in the pre compile header, or app delegate...
add qc view to your xib and load your composition
add object controller to your xib...
change object controllers class to "QCView" without quotes.
control drag your object controller to your qc view and select "content"
add a slider and bind its value to your object controller and set its model key path to "patch.Text.value" without quotes.....
see this for the full thread on this topic.
in xib file choose the QCView
Attibutes Inspector -> check "Forwards All Events"
hope it helps

How to connect a menu item to a custom action defined in the NSApplication delegate across nib files?

In my Cocoa app I have two NIB/XIB files that I need to connect:
MainMenu.xib: contains a custom object for the NSApplication delegate object and connects it to the proper outlet in the NSApplication placeholder.
ContextMenu.xib: sets up an NSMenu; one entry is supposed to open the preferences dialog
My custom app delegate defines an IBAction to bring up the Preferences window for my app.
How can I connect the NSMenuItem (second NIB) for showing the preferences to the action defined in the application delegate (first NIB)?
The Docs say this is supposed to be easy, but they fail to mention how exactly to do this in Interface Builder:
If the menu item refers to an application-level command, you can
implement that command directly in the application delegate or just
have the delegate forward the message to the appropriate object
elsewhere in your application.
I somehow need to access the app delegate in the second NIB, tell Interface Builder that it is of my custom class (so it knows about the custom IBAction), and connect it to the action of the menu item.
Thanks for any pointers!
If the other objects are in the responder chain, then you can just hook the action up to the first responder.
Notice the "if", though.
As Maurice Kelly mentions, your App Delegate is already part of the responder chain, so you can use that: Define a custom action on the First Responder (in Interface Builder) and a corresponding action on your App Delegate. If you have many actions that could clutter up the App Delegate, though, so you might want to use this architecture only for simple apps.
For bindings in the second NIB, application delegate bindings can be accessed by binding to Application with a model key path starting with delegate. ie delegate.managedObjectContext
A warning: Do not create an app delegate object in the second NIB. If you do, you will end up with a second app delegate instance with a second, separate managedObjectContext. The NIB creates another app delegate object. This is terrible.
In the loading of MainMenu.xib, [NSApplication sharedApplication] gets its delegate set to the delegate object instantiated in MainMenu.xib. If you create a delegate object in another NIB, you will have a delegate object that doesn't match [NSApp delegate]. (And you will smash your head into the wall trying to discover why the view of the context doesn't update)
Your second NIB will have a File's Owner which you should set to a class that is instantiated by your application. Within this class you can create a reference to the App Delegate which can be filled in when the class is being instantiated (e.g. using setAppDelegate:self if you are creating it from within the delegate).
Create an IBAction in this class which simply passes the action on to the App Delegate:
- (IBAction) passItOnAction:(id)sender {
[appDelegate openPreferences:sender];
}
I got the same problem, and solved it like this:
I created only one menu (MainMenu.xib). Since menu items for which the first responder does not provide any action are automatically greyed out, the items that are meant for the Document window will be greyed out when the Prefs window is activated.
I created a PrefsWin.xib for the definition of the prefs window. The File's Owner of that xib is a class named PrefsWinController, which inherits from NSWindowController.
The actions in MainMenu.xib simply connect to the First Responder rather than the delegate. If your instance of <NSApplicationDelegate> is an instance of NSResponder, the delegate will automatically act as the last responder in the chain. (I don't know where this might be documented, but it certainly works in my project.)

View outlet not available to File's Owner

I was getting the following message upon creating a new view controller. Everything was compiling a-okay in Xcode without errors, but the app was immediately quitting upon loading the new view from a RootViewController.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "HomeView" nib but the view outlet was not set.'
To resolve this, I tried connecting the File's Owner to the view, but the view outlet wasn't even available to the File's owner.
Moved from question section, per #Tim Post's suggestion.
Discovery:
I finally realized that when I added this View XIB, the File's Owner had been set to NSObject instead of HomeViewController (my newly-created view controller). Once I set the class identity in the indentity inspector, the view outlet was then ready to be connected to the view.
The app now loads and the new view loads perfectly. Just sharing for the benefit of the SO community.
Conclusion:
When creating a new View XIB, make sure to set the class identity to the desired view controller in the indentity inspector (Cmd+4). It may be set to NSObject by default.
The view outlet should then be available.

should I be creating my objects manually or with InterfaceBuilder?

I am relatively new to Cocoa/Xcode and am not sure if I am structuring my application in the most "correct" way possible. I have a number of objects which are active the while time that the application is running. Should I be creating these objects manually or with Interface Builder?
The type of objects I am referring to:
"downloader" which is responsible for downloading files to disk
user interface updater which is responsible for updating the user interface to show the results of the downloaded file
Should I create these objects in IB and set up the connections between them with code?
It's really a matter of personal preference.
In my opinion IB only really good at laying out views, so I tend to only use IB for my view and my view controller, and I create everything else in code in the view controller's viewDidLoad or init method.
In your example, connecting the "downloader" object directly to the interface seems like an MVC violation, so I would keep the downloader out of my xib.
The "interface updater" would be connected tightly to the interface, so it could be in the nib, although unless I had a good reason not to I would probably just put that code into my view controller class.
If you are creating things in code, note that viewDidLoad/viewDidUnload can potentially be called a number of times, as the os loads and un-loads your views when they are not visible to save memory. So only put transient objects there... things that must exist for the life of the view controller should be created in the init/dealloc methods. Part of why I like to do most of my object creation in code, is the finer level of control you have over memory.
I typically build as much as I can in IB, and then switch to code when I run into the limitations of IB. It sounds like you should be able to create the UI you described in interface builder.

Loading data into a Cocoa view before the application loads

I want to load some data from mysql into my cocoa application view before the application starts.
I am sure that this should happen in the controller so that it can send the required data to the view.
I am looking for a method or common technique that is used for this sort of thing.
Many Thanks
Sounds like you're looking for the awakeFromNib function.
http://www.cocoadev.com/index.pl?AwakeFromNib
Cocoa gives you many places to perform tasks before and after objects are loaded from a nib, but it's important to read the documentation carefully to make sure things are happening in the order you expect. Usually I use the following strategy when I'm working on a Cocoa application:
Where appropriate I implement the
+(void)initialize method, which is called before any instances of a class are created. I'll probably set the app's default preferences here, for example.
In my application controller (app delegate), I implement the applicationDidFinishLaunching: delegate method to load my data file. If this works okay, I then create the window controller(s) and display any windows I want to show at launch.
In the window/view controllers, I override windowDidLoad: or loadView to perform tasks involving objects loaded from a nib. If I need to create any instance variables that don't involve the nib, I also override the init method and do that there.
If I need to do anything in my view objects after they're loaded from a nib, I'll override awakeFromNib.
You can use the - applicationDidFinishLaunching: or - applicationWillFinishLaunching: delegate messages, by implementing one of them in your application delegate/controller, and do whatever initialization you want there.

Resources