NSCollectionView in 10.6/Xcode 3.2 - objective-c

in Xcode 3.1.2 I used to load the nib of the NSCollectionViewItem in my subclass of NSCollectionViewItem like this:
-(id)copyWithZone:(NSZone *)zone
{
id result = [super copyWithZone:zone];
[NSBundle loadNibNamed:#"PersonView" owner:result];
return result;
}
In Xcode 3.2 under 10.6 the same method doesn't yield to an error, but it doesn't load the view in the NSCollectionView either.
Is there something else that needs to be done to make the view show up?
Or is there even a better way of doing this that comes with the change of NSCollectionItem's superclass to NSViewController?
After all, overriding copyWithZone to achieve this standard functionality always seemed like a hack to me. I think one should be able to specify the nib that's supposed to be used in IB, but it seems like Apple doesn't think so.
I did have a look at the example that is available in the documentation, but there the NSCollectionViewItem is instantiated programmatically using initWithNibName, but I would like to create it in the IB.
UPDATE:
I did what kperryua suggested, but now I can't access outlets from the NSCollectionViewItem. Here's what I'm trying to do:
- (void)setRepresentedObject:(id)object {
if (object) {
[labelName setValue:[object name]];
}
}
I binded the label name to the file owner which is my NSCollectionViewItem. That used to work perfectly in 10.5, but now the outlet is not assigned(I checked that with GDB).
image showing the bindings http://img21.imageshack.us/img21/671/picya.png
UPDATE 2:
I also binded the NSCollectionView's itemPrototype to my subclass of NSCollectionViewItem(PersonController).
image showing bindings http://img503.imageshack.us/img503/4672/pic2d.png
Now both the File's Owner of the PersonView.nib and the itemPrototype of the NSCollectionView point to my subclass.
image showing console output http://img340.imageshack.us/img340/6184/pic3.png
As you can see in the screenshot the item are displayed, but the text of the label can't be changed as the outlet labelName isn't accessible.
I also logged the name that I'm trying to set to make sure it isn't 'Name'.
What needs to be done to change the label's value?
Any help would be appreciated.

Yes, Snow Leopard makes this much easier. In IB, click on the NSCollectionViewItem and set the nib name and bundle name (just leave it blank for the main bundle). In your PersonView nib, make the NSCollectionViewItem the File's Owner and connect the -view outlet to a view in that nib. (It looks like you might have this set up like that already in that nib.) Everything else should be automatic, and overriding copyWithZone: shouldn't be necessary.

To sync the property of the representedObject with the Value of an IB Element, you might want to use the Cocoa-bindings. Bind the Value of the TextField to the Model Key Path representedObject.name of the File's Owner in this case.
I had that working with 10.6 Xcode 3.2 but what can't get to work is what you did: Connecting an IB Element to an Outlet of my CollectionViewItem. I have a custom subclass of CollectionViewItem and everything set up as you have. But when running the application it fails stating
[NSTextField copyWithZone:]: unrecognized selector sent to instance 0x210a60
2009-10-19 13:05:18.772 WrapperTest[24122:a0f] An uncaught exception was raised
2009-10-19 13:05:18.774 WrapperTest[24122:a0f] -[NSTextField copyWithZone:]: unrecognized selector sent to instance 0x210a60
2009-10-19 13:05:18.779 WrapperTest[24122:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTextField copyWithZone:]: unrecognized selector sent to instance 0x210a60'
*** Call stack at first throw:
(
0 CoreFoundation 0x977f658a __raiseError + 410
1 libobjc.A.dylib 0x9767ff49 objc_exception_throw + 56
2 CoreFoundation 0x978429db -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x9779e026 ___forwarding___ + 950
4 CoreFoundation 0x9779dbf2 _CF_forwarding_prep_0 + 50
5 CoreFoundation 0x97789a5a -[NSObject(NSObject) copy] + 42
6 AppKit 0x918ce1d7 -[NSViewController setTitle:] + 70
7 AppKit 0x91167dab -[NSNibOutletConnector establishConnection] + 406 ...
I'm not sure why those NSTextFields are missing their copyWithZone since they should implement it
I fixed that, I wasn't aware, that I needed to declare those Outlets as properties of the view, everything including bindings seem to work.

Related

EXC_BAD_ACCESS when closing NSDocument window (ARC enabled)

I'm working on converting a document-based application from Garbage Collection (it ran fine under 10.6) to Automatic Reference Counting (trying to get it to compile and run for 10.12). I'm getting a consistent EXC_BAD_ACCESS when the last window is closed. Nothing is flagged by the static analyser.
I used Instruments to look for Zombies, and indeed there appears to be a release message sent to a deallocated object. Here is the trace:
# Event ∆ RefCt Timestamp Responsible Library/Responsible Caller
173 Release -1 3 00:05.226.677 Foundation __48-[NSFileAccessArbiterProxy removeFilePresenter:]_block_invoke
174 Release -1 2 00:05.226.679 Foundation -[NSFilePresenterXPCMessenger invalidate]
175 Retain +1 3 00:05.226.823 Foundation -[NSBlockOperation initWithBlock:]
176 Retain +1 4 00:05.226.858 AppKit -[NSDocument close]
177 Release -1 3 00:05.227.350 Foundation -[NSFilePresenterXPCMessenger dealloc]
Retain/Release (2) 00:05.227.484 AppKit -[NSDocumentController removeDocument:]
180 Release -1 2 00:05.227.485 AppKit -[NSDocumentController removeDocument:]
Retain/Release (2) 00:05.227.496 AppKit -[NSUIActivityManager addProvider:toUserActivity:withSetter:]
183 Autorelease 00:05.227.499 AppKit -[NSWindowController _windowDidClose]
184 Release -1 1 00:05.228.172 Foundation -[NSAutoreleasePool drain]
185 Release -1 0 00:05.228.184 Foundation -[NSBlockOperation dealloc]
186 Zombie -1 00:05.242.579 AppKit -[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]
The difficult I am having in diagnosing this problem is that I can see the message being sent to the Zombie, but because I do not release any objects (it is all done by ARC), I'm guessing there is an implicit release going on somewhere. But I'm not sure where to look.
When in the debugger, lldb complains of a crash in main.m at:
return NSApplicationMain(argc, (const char **) argv);
Any help would be greatly appreciated. Thank you.
After doing more research, the problem is still unsolved, but I have a clue:
Thank you for your response. Yes, I am at this point assuming it is a memory management issue. Is there way to track down the culprit? It doesn't seem like using Zombies in Instruments is helping: it points to a problem, but does not help me target the problem. That is, the offending line according to Instruments appears to be "-[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed:saveWindows:]"; but I never issued that line. I have made what might be a little progress towards figuring things out.
The structure I am using in the document is:
NSDocumentController: default, not subclassed
NSDocument: subclassed, MyDocument; also the delegate of window
NSWindowController: default, not subclassed
NSWindow: MyDocument.xib, MainMenu.xib
I tried setting the delegate of the open window to nil as follows:
-(void)windowWillClose:(NSNotification *)notification
{
windowOpen = YES;
NSArray *windowControllers = [self windowControllers];
NSWindowController *currentWindowController = [windowControllers firstObject];
NSWindow *windowForCurrentController = [currentWindowController window];
NSDocument *w = [windowForCurrentController delegate];
[windowForCurrentController setDelegate:nil];
}
This causes the same crash.
Then, I thought perhaps the currentWindowController (or the application) was messaging a deallocated window. So I tried adding the line (at the end of the method above):
[currentWindowController setWindow:nil];
This gets rid of the crashes, but introduces new problems (such as when trying to load new files, etc.). But I'm wondering if this is a clue to help solve the overall problem.
The problem was that the app delegate was set to being MyDocument (the NSDocument subclass). The problem was solved by creating a standard AppDelegate class (NSObject, implementing the NSApplicationDelegate protocol), creating a corresponding NSObject in the XIB and setting it to type AppDelegate, and then making AppDelegate the delegate for MyDocument.
I seems that the source of the problem was that the MyDocument object was being deallocated, but it was still the delegate of the NSWindow subclass. The NSWindow then sent a dealloc message to the delegate, but it was already deallocated, causing a crash.
Here is the chain that solved it (long but instructive).

Debugging EXC_BAD_ACCESS in AppKit

I am receiving a EXC_BAD_ACCESS when calling setFrame on NSWindow. Unfortunately the exception occurs in AppKit where I can't debug it, in [NSWindow _setFrameCommon:display:stashSize:] with an invalid address of 0x40dedeadbec0 (the same every time).
The call in my code that causes the exception is in a subclass of NSWindow:
[super setFrame:frameRect display:flag];
Both frameRect and display are valid values, and self is a valid instance of my NSWindow subclass.
How should I go about debugging this error?
You need start debuging with enabling NSZombieEnabled. Fast of all NSWindow was released somewhere by some reasons. For example you have releaseWhenClose flag with YES value.
Error address which you provided seems like a Hexspeak

Core Data: crash when last window is closed

I get invariably this error when I close the last window of my app:
Application Specific Information: objc_msgSend() selector name:
respondsToSelector: objc[42729]: garbage collection is OFF
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0
libobjc.A.dylib 0x00007fff8cc9a150 objc_msgSend_vtable5
+ 16 1 com.apple.AppKit 0x00007fff8fbca814 -[NSApplication supplementalTargetForAction:sender:] + 63 2 com.apple.AppKit 0x00007fff8fab91e4
_objectFromResponderChainWhichRespondsToAction + 155 3 com.apple.AppKit 0x00007fff8fab8feb
_NSTargetForSendAction + 3255 4 com.apple.AppKit 0x00007fff8fab832f -[NSApplication targetForAction:to:from:] + 682 5
com.apple.AppKit 0x00007fff8fab7e00 -[NSMenu
_enableItem:] + 403
I confess that the document nib has two windows. I want the "auxiliary window" to be closed and deallocated when the main window is closed. How should I do? Maybe these errors com from here… I'm using Core Data and ARC.
Regards
I found something which seems to solve the problem. But I don't understand what's happening and I really dislike this.
In IB, the file's owner has a "window" outlet who points to the document window; but there is no #property NSWindow window; in the default code of the NS(Persistent)Document.
I had to make a panel a "child window" of the doc's main window, so I add a #property NSWindow mainWindow. The new "mainWindow" outlet points to the same window as the "window" outlet.
And suddenly no more crash, no more zombie. What happened? I'm baffled.
After reflexion: I have added a pointer to the document window, so the ARC counter never reaches zero. I suppose I had a missing reference somewhere to the _window of the NSDocument, which is now balanced by my outlet.

does -[CALayer drawInContext:] do something?

According to documentation
Default implementation does nothing.
But... I throw exception from drawRect method and i see next callstack
3 EasyWakeup 0x0003a7b6 -[AlarmIntervalView drawRect:] + 71
4 UIKit 0x003f6187 -[UIView(CALayerDelegate) drawLayer:inContext:] + 426
5 QuartzCore 0x011a8b5e -[CALayer drawInContext:] + 143
So as i can understand it means default implementation of -[CALayer drawInContext:] call
delegate method.
Is it correct?
Since i have known swizzling technique i'm not sure anything in objective-c...
You're correct in that CALayer's default drawInContext: does nothing. This is true unless the layer has a delegate and that layer's delegate implements drawLayer:inContext:. So the issue with the documentation is that it should have a little asterisk next to the statement "Default implementation does nothing."
Remember, all views are backed with some kind of CALayer. This layer is automatically setup to have its view set as its delegate. What's not apparent on the surface is that UIView does implement CALayer's delegate drawLayer:inContext:. This is what you're seeing with all those calls on the call stack.
Your instance of AlarmIntervalView automatically has a backing layer, and that backing layer has its delegate set to your AlarmIntervalView instance. Some part of the system calls the backing layer's drawInContext: which checks for a delegate (which it has), sends the delegate respondsToSelector: with drawLayer:inContext: as the argument (which UIView does respond to), and finally actually sends the message drawLayer:inContext:. UIView's implementation of drawLayer:inContext: calls your view's drawRect:.
I'm not really sure why you mention swizzling.
[My response is long, mostly for my benefit. It helps me learn too.]

Accessing NSImageView giving EXC_BAD_ACCESS

I've got a strange problem here.
I have a class that I'll call MainView. In MainView I have one NSImageView, which I'll call imageView. I've hooked this up to an image view through Interface Builder. I've also initialized an instance of MainView in Interface Builder, and have connected an outlet to that instance to another class with an ivar name of mainView. So then, I access the image view like this:
[mainView imageView]
So then, for a test I NSLog'd the imageView and it returned the address of the objet. So far so good.
Here's the problem: now I'm trying to get the origin of that imageView by doing this:
NSPoint point = [[mainView imageView] frame].origin;
This should work, right? I'm getting an EXC_BAD_ACCESS (also got a SIGABRT once) warning here with the error in console of: -[NSImage frame]: unrecognized selector sent to instance 0x1001d5fd0
The strange part is that this always used work just fine, but I changed some ivar names and it seemed to mess up the whole thing. I almost know for certain it's not a hookup issue with IB because I get a memory address when I log the object. Any ideas?
The error message
-[NSImage frame]: unrecognized selector sent to instance 0x1001d5fd0
means that imageView is pointing to an NSImage object instead of an NSImageView object. It looks like somewhere in your code you’re reassigning the imageView outlet, making it point to an NSImage instance.