Better understanding ViewControllers and their workflow

I’m doing my best to read the documentation (Hello MAC, SourceWriter, Working with Storyboards, etc) about the GUI development paradigm, (MVC storyboards, Xamarin/xcode designer etc), and it’s been very helpful but in practice I’m running into several questions. I am new to MVC in general, although I understand the abstract idea, I’m stuck on how the pieces are represented by the Xamarin/Xcode workflow. I will try to keep this generic and high level so it will be useful for others as well.

I've observed:

  • “ViewController”s are present as scenes in the Xcode storyboard designer.
  • They are also present as cs files in the Xamarin project.
  • A ViewController in the storyboard designer doesn’t necessarily have a corresponding cs file. Atleast, it is not immediately created when a view controller in the storyboard is created.

Questions:
1. For starters, any general comments you have on the difference/roles of a ViewController being represented in these two ways, relationships/conventions between them?
2. Using SourceWriter as an example, it seems that a ViewController.cs has been given to every scene, is it typically the case that every scene in the designer should have a corresponding ViewController.cs (or WIndowController.cs)?
3. Since they are not created automatically when a ViewController is added to the storyboard, is it my responsibility to add these new controller cs files for each scene into the xamarin sln project (assuming I want to expose some outlets/actions)?
4. If I create a new ViewController.cs to go with my new scene, how is it “connected” (technically speaking) to the VC entity in the designer? Is there some metadata that links them together? Or is the only actual connection made when I add an outlet and choose a specific VC.h file to drag the outlet into? The latter would imply it’s totally arbitrary which VC.cs the outlets are put in, and thus seeming disconnect between storyboard-view-controllers and cs-view-controllers. Perhaps the logical link between them is mere convention?
5. Why are there (sometimes) “view” cs code files? I understand view controllers needing a .cs presence for exposing outlets/actions to the rest of your cs code, but is the view itself not defined inside the storyboard file? With the view's members (buttons, labels, etc) exposed by outlets in the ViewController.cs. Of what value is a cs reference to the view itself? The only view.cs example I’ve seen has been empty, save for the boiler plate (Sourcewriter DefinitionsView.cs)
6. When I create a new ViewController.cs in Xamarin, it comes with a View.cs and a xib file? Are those needed? When you created all the Controller.cs files in SourceWriter, did you go in and remove the xib file and View.cs and it's declaration in the controller?

Posts

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    These are some very good questions, not all covered by our documentation, which you've already gone over.

    Let me post some high level answers and you (or others) can poke for more details if needed.

    1

    • There are two "worlds" in existence in your Xamarin.Mac application while running, "Managed" and "Native". They live side by side, and many objects are reflected in both, but not all. Let me explain.
    • Your storyboard might have many buttons, views, and the like you never interact with in your C# code. When your application starts and the storyboard is inflated into "real" objects again, they only exist right now as "Native" Cocoa objects.
    • Your C# code might have many classes that do not derive from NSObject and are never passed to Cocoa APIs. Those items only live in the "managed" world.
    • And there are the classes that span the gap. A NSViewController from your storyboard that you have a reference to in C#, or a NSObject derived C# class you pass to a Cocoa method.
    • https://developer.xamarin.com/guides/mac/advanced_topics/internals/ has some details on how the magic works, but the 10,000 foot "view" is that we have code that binds the gap; letting C# call Cocoa with objects we register as obj-c classes and wrapping native Cocoa objects in C# classes that you can interact with.
    • If, for example, you enumerated your visual tree and poked at NSViews that previously weren't exposed to C#, we handle things for you so it "just works". 95% of the time, you don't have to care about this.
    • The most common reason to care is to make sure that your lifetimes are correct. If you create an NSViewController for example, make sure to hold on to a reference as long as the view is live. If you assign a delegate class to a view for callback later, make sure your C# class stays around until you unregister. Stuff like that. Most of the time if you screw it up, you'll just get a memory leak or a window disappears on you. In a few cases you can crash though.

    2

    • It is a very common pattern in Cocoa to declare your code in one or more storyboard / xib files, and "inflate" them later into object graphs.
    • NSViewController/NSWindowControllers are classes that handle much of this work for you, and make the transitions between steps nice, but they are not required.
    • There is no reason you couldn't define all of your visual tree in C# if you really wanted to - https://developer.xamarin.com/samples/mac/MacXibless/ .
    • Do see the code in this answer https://forums.xamarin.com/discussion/comment/224426/#Comment_224426 for how to get the view controller for a view defined in a storyboard.

    3

    • Yes, we do not reflect every single action you do in a storyboard with a C# class. If you follow the (older) pattern of separate xib files for each view/window, you can use the new file template in Xamarin Studio and get much of this done for you.
    • What's the better way? It's a toss up. If you do transitions, storyboards let you do that easily, and keep everything in one place. Separate xib files tend to scale better with larger teams, and are easier for some us cases to wrap your mind around.

    4

    • In your ViewController.designer.cs file you'll see something like this:

    [Register ("ViewController")]
    partial class ViewController

    • See https://developer.xamarin.com/guides/mac/advanced_topics/internals/ for details, but roughly this says "tell the Cocoa runtime that we're the definition for this thing, and handle all of the work of getting those objective-c messages to my C# methods please.
    • In your storyboard, if you select the view controller and go to the 3rd tab, you'll see the "Custom Class" matches that name. This tells Xcode to please generate the serialized object that gets created when you load the storyboard with this name.
    • If both of these match, then your C# methods will get called when that objects in Awakened from the storyboard/nib.

    5

    Not every View in your visual tree needs to have a "managed" half. Sometimes, it's just because the IDE template gave us one, but if it is doing nothing then you could just delete it and remove the custom class in the storyboard/xib.

    However, often if the View wants to handle certain events, or put more "smarts" in it in general, you'll have a C# part.

    With the rise of NSViewControllers, this is getting a bit less common, but is far from wrong.

    6

    The default Xamarin Studio template still assume you are creating separate xib files for major portions of your applications. If you want to shove everything in a storyboard, you can delete the xib file, create the item in your storyboard, set your custom class to match the name of the C# bit, and call it a day (mostly).

  • BarrettLewisBarrettLewis USMember ✭✭

    Thanks for taking the time to write out this excellent and informative response. Especially the comments on #1, and the Xibless project I think will come in handy for some unusual parts of my project.

Sign In or Register to comment.