Cocoa view for plugin editor: Xcode 4.3 issue?

Hey there

What’s the correct way for using a native Cocoa view in a JUCE plugin editor through NSViewComponent? I couldn’t find anything beyond the class reference, so I tried poking around. I’m getting some compiler errors after linking with Cocoa.framework and attempting to do the following in my plugin editor’s constructor:

#include “MZPluginProcessor.h”
#include “MZPluginEditor.h”

#import <Cocoa/Cocoa.h>

MZ2synthAudioProcessorEditor::MZ2synthAudioProcessorEditor (MZ2synthAudioProcessor* ownerFilter)
: AudioProcessorEditor (ownerFilter)
{
// This is where our plugin’s editor size is set.
setSize (400, 300);

NSViewComponent *vc = new NSViewComponent();
vc->setView([[NSViewController alloc] initWithNibName:@"MZSynthView" bundle:nil]);

}

Have attached a screenshot of the errors that pop up after doing the above from Finder.h, MacMemory.h, Components.h. The MemoryBlock and Component look like some kind of class naming clash issue. Is this an issue with Xcode 4.3 or me?

Matias, the unashamed noob

Just include all your Cocoa headers before anu juce headers and it should be ok.

Thanks for the quick response – that indeed helped! Now remember experiencing the same thing with OpenCV in a Cocoa application some time ago.

When #import <Cocoa/Cocoa.h> is before any juce headers, I got just one ‘Reference to “MemoryBlock” is ambiguous’ error, and this time around Xcode actually helpfully pointed at the responsible line (as an aside there’s some kind of a more generic 4.3 issue where it fails to show the error details often) in the plugin processor source code file, which is .cpp, not .mm:

void getStateInformation (MemoryBlock& destData);

The following change made it compile:

void getStateInformation (juce::MemoryBlock& destData);

To be clear, there’s no #import <Cocoa/Cocoa.h> anywhere in the project except for the plugin editor implementation file, as the first line. I wonder if I’m still doing something wrong, or was that change that to be expected?

Yeah, that’s to be expected. The old carbon headers define a symbol called MemoryBlock without a namespace.

Ok, makes sense indeed. Now that I have your attention, next question: how do I actually get the Cocoa view showing? Doing the following leads to the host crashing:

NSViewComponent *vc = new NSViewComponent();
MZSynthViewController *viewC = [[MZSynthViewController alloc] initWithNibName:@"MZSynthView" bundle:nil];
vc->setView([viewC view]);

It also shows some detected leaks before it goes. NSViewComponent leaks, but so do audio buffers, heap blocks, MIDI keyboard states, etc. Adding a [viewC release]; after the vc->setView(…) line has no effect. I’ve checked in IB that the view outlet of the synth view controller is connected, so it’s not due to vc->setView being given a nil argument.

Any pointers at relatively noob friendly example code would probably get me going too. Thanks very much for your help!

Maybe have a look at the code for the web browser?

Ah I see, actually, some more debug logging shows this issue:

14/04/2012 20:09:49.257 Audio Plugin Player: unable to find nib named: MZSynthView in bundle path: (null)

The Nib is however bundled with the component, just checked. Weeeird…

Thanks again, the web browser example was indeed informative. Just to finish this off in case some other noob is reading: the issue with the bundle was that the default bundle (bundle:nil) refers to the hosting application’s bundle. Had to get the bundle with +bundleWithIdentifier:@"<the plugin’s bundle>". Beside respond to the window resizing callback after the view hierarchy was set up, that was all that was needed to get the Cocoa view rendering fine.