Overview

This document provides an overview of the SEssentialsTabbedView control. It describes the features of the control and its associated concepts, together with some step-by-step guides for achieving common tasks.

The SEssentialsTabbedView provides an easy way to display and navigate between multiple views using a single viewport, in a similar way to tab separators in paper documents. Tabs can be added, removed, and rearranged by default, or locked in position.

If you simply want to get up and running, follow the Quick Start Guide - Objective-C, or the Quick Start Guide - Swift. Alternatively, for a more detailed description of how the Tabbed View works and the features it presents, head over to the ShinobiEssentials Tabbed View Control Overview. Finally, for guides that tackle specific usage scenarios, head on over to the ShinobiEssentials Tabbed View How-to Guides.

The Tabbed View has a complete set of Xamarin.iOS bindings, allowing you to make use of all of its features from within applications written in C#. In order to get up and running, follow the Quick Start Guide for Xamarin iOS.

Quick Start Guide - Objective-C

Introduction

The following guide will get you up-and-running with the SEssentialsTabbedView component as quickly as possible. In this guide, we will introduce you to the key features of the Tabbed View, including initial project setup and adding items. You can follow along with the related code sample: TabbedViewGettingStarted.xcodeproj.

Creating a Tabbed View

Start up Xcode and create a new project (File / New / Single View Application).

Within your newly created project, add a reference to the ShinobiEssentials framework, and the bundle which contains its resources. Instructions for doing this can be found in the first section of the EssentialsUserGuide.

Tabbed views require a datasource to provide the content for the tabs. We will implement the methods later on, but for now we can specify that our view controller will implement the SEssentialsTabbedViewDataSource protocol. Open up ViewController.h:

#import <UIKit/UIKit.h>
#import <ShinobiEssentials/ShinobiEssentials.h>

@interface ViewController : UIViewController< SEssentialsTabbedViewDataSource >

@end

In ViewController.m we can define an ivars keep hold of our tabbed view:

#import "ViewController.h"

@implementation ViewController {
    SEssentialsTabbedView *myTabView;
}

In ViewController.m, initialize myTabView in viewDidLoad as;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    myTabView = [[SEssentialsTabbedView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:myTabView];
}

Run the application, and check you have an empty tab bar at the top of your view, similar to this;

Adding Items

With the Tabbed View in place, we want to add some content. To do this, we need to make a few small changes.

In ViewController.m, we need a dictionary to map each tab to the content for the tab:

@implementation ViewController {
    SEssentialsTabbedView *myTabView;
    NSMutableDictionary *mapTabToView;
}

In viewDidLoad, we need to set up the dictionary, tell the Tabbed View that we are acting as a datasource, and fill in a tab with content;

- (void)viewDidLoad
{
    ...
    [self.view addSubview:myTabView];
    myTabView.dataSource = self;

    [self.view addSubview:myTabView];

    //Set up the Tab=>View dictionary
    mapTabToView = [[NSMutableDictionary alloc] init];

    // Let's make 2 tabs
    [self setupTabWithText:@"Hello world"];
    [self setupTabWithText:@"Another tab"];
}

As content for our tab, we will use a simple “Hello World!” message;

- (void)setupTabWithText:(NSString*)text
{
    UITextView *myText = [[UITextView alloc] initWithFrame:[myTabView contentViewBounds]];
    [myText setText:text];
    [myText setFont:[UIFont boldSystemFontOfSize:24]];
    [myText setBackgroundColor:[UIColor lightGrayColor]];

    SEssentialsTab *myTab = [[SEssentialsTab alloc] initWithName:@"Hello, Tab!" icon:nil];
    [self addView:myText forTab:myTab];

    [myTabView addTab:myTab];
}

We have called a method addView:forTab: which adds the specified view as the content for the given tab in our backing-store dictionary. It’s important to note here that SEssentialsTab does not implement NSCopying and therefore it is not possible to use it as a key in an NSDictionary. Therefore we use the valueWithNonretainedObject method on NSValue to create a pointer which can be used as a key. If the underlying tab is deallocated, this pointer will become a junk pointer, so this approach requires a certain amount of care:

 - (void)addView:(UIView *)view forTab:(SEssentialsTab *)tab
{
    [mapTabToView setObject:view forKey:[NSValue valueWithNonretainedObject:tab]];
}

We create a simple UITextView, set the content and some styling, create a tab, map the two together, and pass it to myTabView.

One important point here is that the tabs have no concept of the content associated with them. This is where the datasource comes in. We map a tab to its content using the mapTabToView dictionary so when the Tabbed View requests the content, we can look it up in the dictionary;

- (UIView *)tabbedView:(SEssentialsTabbedView *)tabbedViewRef contentForTab:(SEssentialsTab *)tab
{
    return [mapTabToView objectForKey:[NSValue valueWithNonretainedObject:tab]];
}

Simple enough! Now run your app, and check that you have a tab called “Hello, Tab!” with “Hello World!” as the content.

If you got stuck at any point, take a look at our related code sample: TabbedViewGettingStarted.xcodeproj.

Quick Start Guide - Swift

Introduction

The following guide will get you up-and-running with the SEssentialsTabbedView component as quickly as possible. In this guide, we will introduce you to the key features of the Tabbed View, including initial project setup and adding items. You can follow along with the related code sample: TabbedViewGettingStartedSwift.xcodeproj.

Setting up the project

Start up Xcode and create a new project (File / New / Single View Application). Within your newly created project, add a reference to the ShinobiEssentials framework, and the bundle which contains its resources. Instructions for doing this can be found in the first section of the EssentialsUserGuide.

Linking to the bridging header file

In order for Xcode to use an Objective-C based framework in Swift, it needs to have a bridging header file. We have included a bridging header file in our framework. To link to it, you must open the build settings for the your new target, and search for the Objective-C Bridging Header setting. You must then provide the path to the ShinobiEssentials-Bridging-Header.h file, which is inside the Headers directory of the ShinobiEssentials.framework.

Setting the Swift project's bridging header file

In the screenshot above, the framework is three directories above the root of the project, hence it is set to

$(SRCROOT)/../../../ShinobiEssentials.framework/Headers/ShinobiEssentials-Bridging-Header.h

Note that this path will vary based on the location of the framework on your file system.

Adding a Tabbed View

Tabbed views require a datasource to provide the content for the tabs. We will implement the methods later on, but for now we can specify that our view controller will implement the SEssentialsTabbedViewDataSource protocol. Open up ViewController.swift:

class ViewController: UIViewController, SEssentialsTabbedViewDataSource {

We can now define a Dictionary property to keep hold of our tab views.

var tabToViewMap:Dictionary<NSValue, UIView> = Dictionary()

This defines a Dictionary that contains UIViews, keyed by NSValue. We will later use SEssentialsTab objects for these values, to be able to look up a content view from a tab.

Continue and add the following code to ViewDidLoad().

override func viewDidLoad() {
    super.viewDidLoad()

    SEssentials.setLicenseKey("") // Trial Users - Add your license key here!

    let tabView = SEssentialsTabbedView(frame: view.bounds)
    tabView.dataSource = self
    view.addSubview(tabView)

We have set the dataSource of the tabView to be self, meaning we must create the tabs and provide some views for the tabs to use. Before we can return the views in the contentForTab delegate method, we must set them up and add them to the dictionary.

for index in 1...10 {
    let tabContentTextView = UITextView(frame: tabView.contentViewBounds)
    tabContentTextView.text = "Content for tab \(index)"
    tabContentTextView.font = UIFont.boldSystemFontOfSize(24)
    tabContentTextView.backgroundColor = UIColor.lightGrayColor()
    tabContentTextView.autoresizingMask = .FlexibleWidth | .FlexibleHeight

    let tab = SEssentialsTab(name: "Tab \(index)", icon: nil)
    tabToViewMap[NSValue(nonretainedObject: tab)] = tabContentTextView
    tabView.addTab(tab)
}

This for loop creates a UITextView to use as the content view of the tab, and creates the tabs themeslves, adding them to the tabView as they are created. The text views are also added to the dictionary, keyed by an NSValue containing the tabs themselves.

Now we can implement contentForTab, which is just a case of using the tab object passed into this method to look up the respective view in the dictionary:

func tabbedView(tabbedView: SEssentialsTabbedView!, contentForTab tab: SEssentialsTab!) -> UIView!  {
    return tabToViewMap[NSValue(nonretainedObject: tab)]
}

Run your project, and you should see 10 tabs. Tapping a tab should load a UITextView with the correct index number!

If you got stuck at any point, take a look at our related code sample: TabbedViewGettingStartedSwift.xcodeproj.

Quick Start Guide for Xamarin.iOS

Xamarin.iOS: Introduction

The following guide will get you up-and-running with the SEssentialsTabbedView component as quickly as possible. In this guide, we will introduce you to the key features of the Tabbed View, including initial project setup and adding items. You can follow along with the related code sample: TabbedViewGettingStarted.sln.

Xamarin.iOS: Creating a Tabbed View

Start up Xamarin Studio and create a new project (File / New / Solution), then selecting C# / iOS / Universal / Single View Application as your project type, naming your project ‘TabbedViewGettingStarted’.

Within your newly created project, add a reference to the ShinobiEssentials.dll. To do this, right click the References folder under your newly create project and choose ‘Edit References…’. Then select ‘.Net Assembly’ and browse to where you unpacked the ShinobiEssentials zip file. The dll can be found within the Xamarin.iOS / lib folder. Be sure to click ‘Add’ after selecting the dll to add it to your project, and close the window.

To check that the dll is correctly referenced, expand the References folder and you should see the ShinobiEssentials.dll listed as a reference.

First, add a member variable to the view controller for the TabbedView. Open up TabbedViewGettingStartedViewController.cs, and define the member varaible as follows:

...
using ShinobiEssentials;

namespace TabbedViewGettingStarted
{
    public partial class TabbedViewGettingStartedViewController : UIViewController
    {
        SEssentialsTabbedView tabbedView;

        public TabbedViewGettingStartedViewController ()
            : base ("TabbedViewGettingStartedViewController", null)
        {
        }
        ...
    }
}

Further down the view controller, within the generated ViewDidLoad method create an instance of the TabbedView and add it to the view:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    tabbedView = new SEssentialsTabbedView (View.Bounds);
    View.AddSubview (tabbedView);
}

Run the application, and check you have an empty tab bar at the top of your view, similar to this;

Xamarin.iOS: Adding Items

Now that your TabbedView has been created, you can start adding some content. Each tab content is provided via the datasource. In order to provide this data to the Tabbed View you must create a new class that inherits from SEssentialsTabbedViewDataSource.

Right-click the project and select the Add / New File … option, selecting the Empty Class option, naming the class TabbedViewDataSource. Make the class inherit SEssentialsTabbedViewDataSource and add a member variable that we will use to store the content for each tab as follows:

public class TabbedViewDataSource : SEssentialsTabbedViewDataSource
{
    Dictionary < SEssentialsTab, UIView > mapTabToView = new Dictionary < SEssentialsTab, UIView > ();
}

Now add a method to TabbedViewDataSource so we can add tabs to the datasource, and implement the required GetContent method so the TabbedView can get the content for its tabs, as follows:

public void AddViewForTab(UIView view, SEssentialsTab tab)
{
    mapTabToView [tab] = view;
}

public override UIView GetContent (SEssentialsTabbedView tabbedView, SEssentialsTab tab)
{
    return mapTabToView [tab];
}

One important point here is that the tabs have no concept of the content associated with them. This is why the datasource is necessary. We map a tab to its content using the mapTabToView dictionary so when the TabbedView requests the content, it can be fetched from the dictionary.

Now we can make our TabbedView use the datasource and create some default tabs. Open up TabbedViewGettingStartedViewController.cs and modify it to include the following:

public partial class TabbedViewGettingStartedViewController : UIViewController
{
    ...
    TabbedViewDataSource dataSource = new TabbedViewDataSource();

    ...
    public override void ViewDidLoad ()
    {
        tabbedView = new SEssentialsTabbedView (View.Bounds) {
            DataSource = dataSource
        };
        View.AddSubview (tabbedView);

        // Let's make a tab
        SetUpTab ("Hello world");
    }

    void SetUpTab(string text)
    {
        UITextView myText = new UITextView (tabbedView.ContentViewBounds()) {
            Text = text,
            Font = UIFont.BoldSystemFontOfSize(24),
            BackgroundColor = UIColor.LightGray
        };
        SEssentialsTab myTab = new SEssentialsTab ("Hello, Tab!", null);
        dataSource.AddViewForTab (myText, myTab);

        tabbedView.AddTab (myTab);
    }
}

Here we create our datasource, tell the tabbedView to use it and create a tab.

For each tab we create a simple UITextView, set the content and some styling, and map it to the view (via the datasource), and add it to tabbedView.

Simple enough! Now run your app, and check that you have a tab called “Hello, Tab!” with “Hello World!” as the content.

If you got stuck at any point, take a look at our related code sample: TabbedViewGettingStarted.sln.

ShinobiEssentials Tabbed View Control Overview

The SEssentialsTabbedView is a UIView which comprises a set of subviews, only one of which is visible at any given time. Navigating between these subviews is achieved via a horizontal tab bar.

The diagram shows how the SEssentialsTabbedView is composed of subsections. The main concept is that it has a tabBarView that displays the tab headers and a contentViewArea that shows the user content associated with the tab. The tabBarView itself is further broken down into a series of tabs of which only one can be active, the activeTab. To handle use cases where there may be more tabs than can be displayed on screen there is a button area that can display tabOverflowDropdown.

Further Details

The SEssentialsTabbedView can be used to hold several UIViews that the user can switch between by touching the tabs. The tabbed view can hold many tabs and these appear in the tab bar. The tab bar is an implementation of the protocol SEssentialsTabBarProtocol and manages the display of multiple tabs where only one tab can be active at an one time. Each tab is an instance of SEssentialsTab.

  • SEssentialsTab A SEssentialsTab object holds information about the tab including its name and a representative icon. Importantly, it does not hold any reference to the view associated with the tab. This allows the tab to be a relatively lightweight object. This also means that should you require access to the content of the tabs at any point you should keep a reference to them. The associated view is supplied by the tabbed view’s datasource. Only one SEssentialsTab can be active at one time and the tabs can be added, reordered and removed when in edit mode.

  • Tab header views Each tab contains a header view, which adopts the SEssentialsTabHeaderViewProtocol. The header view controls the appearance of the tab. By default, the tab header view will be an instance of SEssentialsTabHeaderView. You can create your own implementation of the header view protocol if you require different appearance or behavior from what this provides.

Tabs appear in the order in which they were added but this ordering can be changed when the tabbed view is in edit mode. Tabs can be moved by dragging them in the tab area and can also be removed by touching the cross symbol to close a tab.

The Delegate

The SEssentialsTabbedView uses a delegate as per the standard UIKit pattern, to notify your application when the user interacts with the TabbedView. In order to react to the user interactions, you need to supply the TabbedView with a class adopting the SEssentialsTabbedViewDelegate protocol.

The methods on the delegate protocol follow these conventions;

  • should - delegate methods prefixed with ‘should’ are invoked before a user interaction is processed. The ‘should’ methods give you the opportunity to cancel an interaction. For example, you can use a ‘should’ method to cancel the removal of tabs.
  • will - delegate methods prefixed with ‘will’ are invoked just before the interaction is processed. These are not cancellable. You typically implement a ‘will’ method if you need to capture the state just before a change occurs.
  • did - delegate methods prefixed with ‘did’ are invoked after the interaction has been processed. When the ‘did’ method is invoked the TabbedView state will have changed to reflect the change due to the user interaction.

The Datasource

The SEssentialsTabbedView requires a datasource - an object which implements the SEssentialsTabbedViewDataSource protocol. This will provide the content view associated with each tab as the user activates them in turn.

The datasource has one required method: tabbedView:contentForTab: and an optional one tabForTabbedView:. The datasource will request the content to be shown when a tab is touched. The SEssentialsTabbedView behaves in a virtualized way, so content views are added and removed only when required. The SEssentialsCarousel does not retain the content views of inactive tabs, so the datasource must retain all of its views.

Styling

The SEssentialsTabbedViewStyle defines the look and feel for an instance of the SEssentialsTabbedView class. If you wish to update how a tabbed view looks, you should update its style object. The style object allows you to configure the following visual aspects of a tabbed view:

  • The color, width, text color and font which is used in the tabs.
  • The color and texture which is used for the background behind the tabs.
  • The height of the area reserved for the tabs.
  • The size of the shadow which is applied underneath the button area (containing the overflow and new tab buttons), and onto the tabs behind it.

Decoration can be applied to the tabbed view. When decoration is applied, the following effects are added to the control:

  • The tab header views are moved so they overlap slightly with each other. When no decoration is applied, the header views will line up without any overlap.
  • The look of the overflow dropdown menu is changed. A translucent border is drawn around the menu, and a drop shadow is drawn beneath the menu.

The decoration property controls whether decoration is applied to the control.

If a style change will result in the tabs changing size, such as updating the font or title of a tab, the tab bar must be updated by calling reloadTabs.

Customizing images within the tabbed view

The tabbed view uses the following set of images:

  • Tabs. If you use the default tabbed view headers, the tabs are displayed using a set of images. These are as follows:
    • An image for the tab when it is active.
    • An image for the tab when it is inactive.
    • You can change the tint color of the tab, so the control contains mask images for the active and inactive states as well.
    • The tab contains a delete button. The control contains an image for the button in its normal state, and when it is pressed.
  • Tab bar:
    • You can specify an image for the bar underneath the tabs.
    • You can tint the tab bar, so a mask is provided for it as well.
  • Button area. The button area contains a ‘new tab’ button, and can contain an ‘overflow dropdown’ button if there are too many tabs to be displayed on screen at once. To draw the button area, the following images are used:
    • An image for the ‘new tab’ button in its normal state, and one for when it is pressed.
    • An image for the ‘overflow dropdown’ button in its normal state, and one for when it is pressed.
    • You can change the tint color of both buttons, so the control contains masks for both buttons as well.
    • In versions of iOS earlier than 7.0, a rounded end is displayed for the bar containing the ‘new tab’ and ‘overflow dropdown’ buttons. An image is used for this rounded end. Like the rest of the bar, it can be tinted, so a mask is also provided (See below).

The style contains these images. Once you’ve created the style, the images are readonly. You can customize the images in the style when you construct it.

To do this, you first create an instance of a SEssentialsTabbedViewImagesWrapper object. This has properties for each of the images in the tabbed view. You can then set the properties on the images wrapper which you would like to customize. Any properties on the images wrapper which aren’t set will just use the default image. An example is shown below where we customize the image and mask used for the active tab in the tabbed view:

SEssentialsTabbedViewImagesWrapper *customImagesWrapper = [SEssentialsTabbedViewImagesWrapper new];
customImagesWrapper.activeImage = [UIImage imageNamed:@"myActiveTabImage.png"];
customImagesWrapper.activeTabMask = [UIImage imageNamed:@"myActiveTabMask.png"];

SEssentialsTabbedViewStyle *myStyle = [[SEssentialsTabbedViewStyle alloc] initWithTheme:yourTheme customImages:customImagesWrapper];
SEssentialsTabbedView *myTabbedView = [[SEssentialsTabbedView alloc] initWithFrame:myFrame tabBarPosition:myTabBarPosition style:myStyle];

iOS7 vs. Earlier iOS versions

In the SEssentialsIOS7Theme, we use images very differently from the other themes. By default, iOS7 devices will use the SEssentialsIOS7Theme, while devices on previous versions will use the SEssentialsDarkTheme.

In iOS7, the “Add tab” and “Overflow” buttons are both tintable, making use of the addTabMask and overflowTabsMask on the SEssentialsTabbedViewStyle. In previous versions, these masks are not used, and the colours are already drawn onto the images.

Buttons in iOS7 theme (left) and Dark theme (right)

To create your own buttons, you will need to provide addTabImage, addTabMask and addTabPressed for the “Add Tab” button, and overflowTabsImage, overflowTabsMask and overflowTabsPressed for the “Overflow” button. If you don’t want to tint the image, then the mask for each set can just be a blank image, of the same dimensions as the other two images in the set.

In addition, the general style of the images and theme in iOS7 is a much flatter, less cluttered appearance, in keeping with the Apple style guidelines. The shine and curved corners on the tabs has been removed, and they no longer overlap in iOS7.

The Tab Bar in iOS7 theme (left) and Dark theme (right)

To create your own custom tab appearance using images, you will need to provide an activeImage, activeTabMask, inactiveImage, inactiveTabMask, closeTabImage and closeTabPressedImage. The activeImage and activeMask control the look and tinting of the active tab, while the inactiveImage and inactiveTabMask control the look and tinting of all inactive tabs. The closeTabImage and closeTabPressedImage control the delete button on the active tab.

The Overflow menu is also much flatter, with a slight transparency and no border.

The Overflow menu in iOS7 theme (left) and Dark theme (right)

Default style settings

SEssentialsTabbedViewStyle derives from SEssentialsStyle, and so it is initialized with an SEssentialsTheme object. The theme provides the default settings for the style.

The following default settings are provided by the theme:

  • The primaryTintColor on the theme is used for the background color of the tab header views (tintColor).
  • The secondaryTintColor on the theme is used for the background color of the tab bar (tabBarBackgroundColor).
  • The tertiaryTintColor on the theme is used as the tint color for the ‘new tab’ and ‘overflow dropdown menu’ icons (tabButtonsTintColor).
  • The secondaryTexture on the theme is used for the background texture of the tab bar (tabBarBackgroundTexture).
  • The primaryTextColor on the theme is used for text in active tab header views (defaultFontColor).
  • The secondaryTextColor on the theme is used as the color for text in inactive tab header views (alternativeFontColor).
  • The secondaryFont on the theme is used as the default font on tabs (defaultFont).
  • The primaryFont on the theme is used as the default font for items in the overflow menu (defaultOverflowFont).

ShinobiEssentials Tabbed View How-to Guides

How to customize the appearance of a Tabbed View

The SEssentialsTabbedView comes with a variety of styling options to tweak, allowing beginners to quickly make it work and look good while more advanced users can have more control over the appearance. In particular, the TabbedView allows you to pass in custom views for tabs, and has a style which can be modified as desired. For more information on the styling, see our Control Overview and the SEssentialsTabbedViewStyle API documentation.

To create a custom tab view, we have two options available; we can either subclass the SEssentialsTabHeaderView class and override the basic defaults we need, or we can start from scratch by adopting the SEssentialsTabHeaderViewProtocol. As an example, we will be doing the latter of these two options. You can follow along with our related code sample: TabbedViewHowToCustomTabs.xcodeproj.

Both options require the initWithName:icon:customTabView: method on the SEssentialsTab class, such as below;

CustomTabHeader *customHeader = [[CustomTabHeader alloc] initWithFrame:CGRectMake(0, 0, 200, 50)];
SEssentialsTab *newTab = [[SEssentialsTab alloc] initWithName:@"Custom tab" icon:nil customTabView:customHeader];
[tabbedView addTab:newTab];

The CustomTabHeader adopts the SEssentialsTabHeaderViewProtocol:

@interface CustomTabHeader : UIView<SEssentialsTabHeaderViewProtocol>
@end

The protocol has a few properties and methods which we will need to synthesize and implement, as below. You will also need to fill in your initialization method to layout everything the way you want;

@implementation CustomTabHeader

@synthesize tab;
@synthesize active;
@synthesize removable;

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        // Your custom init here
    }
    return self;
}

-(void)updateView
{

}

-(UIImage *)destinationMarker
{
    UIGraphicsBeginImageContext(self.bounds.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return img;
}
@end

The destinationMarker method will return a “ghost image” representation, to use when rearranging the tabs. If you just want to take a snapshot of your tab without any extras, the implementation of destinationMarker above will do exactly that.

If you got stuck at any point take a look at our related code sample: TabbedViewHowToCustomTabs.xcodeproj

How to add and remove tabs from the tabbed view

While users are using the Tabbed View, you may want to give them the ability to add or remove tabs at runtime. This how-to guide will show you how to add and remove tabs from your Tabbed View. You can follow along with the related code sample: TabbedViewHowToAddRemoveTabs.xcodeproj.

In the Quick start guide, we covered adding tabs programmatically, at compile time. To recap, we create an SEssentialsTab, and pass it to our Tabbed View with addTab:, keeping a reference in our own program of the content for the tab. Similarly, if we want to remove a tab programmatically, we can call removeTab: on the Tabbed View, passing in our tab to remove. We can alternatively use addTab:atIndex: and removeTabDisplayedAtIndex:. For example;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    tabbedView = [[SEssentialsTabbedView alloc] initWithFrame:self.view.bounds];
    [self setupTabCalled:@"First Tab"];
    [self setupTabCalled:@"Second Tab"];
    [self setupTabCalled:@"Third Tab"];

    [self.view addSubview:tabbedView];

    [tabbedView removeTabDisplayedAtIndex:0];
}

-(void)setupTabCalled:(NSString*)tabName
{
    SEssentialsTab *tab = [[SEssentialsTab alloc] initWithName:tabName icon:nil];
    [tabbedView addTab:tab atIndex:0];
}

Here we create three tabs, inserting each at 0 (i.e. displaying the tabs in reverse order), then deleting the last created tab, leaving us with “Second Tab” and “First Tab”.

By default, the user is allowed to remove these tabs, using the “X” button on the active tab to remove it. The user is not allowed to delete the final tab though, otherwise we would have nothing to display. If you want to stop the user being able to delete the tabs, use the editable property on the Tabbed View.

When a user deletes a tab, the SEssentialsTabbedViewDelegate will be informed via the tabbedView:shouldRemoveTab:, tabbedView:willRemoveTab: and tabbedView:didRemoveTab: callbacks. Depending on the tab’s content, you may need to update your datasource to remove the content yourself too. For more about the delegate, refer to the Control Overview and the SEssentialsTabbedViewDelegate API.

To allow the user to add more tabs, we set the hasNewTabButton property on the Tabbed View to YES, and implement the tabForTabbedView: method on the SEssentialsCarouselDataSource

-(void)viewDidLoad
{
    ...
    tabbedView.dataSource = self;
    tabbedView.hasNewTabButton = YES;
}

-(SEssentialsTab *)tabForTabbedView:(SEssentialsTabbedView *)tabbedView
{
    return [[SEssentialsTab alloc] initWithName:@"New Tab" icon:nil];
}

Now when the user presses the “+” button, the Tabbed View will request the new tab from us.

If you got stuck at any point take a look at our related code sample: TabbedViewAddRemoveTabs.xcodeproj