I have a xib file - LoaderView.xib and associated class LoaderView.cs which contains a view for showing loading text. When I try to load it in the main ViewController as -
public override void ViewDidAppear()
{
base.ViewDidAppear();
NSBundle.MainBundle.LoadNibNamed("LoaderView", this, out NSArray arr);
var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));
view.Frame = View.Frame;
View.AddSubview(view);
}
I am getting the System.InvalidCastException in this line -
var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));
And the strange part is I do not get the exception every time. When it works, I am seeing the loading text overlapped with default view - associated with the ViewController.
Can someone point out what is the best way to show Loading, Error and Empty states. Should I have separate ViewControllers for them? Or Can I have separate xib files which I can load/unload from the main View Controller? How to load a view from a xib file?
The problem lies within arr.
In the above images, it can be seen that somehow the method LoadNibNamed
is not returning the top level objects in arr
in the same sequence every time. That's why the code -
var view = Runtime.GetNSObject<LoaderView>(arr.ValueAt(0));
is not able to cast the 0th item of arr
to type LoaderView
every time.
The solution is to traverse the array to find the item of your type - LoaderView
here. For my case - I wrote a static class which has a generic method LoadViewFromNib
which returns a view of type T inheriting from NSView
.
public static class LoadNib
{
static NSArray xibItems;
static nuint index;
public static T LoadViewFromNib<T>(string filename, NSObject owner) where T : NSView
{
NSBundle.MainBundle.LoadNibNamed(filename, owner, out xibItems);
for (nuint i = 0; i < xibItems.Count; i++)
{
NSObject item = xibItems.GetItem<NSObject>(i);
if (item is T)
{
index = i;
break;
}
}
return Runtime.GetNSObject<T>(xibItems.ValueAt(index));
}
}
And as for the overlapping issue, I found out that a subview is transparent unless its background is set explicitly.