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?
Something like this should work
for (int i = 0; i < a.Count; ++i) { NSObject item = a.GetItem<NSObject> (i); if (item is LoaderView) Stuff (); }
I would consider reading the "Adding and Removing Views from a Hierarchy" section in
in particular note "Note: For performance reasons, Cocoa does not enforce clipping among sibling views or guarantee correct invalidation and drawing behavior when sibling views overlap. If you want a view to be drawn in front of another view, you should make the front view a subview (or descendant) of the rear view."
If you want overlapping views, they need to have a parent/child hierarchy, else the behavior is undefined by Apple.
Answers
Maybe you have a race condition? Does LoadNibNamed return sometimes before item is in memory?
If you want your Window's view to change based upon the loaded controller, you'll likely have to remove the other views from the tree (call RemoveFromSuperview on the view) so you don't see overlap (you have two sets of view in your window tree).
If you want just text however, you can just skip having 3 view hierarchies and just do something like:
@ChrisHamons Pardon me, but before WHAT item is in memory?
I believe the problem lies within arr. I checked its value after setting breakpoint


a. When it works -
b. When it does not and I get an
InvalidCastException
Why is the array not holding the values in the same sequence every time?
I don't want just text. What I want is to show various states - Loading, Empty, Error (which will also have a retry button) but I don't know if having them in different xib file is a good idea or should I have separate View Controllers for them. Can't call
RemoveFromSuperView
fromView
because that is the superview (Tried it and I am getting a blank view instead of overlapped text). The app is a menu bar app and hence it does not have any Window/WindowController but only ViewController.Thanks.
Looking at the API, ignore my previous comment on race conditions. I was wondering if there was some race condition between loading the nib and surfacing it to managed land. However, since we're just looking at the out NSArray, it should be synchronous.
It appears Cocoa is not returning a stable array, as you noted the order is reversed in some cases. Maybe they are doing some multithreaded loading? In any case, you need to walk the array looking for your type, not assuming it is item zero. I do not know the reason why, as that's all implemented in Apple's Cocoa libraries.
Different xib / in one storyboard with view controllers / generated from code for the various views is a matter of opinion. Off the top of my head the tradeoffs are:
Different xib:
Storyboard:
Code:
If you forced me to make a choice, I'd shove everything in a storyboard if your UI is complicated or do it in code if it is easy. Storyboards are the more "modern" approach and what Apple is pushing.
Hi @ChrisHamons , thank you very much for the answer.
Something like this should work
I would consider reading the "Adding and Removing Views from a Hierarchy" section in
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CocoaViewsGuide/WorkingWithAViewHierarchy/WorkingWithAViewHierarchy.html
in particular note "Note: For performance reasons, Cocoa does not enforce clipping among sibling views or guarantee correct invalidation and drawing behavior when sibling views overlap. If you want a view to be drawn in front of another view, you should make the front view a subview (or descendant) of the rear view."
If you want overlapping views, they need to have a parent/child hierarchy, else the behavior is undefined by Apple.