NSCollectionView not updating subviews on data change - objective-c

I have set up an NSCollectionView through Interface Builder. My prototype view contains a progress indicator and a text field. I have set up the bindings so that my "task" object maintains the value of the progress indicator and the text field value.
It all works okay when I add new objects to the collection (via [NSCollectionView newItemForRepresentedObject:] which I add to my array controller). The initial value of the progress indicator and the text field get set appropriately. However, when the values change, it is not reflected in the prototype view. The values always keep their initial value.
I have tried adding a pointer to the prototype view in the "task" object and trying to force an update via [NSView setNeedsDisplay:TRUE] but to no avail. I have subclassed the prototype view and gave it an outlet to the progress indicator so that I could inspect it to see its value at runtime and strangely enough, even though the view is created successfully, the progress indicator is not! Quite contradictory to the fact that it does in fact display and maintain an initial value!
Is there any way I can, using the current setup, propagate the changes to the view?
Thanks in advance.

Your bindings setup should be sufficient.
What is your progress indicator bound to? Make sure it is sending out KVO notifications when the progress value is updated.

Related

Auto Layout manipulating object created in IB through code

I asked a more general question in a previous thread about converting to Auto Layout, but as I'm doing the conversion I've run into something very specific.
I have a base class VC that handles getting text fields and views out of the way when the keyboard pops up. It also does the same with date pickers and picker views. So if the VC has a date picker, then in IB a date picker is created, and it's Y value in the frame is set to be just off the bounds of the main view. There is an IBOutlet that it is connected to in the base class, and then in the code [self showDatePicker] is called, and the base class does everything else. Works great.
Enter Auto Layout. Even though constraints are generated at runtime for the date picker, since I don't create any, it still seems to work by manipulating the frame, i.e. the picker still animates up and down the screen when it is called or dismissed.
In trying to convert that to Auto Layout, I added a new constraint in code which binds the top of the view to the Top Layout Guide. This works fine, except for the error messages in the debugger that a constraint has to be broken, since one already exists, (created at runtime) for this.
I'd like to avoid having to manually create the constraints on the picker, and then bind one to a property, but it seems the only way around that is to go through the list of constraints on the main view, find the specific one for the top binding of the picker, and then manipulate that. But I don't see a convenient way to find specific constraint, especially one generated at runtime.
So, any thoughts on this? Should I just add the constraints on the picker and attach the top one to a property? Leaving it as it is doesn't seem like a good option, as this is the first time I've seen adjusting the frame work with constraints...

ArrayController's CoreData selection binding not refreshed across multiple NIB files

I've a hard time getting my Cocoa application to work as expected. It consists of a toolbar in the main.nib and a custom view in a details.nib file. Now I want the user to select an entry in a NSPopupButton in the toolbar and the content of the custom view should be changed accordingly.
To achive this I've added an ArrayController to my main.nib, showing the following configuration:
Furthermore the Managed Object Context is bound to the Model Key Path delegate.managedObjectContext (it is no document based application).
With this configuration the NSPopupButton works just fine and if I add a Label to the toolbar (also in the main.nib) and bind it's value to the selection (Controller Key), name (Key Value Path) the content is refreshed whenever I change the selection.
The Bindings of the NSPopupButton look like shown in the following screenshot:
So in my details.nib I tried the following to achieve the same effect. I've added an ArrayController, whichs Managed Object Context is also bound to the Model Key Path delegate.managedObjectContext. Also the configuration is exactly the same as shown in the above pictures. I've then added a label and bound it's value to the selection (Controller Key), name (Key Value Path) of this ArrayController.
The problem is that the Label only displays the the initial selection after the application did launched correctly. Afterwards, when I change the selection of my NSPopupButton, the label does not change accordingly.
What are my options to get the ArrayController working accross multiple NIB files?
BTW: I've tried to follow this blog post to get it working but it seems I'm missing something here.
Update:
If I replace the Label in the details.nib by a NSTextField and change the text of it, the changes are reflected in the related NSPopupButton entry. So I guess I made something right, but the main problem remains: I can only edit the entry which was loaded during application startup. Switching to another NSPopupButton entry does not change the text in the NSTextField.
Update 2:
I've created a small sample project with exactly the same configuration and uploaded it on GitHub. So feel free to check it out or create a pull request with a solution approach.
It seems you're missing the fact that, when you create the second array controller on the Details.xib it has no relation to the array controller on the MainMenu.xib. They are two separate instances.
When you change the selection on the PopUp the only array controller affected is the one on MainMenu.xib.
You have several options here:
When you create your DetailViewController pass a reference to the array controller on the Controller and bind to that (don't create a new one on the details.xib)
Just use simple KVO to observe the selection on Controller, and programatically change your label value.
Just use simple KVO to observe the selection on Controller and update the array controller on the DetailsViewController to keep them in sync.
your solution here...
As long as you understand what's going on I'm sure you'll find the best solution to your original problem.

Who calls commitEditingStyle:forRowAtIndexPath?

I've got a custom UITableViewCell that allows a user to input text when in edit mode. I've noticed that on stock UITableViewCells, when I swipe left, then hit the Delete button, it's table view receives the commitEditingStyle:forRowAtIndexPath message. I'm curious where this message is coming from. As far as I can tell, individual cells don't have a reference to the table view they belong to. If I want my custom cell to send this message, how would I go about doing that? I've thought about using the superview of the cell, but it seems like there's got to be an easier way.
This method gets called automatically (if you implement the data source protocol) before adding any row or column.
If you want to know to which table view a cell is belonging, use the superview method.

Changing visibility of NSPopUpButton's items based on keypress

I've got an application here that needs to read in a bunch of data from an external file and display it as a NSPopUpButton in a Cocoa user interface. The catch here is that the data that is being read in needs to have a flag that states if it is considered "hidden" or not.
If the data is hidden, it needs to be added to the NSPopUpButton as an NSMenuItem, but the hidden flag needs to be set to YES so it does not normally appear in the NSPopUpButton menu. If the user holds down a "magic key" on their keyboard (usually ALT, in this case) then those hidden objects need to be unhidden. If the user lets go of the ALT key, then they need to be automatically re-hidden, except for the one that may have been selected -- which would become hidden if another NSMenuItem were chosen.
I'm kind of having a heck of a time figuring this out, actually.
I was wondering if there is a straight forward way of doing this using NSArrayController and an NSPopUpButton, but thus far I have not been able to find anything resembling a solution -- not when it comes to managing the hidden property of the NSMenuItem objects.
Does anyone know how this can be achieved using Cocoa Bindings?
You can wire the popup to an array controller and alter the filter predicate. From an MVC design standpoint, you wouldn't use an attribute like "hidden", which is a view characteristic, but maybe "advanced". Normally, set a filter predicate on your array controller to "advanced = no". Then when the user holds your preferred modifier, remove the predicate. The popup will update automatically. The array controller should be bound to an array property on another object (in your data model). The popup should be bound to arrangedObjects on the array controller.

How to show progress of download in a custom UITableViewCell with ASIHTTPRequest?

I'm trying to implement a list language packages that can be downloaded by selecting a custom UITableViewCell that contains a UIProgressBar. For each language package I want to show the download progress. I get this done by setting this delegate setDownloadProgressDelegate:.
Everything works great except when the UIProgressBar is moved out of the visible area. This makes sense because the delegates progress bar is removed. What can I do to stop the app from crashing and how can I display the progress bar if it returns to the visible area?
Hier is a picture to see what it looks like right now.
Thx
I suppose you could use a class of your own (or even the view controller) as progress delegate. In your view controller you could hold an array of references to all progress bars currently in use. You would create one progress bar per download and hold it in the array (thus the object would not be destroyed). Whenever a cell is being created you now have to check your array for the corresponding progress bar object instead of creating a new one. Whenever a download is done and the progress bar is no longer needed, you remove it from the array.
Beware of possible multithreading issues and if necessary (e.g. if your notifications could arrive in another thread than the main thread) use performSelectorOnMainThread: to update the progress bar array and the progress bars within.