Having used Fragments in Xamarin.Android and ContentControls in WPF I was keen to understand how to create pages composed of subviews in iOS.
The project I am working on has a number of pages sharing some common views implemented as Fragments in Xamarin.Android. As we come to write the Xamarin.iOS app for the project I needed to find out how to implement the equivalent of Fragments in iOS. This aim of this post is to share what I have found out.
Having used the Model-View-ViewModel (MVVM) pattern in WPF for many years, and now also in Xamarin projects the concept of reusing sub-views within the main page backed by a View Model is second nature. Having Googled this it seems that the
ContainerView in iOS should provide something like the
FrameLayout in Android or
ContentControl in WPF.
The sharing of views in iOS to provide an equivalent to
Fragments in Android is the scenario which I need to find a solution for and is the subject of this post.
There is a related scenario which is the transitioning of child views within a page, someting which I have done a lot in the past using WPF with different forms of Transitioning Content Controls. I intend to look at this scenario in another post.
Another aspect we can start to look at is actually working together in a team of devs on these views/pages when held in Storyboards.
If two developers edit the same Storyboard then the merge conflict that may well arise is very difficult to fix. I'll cover this in more detail in another post, but for this post we will look at creating a new Storyboard to contain the Shared View and reference it from the Main storyboard by using Storyboard References.
The Example app demonstrates using a
ContainerView to display a Shared View in two different pages:-
The Apple documentation Implementing a Container View Controller is a great starting point.
The apple documentation Adding a Storyboard Reference.
ContainerViewwill automatically create a
ViewControllerfor the child content and reference it using an Embed Segue.
Multiple View Controllers can reference the child content via Embed Segues. The same instance of the child
We can reference View Controllers in separate Storyboards by the use of Storyboard References.
Using Storyboard References require an app targeting at least iOS 8.0, OS X 10.10, or watchOS 1.0
The example app we will create will consist of a Home page with buttons to show a First page and a Second page. The FirstPage and SecondPage will each have a
ContainerView displaying the same SharedView.
Embedding a Shared View using a ContainerView
I have already created the basic app pages, so we will start with the Main Storyboard below with the Home, First and Second pages already created:-
ContainerView from the Toolbox onto the First Page View Controller, the
ContainerView will be added and a
ViewController created. We would most likely generate a code-behind file for this View Controller but to keep things simple we will omit this for now:-
ContainerView and copy it and paste onto the
SecondPageViewController. Now Click+Drag from this onto the
ViewController added in the previous step. A context menu will be displayed:-
Choose the Embed menu option and an Embed Segue will be created from the
SecondPageViewController to the
Label with the text Shared View and change the backgound colour of the View so that we can identify the Shared View:-
Run the app, the intial page is the Home Page:-
Click the First Page button and the page is displayed with the Shared View in the
Press the Home button in the Navigation Bar and then click the Second Page button and the page is displayed with the Shared View in the
Note there can only be a single embed Segue for the contiainer view so this technique cannot be used for the scenario of transitioning views.
The source code for this inital example can be found on GitHub.
Move the Shared View to a new Storyboard
Now we can use a
Storyboard Reference to enable the Shared View to be defined in a separate Storyboard to enable multiple developers to work together more easily.
Right-click on the project and choose the Add menu option and then the New File.. menu option, the New File dialog will be displayed:-
In the New File dialog select the iOS option and then the Storyboard file type options. Enter a name for the storyboard, in this example we will use the name SharedView:-
View Controller for the Shared View in the Main.storyboard and copy it from the Designer or the Document Outline pad.
Open the SharedView.storyboard file and right-click on the Designer surface and select the Paste option. You will probably have to zoom out and scroll to see the
ViewController. The SharedView will be added:-
Note that this is now displayed full screen so we have to resize it to suit the size of the
ContainerView in which it will be hosted.
Select the SharedViewController and use the Properties pad to set the Presentation drop-down to Current Context. Check the Content Size option and set the Width to 320 and Height to 300.
At the top of the Presentation pad select the Layout tab. In the Simulated Size drop-down to Freeform. Set the Simulated Size Width to 320 and Height to 300.
Add a Storyboard ID of TheSharedView :-
Return to the Main.Storyboard and right-click on the View controller we have copied and select the Delete menu option.
In the Toolbox pad type story and the list will be filtered to show the Storyboard Reference. Select this and drag it onto the Designer:-
With the External View Controller selected enter SharedView into the Storyboard field and TheSharedView in the Referenced ID field:-
Ctrl-click and drag from the
ContainerView in the First Page onto the External View Controller and select the Embed menu option. Repeat this for the Second Page and the designer should look like this:-
The app now runs as before and the Shared View can be edited independently of the storyboards using it.
The source code for this example is in the repository Storyboard References.