XIB Code Generation

From $1
    Table of contents

    Overview

    The Apple Interface Builder tool ("IB") can be used to designer user interfaces visually. The interface definitions created by IB are saved in "xib" files. Widgets and other objects in xib files may be given a "class identity", which can be a custom user-defined type. This allows you you customize the behaviour of widgets and write custom widgets.

    These user classes are normally subclasses of UI controller classes. These have outlets (analogous to properties) and actions (analogous to events) that can be connected to interface objects. At runtime, when the IB file is loaded, the objects are created, and the outlets and actions are connected to the various UI objects dynamically. When defining these managed classes, you must define all the actions and outlets to match the ones that IB expects. MonoDevelop uses a CodeBehind-like model to simplify this. This is similar to what Xcode does for Objective-C, but the code generation model and conventions have been tweaked to be more familiar to .NET developers.

    Xib Files and Custom Classes

    As well as using existing types from Cocoa Touch, it is possible to define custom types in xib files. It is also possible to use types that are defined in other xib files, or defined purely in C# code. Currently Interface Builder is not aware of the details of types defined outside the current xib file, so will not list them or show their custom outlets and actions. We plan to remove this limitation sometime in the future.

    Custom classes may be defined in a xib file using the "Add Subclass" command in the "Classes" tab of Interface Builder. We refer to these as "CodeBehind" classes. If the xib file has a ".xib.designer.cs" counterpart file in the project, then MonoDevelop will automatically fill it with partial classes definitions for all the custom classes in the xib. We refer to these partial classes as "designer classes".

    Generating Code

    For any {0}.xib file with a build action of Page, if a {0}.xib.designer.cs file also exists in the project, MonoDevelop will generate partial classes in the designer file for all of the user classes it can find in the XIB file, with properties for the outlets and partial methods for all of the actions. Code generation is enabled simply by the presence of this file.

    The designer file is automatically updated when the xib file changes and MonoDevelop regains focus. The designer file should not be modified manually, as changes will be overwritten next time MonoDevelop updates the file.

    Registration and Namespaces

    MonoDevelop generates the designer classes using the project's default namespace for the designer file location, to make it consistent with normal .NET project namespacing. The namespace of designer files is driven by the project's "default namespace" and its ".NET naming policies" settings. Beware that if your project's default namespace changes, MD will regenerate the classes in the new namespace, so you may find that your partial classes no longer match up.

    In order to make the class discoverable by the Objective-C runtime, MD applies a [Register (name)] attribute to the class. Although the MonoTouch automatically registers NSObject-derived classes, it uses the fully-qualified .NET name. The attribute applied by MD overrides this to ensure it's registered it with the name used in the IB file. If you use custom classes in IB without using MonoDevelop to generate designer files, you may have to apply this manually to make your managed classes match up to the expected Objective-C class names.

    Classes cannot be defined in more that one xib, or they will conflict.

    Non-Designer Class Parts

    Designer partial classes are not intended to be used as-is. Outlets are private, and no base class is specified. It is expected that each class will have a corresponding "non-designer" class part in another file, which sets the base class, defines constructors that are required to instantiate the class from native code when loading the xib, and uses or exposes the outlets. The default xib templates do this, but for any additional custom classes you define in a xib you must add the non-designer part manually.

    The reason for this is for flexibility. For example, multiple CodeBehind classes could subclass a common managed abstract class which subclasses the class that IB thinks they need to subclass.

    It is conventional to put these in a {0}.xib.cs file beside the {0}.xib.designer.cs designer file.

    Generated Actions and Outlets

    In the partial designer classes, MonoDevelop generates properties corresponding to any connected outlets defined in IB, and partial methods corresponding to any connected actions.

    Outlet Properties

    Designer classes contain properties corresponding to all outlets defined on the custom class. The fact that these are properties is an implementation detail of the MonoTouch to Objective C bridge, to enable lazy binding. You should consider them to be equivalent private fields, intended to be used only from the CodeBehind class. If you wish to make them public, add accessor properties to the non-designer class part as you would for any other private field.

    If outlet properties are defined to have a type of "id" (equivalent to NSObject) then the designer code generator currently determines the strongest possible type based on objects connected to that outlet, for convenience. However, this may not be supported in future versions, so it is recommended that you explicitly strongly type the outlets when defining the custom class.

    Action Properties

    Designer classes contain partial methods corresponding to all actions defined on the custom class. These are methods without an implementation.  The purpose of the partial methods is twofold:

    1. If you type partial in the class body of the non-designer class part, MonoDevelop will offer to autocomplete the signatures of all non-implemented partial methods.
    2. The partial method signatures have an attribute applied that exposes them to the Objective-C world, so they can get handled as to the corresponding action.

    If you wish, you may ignore the partial method, and implement the action by applying the attribute to a different method, or let it fall through to a base class.

    If actions defined to have a sender type of "id" (equivalent to NSObject) then the designer code generator currently determines the strongest possible type based on objects connected to that action, for convenience. However, this may not be supported in future versions, so it is recommended that you explicitly strongly type the actions when defining the custom class.

    Note that these partial methods are created only for C#, because CodeDOM doesn't support partial methods, so they are not generated for other languages.

    Cross-XIB Class Usage

    Sometimes users wish to reference the same class from multiple XIB files, for example with tab controllers. This can be done by explictly referencing the class definition from another XIB file, or by defining the same class name again in the second XIB.

    The latter case can be problematic. Because MD processes XIB files individually, it cannot automatically detect and merge duplicate definitions, so you may end up with conflicts applying the Register attribute multiple times when the same partial class is defined in multiple designer files. Recent versions of MonoDevelop attempt to resolve this, but this may not always work as expected. In future is is likely to become unsupported, and instead MonoDevelop will make all types defined in all xib files and managed code in the project directly visible from all xib files. 

    Type Resolution

    Types used in IB are Objective-C type names. These are mapped to CLR types though the use of Register attributes. When generating outlet and action code, MonoDevelop will resolve the corresponding CLR types for all Objective-C types wrapped by the MonoTouch core, and fully qualify their types names.

    However, the code generator cannot currently resolve CLR types from Objective-C type names in user code or libraries, so in such cases it outputs the type name verbatim. This means that the corresponding CLR type must have the same name as the Objective-C type and be in the same namespace as the code that's using it. This is planned to be fixed sometime in the future by considering all Objective-C types in the project during code generation.

     

    Tag page
    • No tags

    Files (0)

     
    Page last modified 22:49, 3 Feb 2011 by MichaelHutchinson