Alexandstein Alexandstein - 5 months ago 16
Swift Question

NSTextFields using bindings not updating after initialization

I am importing data from JSON to be used as the models for some items in a CollectionView, and it seems that they are being initialized, and with the correct number of elements. But for some reason the

representedObject
(aliased as
morpheme
below) is returning
nil
initially. Hence the placeholder if nil values being the ones showing up.

If you click the items, I have it set up to show up in the log the name of the item clicked, and it works fine, and doesn't return the debugging defaults. So I'm guessing there is a concurrency issue going on.

For more details, this are items being manually prototyped because XCode 7 still hasn't fixed the segue bug with collection item prototypes.

Here is a screenshot I hopefully managed to get it all the important info in:

enter image description here

Here is the cell's controller/delagating class code in detail:

///Acts as view controller for the items of the morpheme collection
public class MorphemeCell: NSCollectionViewItem, NSTextViewDelegate{

var backgroundColor = NSColor.clearColor()

var morphemeLabel: String{
get{
return morpheme?.morphemeDisplayName ?? "Morpheme"
}
}

var allomorphsLabel: String{
get{
return (morpheme?.allomorphsAsString ?? "Allomorphs")
}
}

///The morpheme data contained in the cell
public var morpheme : Morpheme?{
get{
return representedObject as? Morpheme
}
set{
representedObject = newValue
}
}

required public init?(coder: NSCoder) {
super.init(coder: coder)
}

///Detects clicks on each item
public override func mouseUp(theEvent: NSEvent) {
Swift.print("Clicked on " + morphemeLabel)
backgroundColor = NSColor.blueColor()
}
}


Not sure if this is needed, but just in case here is the main window's ViewController doing some setup/loading functionality.

enter image description here

The loading code itself:

///Loads morpheme data into memory and then into the collection view
func loadMorphemeData(){
//Open morphemes.json and begin parsing
let morphemeDataPath = "morphemes"
if let file = NSBundle.mainBundle().URLForResource(morphemeDataPath, withExtension: "json")
{
let data = NSData(contentsOfURL: file)
let json = JSON(data:data!)

//Create Morpheme objects passing in JSON elements
for morphemeElement in json{
let toAdd = Morpheme(JSONElement: morphemeElement)
fullMorphemesList.append(toAdd)
}
///TODO Use full range or filters in final product
let morphemesToLoad = fullMorphemesList[0...100]
collectionView.content.appendContentsOf(Array(morphemesToLoad) as [AnyObject])
}
else
{
print("Resource Failure")
}


So, recap: It seems that I either need to delay the collectionView's setup, or find out how to update the Labels once the data is in.
Thanks very much for any help! I'm very new to the Cocoa framework so it's been a doozy.

Answer

Take different route: bind your label to self.morpheme.morphemeDisplayName. Then set "Null Placeholder" text to be "Morpheme" (in that right panel see the list of text edits below binding settings). Finally make property morphemeDisplayName dynamic:

 dynamic var morphemeDisplayName: String? 

Obviously, you dont need morphemeLabel property inside cell anymore.

morpheme property of cell must be dynamic as well, or if there is setter-based property, you can call:

 set {
 willChangeValueForKey("morpheme") 
 <whatever variable> = newValue 
 didChangeValueForKey("morpheme") 
 }

Edit by original poster:

Also, in order to avoid binding synchrony issues, it turns out using viewWillAppear() instead of viewDidLoad() was causing issues with data loading and "freezing the labels".