Binding an NSColorWell to an NSTextField - cocoa

I'm attempting to bind an NSColorWell to the NSTextField value and implementing an NSFormatter subclass. The NSColorWell is bound to an ivar in the app delegate which is also bound to the NSTextField. There is an NSFormatter that converts the [NSColorWell color] to a descriptive string.
When the UI focus is on the NSTextField, it doesn't update at all; but when the focus is on another NSTextField, it does.
I understand KVO/KVC, bindings etc. but wonder if there are any 'gotchas' in IB that I'm missing.

Try a bidirectional value transformer instead. For one advantage, you may find it easier to implement than a formatter.

Related

Possible to use NSView subclass in NSTableView?

I have an NSView subclass that I'd like to use in an NSTableView. Normally of course I'd use a NSTableCellView subclass but this view will be used elsewhere.
Possible?
There's no requirement that the cell view used for a view-based table view be an NSTableCellView or subclass. It's perfectly OK to use an instance of some other view object. For example, an NSTextField works out of the box.
Your table view delegate's -tableView:viewForTableColumn:row: method can configure the view as appropriate for the row. Or, your view can implement an objectValue property (with -setObjectValue: setter). In this case, the table view will forward whatever object value your data source returns from its -tableView:objectValueForTableColumn:row: method to your view's objectValue property.
Also, if your view class has textField or imageView properties (like NSTableCellView does), then those will be treated specially in certain cases. For example, the text field will be the accessibility string for the cell.
Basically, all of the behaviors of NSTableCellView are generalizable. It's not that the class is treated particularly specially by the framework. It's that it provides the appropriate properties and methods and any view with those same properties and methods could replicate its behavior.
Change your NSView subclass to inherit from NSTableCellView instead of NSView, since NSTableCellView also inherits from NSView too.

How to tell which NSTextField was edited?

My NSDocument subclass adopts NSTextFieldDelegate. The document window contains several NSTextField instances (all setup as outlets of the document class). When the user edits a text field, I want my document to be notified. But all the methods in the NSTextFieldDelegate protocol are inherited from NSTextViewDelegate and hence pass NSText* instances in their parameters, NOT NSTextField instances. The same applies to the notification:
- (void) controlTextDidChange:(NSNotification*) notification
So, How do I find out which of the many NSTextField instances is being edited?
NOTE
I need to register undos properly, using the document's undo manager. I tried implementing
- (NSUndoManager *)undoManagerForTextView:(NSTextView *)aTextView
but this seems to only work with NSTextViews, NOT NSTextFields.
You can get a reference to your NSTextField as [notification object]. From the documentation for NSControlTextDidChangeNotification:
The notification object is the NSControl object posting the
notification.
The actual control subclass will be your NSTextField.

Redraw custom NSTextField when bindings value changes?

I have a custom NSTextField sub-class with a custom drawRect: implementation.
The text field is part of a view inside a table cell. I programmatically bind the fontBold property of the text field.
The problem is that I have to recalculate a few things when the fontBold binding changes, but I can't figure out how to get notified when that happens.
I tried adding an observer, but that is not called. There does not seem to be a setFontBold:(BOOL) method that I could overwrite in NSTextField.
I think I figured it out:
There really is no fontBold property. I think what happens under the hood is that the binding is transformed by a value transformer into an NSFont object and what actually changes is the font attribute of NSTextField (I confirmed that setFont: is called when the fontBold binding changes). Phew, 4 hours of my life gone.

Catching TextDidChange or DidEndEditing of an NSTextView instead of an NSTextField

It seems that NSTextView does not have the notification DidEndEditing and TextDidChange (which both exist for an NSTextField). Is there any similar functionality I can get out of the NSTextView? If not is there no way to know when the user has edited the text of the NsTextView?
Don't forget about superclasses. An NSTextView is a kind of NSText, and every NSText can have a delegate. It also, of course, posts matching notifications.

setString vs. setStringValue in Cocoa

I tried to use the method setString to change the text in a textfield and it didn't work. Then I changed it to setStringValue and it worked. So what is setString used for?
NSTextField does not have a setString: method. NSTextField is a type of NSControl, and NSControl has a setStringValue: method.
NSText and its more famous subclass NSTextView have a setString: method. #John Boker is correct that the field editor is an NSText, but you still can't send setString: to an NSTextField, even in edit mode. You'd need to get the field editor from the window and then call setString: on that (not that you really should do that).
While it is confusing to newcomers, there is a good rationale behind the different methods. NSControl has a "value", and that value can take different types (setDoubleValue:, setObjectValue:, etc.) This allows me to set the value as a double, but then retrieve in as a string. For the broad range of possible controls, this makes good sense and is very flexible. NSText is not a control; note how it doesn't have setAction: or setTarget: either. Its purpose is to display and edit (attributed) strings. When you call string, you are actually getting the real backing text storage, not just the value of the object in string form (as stringValue does for NSControl).
That said, when you say "it didn't work," I hope you mean that you got a compiler warning about this that told you that NSTextField may not respond to setString:. If you're ignoring compiler warnings, then you're going to have a lot of problems in ObjC.
from: http://macosx.com/forums/software-programming-web-scripting/43905-_outlet-setstring-testing-selector-not-recognized.html#5
setString: is for NSText, which is the
class used for an NSTextField's field
editor while it is being edited, and
for the NSText subclass NSTextView
which can display and edit styled text
as in TextEdit.
So the way i take it is you can only use setString: when the field is in an edit mode, i think.
Going a bit more generically (in contrast to my comment on Rob's answer):
Objects respond to messages. You can send a message to any object that responds to that message; you can't send a message to any object that doesn't respond to it.
Instances of NSText and its subclass NSTextView respond to setString:, so you can send NSText objects and NSTextView objects setString: messages.
Instances of NSControl and its subclasses, including NSTextField, respond to setStringValue:, so you can send NSControl objects, NSTextField objects, and other control objects setStringValue: messages.
See Rob's answer and my comment on it for why these two specific branches of the class hierarchy have these seemingly-similar-but-differently-named methods.

Resources