Xcode hanging, runs out of memory when using Bindings and IB - cocoa

I have a core data model with two entities, for the sake of this post I will call them Category and Items, Category is the parent entity with a one-to-many relationship to Items.
In IB I have a NSTreeController and NSOutlineView that manages the Category entity, this works great.
I also have an ArrayController with Mode set to Entity, Entity Name set to Items, Content Set bindings set to Tree Controller with Controller Key of "selection" and Model Key Path set to the relationship.
I have tested all this works by selecting Categories in the outline view and outputting how many Items are available inside the array controller when I change selection from the tree controller using the following code:
SWIFT:
#IBOutlet var itemsArrayController: NSArrayController!
#IBAction func logResult(sender: AnyObject) {
println("Items Array has \(itemsArrayController.content?.count) records")
// Print first item to console
var anItem : Items! = itemsArrayController.content?.objectAtIndex(0) as Items
if let something : Items = anItem? {
println(something.name)
}
}
Now I want to hook up a Table View to the Array Controller that will list all the Items of the selected Category.
So If I bind Table View Cell's Value to Items Array Controller.arrangedObjects.name and click RUN xcode starts compiling and just doesnt proceed past 50%. Activity Monitor->Memory shows "ibtooid" with 5GB of memory after awhile before the entire system locks up and I have to hard reset my mac. Even if I click stop in Xcode the ibtooid continues to eat memory, The only way to stop from a hard reset is to kill that process,.
Any help would be much appreciated.
Thanks
Xcode Version 6.1 (6A1046a)

Fixed it by changing the table to Cell based rather than View Based. Will file a bug with Apple.

Related

Xcode: Collection view not displaying properly

I was working on app that would take some input from the user and put them into a collection view. The data goes to the database and retrieves successfully into a dictionary movies, but while displaying the collection view, it shows doesn't show the third item, but shows the second item twice. After re-running the app, the problem gets fixed. How do I fix this without having to re-run my app every time?
movieCollectionView is my UICollectionView, and MovieCollectionViewCell is my Cocoa Touch Class file for the collection view.
Fix for the issue - Add following call inside refreshBtn(_ sender: Any) function.
productCollectionView.reloadData()
Other observation - You shouldn't need this line -
productCollectionView.collectionViewLayout = UICollectionViewFlowLayout()

How to reuse WKInterfaceTable in WatchKit

I chose page-based layout for my WatchKit app. Each page shows a table. I want to keep the layout of the table exactly the same across all pages. I will be feeding filtered data to each page at run time, so essentially pages will be identical, except the data will be different.
One way to achieve this is to manually create InterfaceController instance for each page in InterfaceBuilder, then populate with GUI elements and connect the outlets. The problem here is whenever I want to change something (say, move a label or add a button), I will have to apply that change consistently to every page.
Moreover, for each page I have to connect the outlets to table row controller, essentially repeating myself over and over again. Here's an illustration:
Is there a way to reuse a table?
I considered inheritance, but the documentation tells me not to subclass WKInterfaceTable. This also rules out creating a table programmatically.
You should create a single interface controller with the table and various row types. Then you want to create an architecture very similar to my answer here. You'll only have a single PageOneInterfaceController which should be named TableInterfaceController in this example with TableInterfaceIdentifier as the identifier. Then you would do the following:
MainInterfaceController.swift
func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
let context1 = "context 1 - for you to fill out"
let context2 = "context 2 - for you to fill out"
let context3 = "context 3 - for you to fill out"
WKInterfaceController.reloadRootControllersWithNames(
["TableInterfaceIdentifier", "TableInterfaceIdentifier", "TableInterfaceIdentifier"],
contexts: [context1, context2, context3]
)
}
This will reload the page set using the same interface controller that displays all the data in the respective context.
To accomplish this, provide the same WKInterfaceController in reloadRootControllersWithNames:contexts: multiple times, but provide a different context to each one.

Sharing NSArrayController Between Nibs

I have an Core Data-based iTunes-like app I'm building that has an NSTableView in the main window and allows the user to select items in the table view and perform a "get info", like in iTunes. Currently I'm working on the single-item get info window, which displays when the user selects a single item in the main window (which is in MainMenu.xib) and pressed Cmd-I. This brings up the single-item get info window (in SingleItemGetInfo.xib).
The table view in the main window is populated via bindings to an NSArrayController. If I put an NSArrayController into the SingleItemGetInfo.xib file, I understand that's going to be a different instance of NSArrayController.
So, what's the proper way to bind the fields in the single item get info window to the selection the user has made in the main window's table view?
MainMenu.xib's Array Controller bindings:
Managed Object Context: AppDelegate.self.managedObjectContext
MainMenu.xib's Table View bindings:
Content: Array Controller.arrangedObjects
Selection Indexes: Array Controller.selectionIndexes
Sort Descriptors: Array Controller.sortDescriptors
This will work mostly the same way it does when the master and detail views are in the same window. The primary difference is that you need to bind the selection of the array controller in the detail xib to the selection of the master array controller.
It depends on how you have your app organized as to how you accomplish this. If both views are run by the same object then you can just make the master array controller an outlet connected to the controller (#property IBOutlet NSArrayController *masterArrayController;). Then in the detail xib you can bind the selection of the detail array controller to the selection of the master array controller.
If each view has its own controller you might also consider just passing the managed object from the master view to the detail view. Then you can bind to each of the attributes of the managed object in your xib file (i.e. bind to File's Owner self.detailObject.fullName). If you pass a reference I think all of the changes will go right back into the managed object context.

How to get the stringValue of a Text Field Cell inside a Table View after editing the cell?

I have a standard Table View with the default settings inside my main nib. I use an Array Controller and Bindings for dealing with the data that the table view should show to the users. I already achieved that the "add" button inserts the new row and sets the first column to editing mode so the users can type their text immediately. My problem is i can't detect when the editing is over and i should save the new values. I couldn't find any delegate method and/or any notification for this purpose. I searched the internet and i couldn't find anything useful. I'm not even sure that i'm doing it right, i didn't add any specific thing, i just use the standard double click editing that the table view offers for each cell.
Any help is much appreciated.
Thanks in advance!
If you have everything hooked up with bindings, you shouldn't need to save the data until you exit the program. When the array controller's add: method is called, the new record is added to the controller's arranged objects, and the array holding your data is also updated. So, you only need to save the array when your app closes.
However, if you wish to save the data after every edit, you can detect the end of the editing with the delegate method controlTextDidEndEditing:. You will get a notification after each column is finished editing (make sure to make the class where you implement this method the delegate of the table view).

Get index of a view inside a NSCollectionView?

I've developed an app for Mac OS X Lion using its new view-based NSTableView, but as I want to port the whole app to Snow Leopard I'm trying to figure out the best way to emulate such a tableview. So far I've created a NSCollectionView and everything is fine, except for the fact that I can't get the index of the view from which a button click event is triggered.
In Lion I have the following function:
- (IBAction)buttonClick:(id)sender
so I can get the index of the view inside the tableview using a method (I can't remember its name) like
- (NSInteger)rowForView:(NSView *)aView
with aView being the sender's superview, but I couldn't find something similar for the collection view ... The only "useful" method seems to be
- (NSCollectionViewItem *)itemAtIndex:(NSUInteger)index
(or something like this), but this can't help me as it returns a NSCollectionViewItem and I can't even access it knowing only the corresponding view!
Within buttonClick, try this code:
id collectionViewItem = [sender superview];
NSInteger index = [[collectionView subviews] indexOfObject:collectionViewItem];
return index;
Hope this helps :)
Geesh! Both of those approaches have issues. I can see how the first on may work, but note that the "collectionViewItem" is actually the view, NOT the collectionViewItem, which is a view controller.
The second way will not work, unless you subclass the button and put in a back link to the collectionViewItem. Otherwise, your view does not know what collectionViewItem controls it. You should use a selector binding to the collectionViewItem's representedObject instead, to get the action to the correct object in your array.
How about something like:
id obj = [collectonViewItem representedObject];
NSInteger index = [[collectionView contents] indexOfObject:obj];
As I suggested here: How to handle a button click from NSCollectionView
I would do it like this (because the button you want to press should be coupled with the corresponding model, therefore the represented object):
Add a method to the model of your collectionViewItem (e.g. buttonClicked)
Bind the Button Target to Collection View Item
While binding set model key path to: representedObject
While binding set selectorname to: methodname you chose earlier (e.g. buttonClicked)
Add protocol to your model, if you must tell delegate or establish observer-pattern
use NSArrayController for binding to NSCollectionView,
use collectonViewItem.representedObject to get a Custom Model defined by yourself.
save and get index in your custom model.
That's works for me.

Resources