I am experience the exact same issue as identified in this submission: MvvmCross/Xamarin "This class is not key value coding-compliant for the key"
The issue stems from trying to use MVVMCross databinding in an IOS CollectionView
That article was closed and marked as a duplicate but I don't see it as such. The article that it links to as the solution offers workarounds when using XCode as a development environment. My scenario and the scenario described in the issue linked above are in using Visual Studio on Windows with Xamarin to build with. With Visual Studio, the XIB editor and wiring up outlets is done differently.
I have been trying to get past this problem for a few days now and haven't figured anything out. I'm hoping that someone who has seen this in Windows Visual Studio has a solution that they can share.
(I apologize, I am new so I couldn't do this as a comment in the original post).
The Stack trace of the error is below
Foundation.MonoTouchException: Objective-C exception thrown.
Name: NSUnknownKeyException Reason: [<NSObject 0x7c4eb9a0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.
Native stack trace:
0 CoreFoundation 0x00928494 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x08fa3e02 objc_exception_throw + 50
2 CoreFoundation 0x009280b1 -[NSException raise] + 17
3 Foundation 0x014477f8 -[NSObject(NSKeyValueCoding) setValue:forUndefinedKey:] + 282
4 Foundation 0x013a1e6a _NSSetUsingKeyValueSetter + 115
5 Foundation 0x013a1def -[NSObject(NSKeyValueCoding) setValue:forKey:] + 295
6 Foundation 0x013d654b -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 384
7 UIKit 0x03bc8a62 -[UIRuntimeOutletConnection connect] + 132
8 libobjc.A.dylib 0x08fb800c -[NSObject performSelector:] + 62
9 CoreFoundation 0x00851131 -[NSArray makeObjectsPerformSelector:] + 273
10 UIKit 0x03bc70fc -[UINib instantiateWithOwner:options:] + 2102
11 UIKit 0x041205ec -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 750
12 UIKit 0x04120f35 -[UICollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:] + 194
13 ??? 0x1b909f9c 0x0 + 462462876
14 ??? 0x1be1b820 0x0 + 467777568
15 ??? 0x1be1b633 0x0 + 467777075
16 ??? 0x1be1adf6 0x0 + 467774966
17 ??? 0x1be1b08d 0x0 + 467775629
18 CompanionForSpotifyiOS 0x001bb2a1 mono_jit_runtime_invoke + 705
19 CompanionForSpotifyiOS 0x00276fef mono_runtime_invoke + 127
20 CompanionForSpotifyiOS 0x0034bb77 xamarin_trampoline + 5559
21 UIKit 0x0410d5ee -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:] + 448
22 UIKit 0x0410d2ff -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 65
23 UIKit 0x04111761 -[UICollectionView _updateVisibleCellsNow:] + 6023
24 UIKit 0x041167df -[UICollectionView layoutSubviews] + 254
25 UIKit 0x038543d4 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 810
26 libobjc.A.dylib 0x08fb8059 -[NSObject performSelector:withObject:] + 70
27 QuartzCore 0x0b5d8096 -[CALayer layoutSublayers] + 144
28 QuartzCore 0x0b5cb8b6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 388
29 QuartzCore 0x0b5cb71a _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
30 QuartzCore 0x0b5bdee7 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 317
31 QuartzCore 0x0b5f2847 _ZN2CA11Transaction6commitEv + 561
32 QuartzCore 0x0b5f3108 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
33 CoreFoundation 0x0083a75e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
34 CoreFoundation 0x0083a6be __CFRunLoopDoObservers + 398
The ViewModel code is here
public partial class AlbumCell : MvxCollectionViewCell
{
public static readonly UINib Nib = UINib.FromName("AlbumCell", NSBundle.MainBundle);
public static readonly NSString Key = new NSString("AlbumCell");
public AlbumCell(IntPtr handle) : base(string.Empty, handle)
{
this.DelayBind(() =>
{
var set = this.CreateBindingSet<AlbumCell, Album>();
set.Bind(artistNameLabel).To(album => album.ArtistName);
set.Apply();
});
}
public static AlbumCell Create()
{
return (AlbumCell)Nib.Instantiate(null, null)[0];
}
}
And this is the generated component of the view model that has the outlets [Register ("AlbumCell")] partial class AlbumCell { [Outlet] [GeneratedCode ("iOS Designer", "1.0")] UILabel artistNameLabel { get; set; }
void ReleaseDesignerOutlets ()
{
if (artistNameLabel != null) {
artistNameLabel.Dispose ();
artistNameLabel = null;
}
}
}
Finally, this is the XIB which is very basic - it just has one label on it
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AlbumCell">
<connections>
<outlet property="view" destination="2" id="RRd-Eg-VrN"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="2">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" fixedFrame="YES" text="Label" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="5">
<rect key="frame" x="279" y="95" width="42" height="21"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</objects>
</document>
The code where I create instanced of the cell objects from the parent ViewController is below
public partial class NewReleasesView : MvxCollectionViewController
{
public NewReleasesView()
: base(new UIKit.UICollectionViewFlowLayout()
{
ItemSize = new CoreGraphics.CGSize(250,200),
ScrollDirection = UICollectionViewScrollDirection.Vertical
})
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
CollectionView.RegisterNibForCell(AlbumCell.Nib, AlbumCell.Key);
var source = new MvxCollectionViewSource(CollectionView, AlbumCell.Key);
CollectionView.Source = source;
var set = this.CreateBindingSet<NewReleasesView, NewReleasesViewModel>();
set.Bind(source).To(vm => vm.NewReleases);
set.Apply();
CollectionView.ReloadData();
var viewModel = this.ViewModel as IMvxViewModel;
viewModel.Start();
}
}
It looks like Visual Studio was putting the outlets in the wrong location. See below where i typed "Outlet was here". That is where the UI Label was generated. I manually removed it then went into the XIB Editor in visual studio and re-added the outlet name in the designer. At that point, it put it in it's right place where i labeled "When it should have been here".
I'm not sure what caused the behavior in the first place, but this work around definitely did the trick. Thanks to all who assisted me.
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AlbumCell">
<connections>
***OUTLET WAS HERE***
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1" customClass="AlbumCell">
<rect key="frame" x="0.0" y="0.0" width="250" height="250"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" customColorSpace="calibratedWhite" colorSpace="calibratedWhite" white="0" alpha="1"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Label" lineBreakMode="tailTruncation" minimumFontSize="10" id="4" translatesAutoresizingMaskIntoConstraints="NO" fixedFrame="YES" customClass="UILabel">
<rect key="frame" x="53" y="20" width="177" height="21"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" colorSpace="calibratedWhite" white="1" alpha="1"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="600" height="600"/>
<connections>
***WHEN IT SHOULD HAVE BEEN HERE***
<outlet property="artistname" destination="4" id="name-outlet-4"/>
</connections>
</view>
</objects>