Interface builder bindings only working in one direction? - objective-c

I've got an XIB window that I'm working with in Interface Builder. It has an NSScroller and 4 popups. The controller class has a float and 4 ints.
I bound the scroller to the float and the pupups to the ints, binding the value of the scroller and the selected index of the popups.
When I move the scroller, or change the popup selection, the ints and float change exactly as expected.
However, when I change the ints and float in the code (To initialize them for example) the UI elements don't change.
All of the ints and float are properties, properly synthesized.
Am I missing something really dumb?

There could be one of several things wrong.
First, by "binding" do you mean that you are using Cocoa bindings? If so, do you have an Object Controller in the NIB file that arbitrates between your UI elements and your data holding code? That is generally required.
When you say "when I change the ints and floats in code", how are you changing them? If you are setting the instance variables directly, you are bypassing any change monitoring mechanisms.
Post some code.

Related

Don't Understand Apple's takeFloatValueFrom: Example

I'm no iOS guru but I know enough to build apps. I know and understand the patterns, UIKit, and Objective-C. I'm now learning Mac Development and this little bit of "Cocoa Bindings Programming Topics" has me stumped:
Take as an example a very simple application in which the values in a text field and a slider are kept synchronized. Consider first an implementation that does not use bindings. The text field and slider are connected directly to each other using target-action, where each is the other’s target and the action is takeFloatValueFrom: as shown in Figure 2. (If you do not understand this, you should read Getting Started With Cocoa.)
This example illustrates the dynamism of the Cocoa environment—the values of two user interface objects are kept synchronized without writing any code, even without compiling.
(Emphasis mine)
Huh? Wouldn't you need to create outlets? And an IBAction that goes something like
- (IBAction)takeFloatValueFrom:(id)sender {
self.slider.floatValue = [sender floatValue];
self.textField.floatValue = [sender floatValue];
}
Is this something Mac-specific? How do you actually hook up two controls with target-action in a XIB without writing any code and have their values locked?
When you're setting up an interface in Interface Builder, you can specify that it sends a message to another object whenever it changes in some way. What this example is showing is that you can hook these two objects up such that whenever the slider changes, it sends the message takeFloatValueFrom: to the text field, and vice-versa.
takeFloatValueFrom: is a method defined on NSControl, and both a text field and a slider are subclasses of NSControl.

NSTextField doubleValue localization confusion

I am from germany. So I have a little problem with localization and the property doubleValue of the class NSTextField. Comma and points are different from the U.S.
double a = self.heightTextField.doubleValue;
If I have a "11,11" in my textfield I only get the integer part unless I write "11.11" with a point. So I guess I have to convert this value according to my current location. No big deal. NSNumberFormatter will do that.
But if I assign a value to the property it all works fine automatically. "11.11" gets converted into "11,11" on the NSTextField without me doing anything.
self.heightTextField.doubleValue = 11.11;
Why is that so?
Why is the the value from the controller converted automatically when send to the view but when I read a value from the view I have to convert it myself? Can I get automatic conversion both ways?
The number handling in NSTextField is from the old, old days, and is being gently deprecated in favor of NSFormatters, so it’s not surprising it’s kind of spotty.
As #Michael says, if you want to handle different localizations of you should add an NSNumberFormatter to your field. You can just drag one off of the Interface Builder’s classes palette and onto the field in question.

How do we implement selectionRectsForRange: from UITextInput Protocol?

How do we implement selectionRectsForRange: from UITextInput Protocol ?
Has anybody figured out this one?
Is it just very dependent upon specific use-case needs? Or is there something in the frameworks that will call this method?
To silence the compiler it is of course appropriate to stub out the method, but will returning nil or an empty NSArray cause any harm?
According to session 220 at WWDC12 this method was added to support subclassing of UITextView where the implementation renders its own text. Sadly their sample code from that session isn't available, would love to peek at it to see if I've missed anything in my implementation.
It's fairly similar to how you'd implement -firstRectForRange: except you'd return all rects which covers the current selection.
Furthermore you'd have to subclass UITextSelectionRect (it's an abstract class like UITextPosition/UITextRange) which you'd return an array of from this method. Make sure to calculate the containsStart and containsEnd properties correctly and only return YES for one of each once across all the selection rects you return. These properties are used by UITextView to decide on where to place the selection resize "paddles".
Returning an empty array (or nil I suppose) would indicate that UITextView shouldn't draw any selection rects for the current selection.

Fundamental Drag And Drop In iOS

I've been considering an app now that implements a drag and drop sort of idiom from maybe a side pane or a drawer, etc. what I can't wrap my head around are how to keep reference to the objects I drop. I mean; it would be easy if it was just drop the object, then let it alone, but I want more manipulation after the fact.
My brain just cannot wrap around the concept of creating objects out of thin air to place on the 'canvas', or having preset objects (which I imagine would be limited, cumbersome and awkward) already on the canvas that would then just be activated and manipulated easily, seeing as the references to them are created before the fact (my apologies for the loose term 'reference', I mean something like selecting the object and having it's unique properties recognized or displayed).
There must be something I'm missing. So, I wonder how one might go about implementing drag and drop with interface and manipulation with the dropped object after the fact or maybe sample code or a link to a git or svn repo? (something like how MIT's scratch, or Xcode's interface builder might work).
For clarity's sake, I know how to go about fiddling with drag and drop thanks to DragKit, but not about editing 'properties' on the object dropped onto the 'canvas', and I would like there to be a near infinite amount of objects that can be dropped on the canvas, yet a set amount of items in the drawer/side view.
If I'm understanding your question correctly, you want to be able to drag objects onto a canvas and then manipulate their properties individually. For instance, you'd drag square views onto the screen and then increase its size or change its color.
In order to do something like that, I would have a NSMutableArray or an NSMutableSet that would hold all of the on canvas objects. Then when any interaction comes, you could either dynamically generate gesture recognizers if the objects are UIViews or a subclass. Then in the target of the gesture recognizer you would use the recognizer.view property.
Or you would have to check which object on the canvas you were currently manipulating. That would be done by iterating through the array and seeing which object equals the one you are touching.
Is there anything that you are trying to do but is not working? Have you written any code in attempt to do this?

IKImageBrowserView appears to not bind properly

my question relates to Interface Builder and an IKImageBrowserView not implementing bindings as I would expect.
I have a fairly long key path to get to an NSArrayController, the contents of which I want to display in the IKImageBrowserView.
This is the key path I am binding an NSTextField's Display Pattern binding to:
currentOrder.imagesArray.unvalidatedImages.arrangedObjects.#count of the AppDelegate.
This works fine and gives me the number of unvalidated items in the array of images belonging to the current order, which is what it is supposed to.
When I attempt to bind the following key path to the IKImageBrowserView's content: currentOrder.imagesArray.unvalidatedImages.arrangedObjects of the AppDelegate, Interface Builder gives no error but instead acts as if I hadn't entered anything. When I click back to the inspector, the bindings key path is blank again.
It does however log the following to the Console:
Ignoring exception related to working with bindings: NSUnknownKeyException, [<NSCustomObject> addObserver:<IKImageBrowserView ...> forKeyPath:#"currentOrder.imagesArray.unvalidatedImages.arrangedObjects" ...] was sent to an object that is not KVC-compliant for the "currentOrder" property.
My AppDelegate implements currentOrder as an #property retained and all sub-keys are also #properties. I can be sure that these properties are KVC-okay because the NSTextField above is able to read changes without a problem. Interestingly enough the IKImageBrowserView's selectionIndexes is able to bind to ...unvalidatedImages.selectionIndexes, it's only the content that can't.
I have implemented a workaround whereby I have placed an NSArrayController in my nib file and bound the Content Array to ...arrangedObjects then bound the IKImageBrowserView to the array controller but would be very happy to have a neater solution, or at least to know whether I am doing anything wrong.
Thank you!
Did you try implementing the methods of <IKImageBrowserDataSource> in your app delegate, and using the _dataSource connection instead of a binding? That works for me, and is how the Apple tutorial has you do it.
You basically only need to implement – numberOfItemsInImageBrowser: and – imageBrowser:itemAtIndex: to provide the data, which isn't too bad. The slightly trickier part is to implement an <IKImageBrowserItem> class to wrap your data, but even that doesn't require massive effort. The tutorial linked above should help a lot.