In Xcode Document App: Why would init method of MyDocument be called twice? - cocoa

I followed Chapter 8 of Hillegass to implement the RaiseMan application there.
Then I decided to follow the same process to implement the code for an exercise in a Cocoa programming class that I am taking, but I got the following very cryptic error message after building and running.
Cannot create BOOL from object <_NSControllerObjectProxy: 0x100460e30> of class _NSControllerObjectProxy
I have no idea what this error message means. Doing a Google search brought up some hits, but their remedies seemed to be to do things that I was already doing.
I stared at all the connections and assignments that I made in Interface Builder and nothing looks obviously wrong.
So I went into the debugger and set a breakpoint inside the init method of the MyDocument class and it is being called twice. How could that happen? What should I be looking for that would make the init method be called twice? The stack trace shows that init is called by system functions that we did not write ourselves.
For comparison, I went back to the project that follows Chapter 8 of Hillegass and set a breakpoint inside the init method of the MyDocument class, and it is being called once ( which is what one would expect ).

Cannot create BOOL from object <_NSControllerObjectProxy: 0x100460e30> of class _NSControllerObjectProxy
It appears you've bound a BOOL property to a controller, and not specified a model key path. Most probably, you bound one of the Cocoa view classes' built-in bindings, such as enabled or editable.
Look through your nib for views whose enabled or editable you've bound, and make sure they are all bound to the correct model key path.

I just ran into this myself. And then I remembered seeing something odd before, whose significance hadn't struck me at the time. Which is that in my XIB file, there was a "My Document" object, in addition to the "File's Owner" object (which is what actually represents the document in the XIB file). I have no idea how it got there, but I deleted it in IB, recompiled, and presto, [MyDocument init] only gets called once now.

Related

Assertion error when using NSCollectionView with QLPreviewView

I am using an NSCollectionView where each NSCollectionViewItem uses a QLPreviewView to get a rendering of a file's content.
(This is an attempt at a file browser for images and other previewable files.)
Initially, this works fine.
However, once collection items are getting re-used, I get an assertion error (both in 10.13 and 10.14):
[QL] Assertion failure (unreachable code) - [… MyPreviewView activated … doc:[QLPreviewDocument …]] is already activated
Apparently, before I can re-use a NSCollectionViewItem, the previously used QLPreviewItem needs to be set to inactive state somehow. How do I do that?
I've tried to send the close message to the QLPreviewView instance but that doesn't make a difference.
I also do not get a dealloc call on my QLPreviewView subclass, which suggests that the object is still referenced by something else, possibly the QLPreviewDocument, which then gets confused about the change of state.
I have made a demo project available on github: https://github.com/tempelmann/NSCollectionViewWithQLPreview
To test: Run it, then scroll down. When reaching items 50 to 60, the assertion will be triggered.
The fix is to set QLPrewiewView's shouldCloseWithWindow property to NO.
This, I suspect, tells the controller behind the scenes not to attach itself to higher level structures, i.e. tells it to remain self-sufficient.
So, adding this line to the code that sets up a new MyPrewiewView object in the sample code's ViewController.m file prevents the error:
qlView.shouldCloseWithWindow = NO;

How to create multiple windows using "command + n" in non document based application

Is there a way to create/enable having multiple windows using "command + n" in a non document based application? I want to have unlimited instance of that window (not actually unlimited, but might be 6-7 instances) using command + n
Or I have to create a document based app and port all my code in new project template is the only solution?
I can see the menu button for "New" is disabled right now.
A few ways to do this.
First connect the New menu item to an IBAction method.
Name the method whatever makes sense to you.
Next, you will want to add some kind of property to your controller ( app delegate for simplicity ) that is basically a window stack only storing a reference to each window or window controller. NSMutableArray should do nicely.
Now you can do the next part a few ways, but I would recommend creating an NSWindowController subclass with a nib/xib (especially if these windows will have the same basic things in them).
Do what you want in the nib file.
Now in your IBAction method, create a new instance of your window controller class, add it to your mutable array. Tell it to load its window.
You only have to decide if the controller should be removed from the stack and set to nil if its window is closed.
Many ways to handle that, and up to your design to know what is correct.
Try this :-
NSWindowController *yourWindow=[[[[yourWindowController alloc]init]retain]autorelease];
[yourWindow loadWindow];

Selectively displaying Installerpane of an installerplugin at runtime

I have written an installerplugin to show a custom pane in the pkg installer. I want to display the pane only during first install and hide it when upgrading. I know how to find out if the package has already been installed or not but I am not able to figure out the logic of showing/hiding the installerpane based on a runtime decision.
One method I could think of is that the installerplugin contains an Installersection outlet called parentSection. And installersection class has a function shouldload whose return value decides whether the section should be loaded or not. And this article mentions that the installersection methods can be overloaded. But I am unable to think of a way to overload the functions as parentSection is just an object inside the installerpane class.
Even though it's been several months since sanmukh asked this question, I figured I would post the answer since I figured out how to do this.
The solution is indeed to subclass InstallerSection and override the shouldLoad method. To use it, you have to edit your plug-in's Info.plist file and change the entry for "NSPrincipalClass" (or "Principal Class" as it appears in Xcode 4) to be your new InstallerSection derived class. Afterwards when your package loads, the new shouldLoad method will be called, allowing you to programmatically decide whether the installer pane should be visible.

Duplicate of first entry in navigation bar in custom Visual Studio Language Service

I'm implementing a Visual Studio Language Service for a custom scripting language used internally at my company, and I've run into an issue with the navigation bar implemented as a subclass of TypeAndMemberDropdownBars. The subclass is created by my LanguageService subclass' LanguageService.CreateDropDownHelper method.
In the OnSynchronizeDropdowns method I'm iterating through the types defined in the file and adding DropDownMembers to the passed-in array to fill out the navigation bar. The issue I'm seeing is that the first item in the array is being duplicated and placed at the end of the listing by code that I don't have access to. This extra item does not behave correctly when selected (nothing happens), but doesn't seem to cause any other issues; the rest of the items in the list work fine. Additionally, this only seems to happen for the type dropdown box - the members dropdown box does not display this behavior.
I'm hoping someone else has seen and resolved this issue and could provide some assistance. Thanks!
Turns out this was caused by me calling LanguageService.SynchronizeDropdowns from my LanguageService.ParseSource method, which was being called on a background thread. I've fixed the problem by setting a flag when ParseSource does a Check parse, and then implementing a check for that flag in my LanguageService.OnIdle function that will call SynchronizeDropdowns. It's now working as expected!
A better solution is to implement the LanguageService.OnParseComplete callback, and call SynchronizeDropdowns from there. OnParseComplete is always called from the main thread, so this prevents any synchronization issues from coming up, and also keeps you from having to keep track of whether or not you need to call SynchronizeDropdowns().

NSDocument Subclass not closed by NSWindowController?

Okay, I'm fairly new to Cocoa and Objective-C, and to OOP in general.
As background, I'm working on an extensible editor that stores the user's documents in a package. This of course required some "fun" to get around some issues with NSFileWrapper (i.e. a somewhat sneaky writing and loading process to avoid making NSFileWrappers for every single document within the bundle). The solution I arrived at was to essentially treat my NSDocument subclass as just a shell -- use it to make the folder for the bundle, and then pass off writing the actual content of the document to other methods.
Unfortunately, at some point I seem to have completely screwed the pooch. I don't know how this happened, but closing the document window no longer releases the document. The document object doesn't seem to receive a "close" message -- or any related messages -- even though the window closes successfully.
The end result is that if I start my app, create a new document, save it, then close it, and try to reopen it, the document window never appears. With some creative subclassing and NSLogging, I managed to figure out that the document object was still in memory, and still attached to the NSDocumentController instance, and so trying to open the document never got past the NSDocumentController's "hmm, currently have that one open" check.
I did have an NSWindowController and NSDocumentController instance, but I've purged them from my project completely. I've overridden nearly every method for NSDocument trying to find out where the issue is. So far as I know, my Interface Builder bindings are all correct -- "Close" in the main menu is attached to performClose: of the First Responder, etc, and I've tried with fresh unsullied MainMenu and Document xibs as well.
I thought that it might be something strange with my bundle writing code, so I basically deleted it all and started from scratch, but that didn't seem to work. I took out my -init method overrides, and that didn't help either. I don't have the source of any simple document apps here, so I didn't try the next logical step (to substitute known-working code for mine in the readFromUrl and writeToUrl methods).
I've had this problem for about sixteen hours of uninterrupted troubleshooting now, and needless to say, I'm at the end of my rope. If I can't figure it out, I guess I'm going to try the project from scratch with a lot more code and intensity based around the bundle-document mess.
Hard to tell without code but I would suggest sending:
closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:
... to the document controller and then looking at the controller as it is passed to the delegate to see how its state changes.
If the controller closes the document when you send the explicit message then your problem is with the binding to the window.

Resources