# Migrate iOS Sender App From Cast SDK v2 to the Cast Application Framework (CAF)

The following procedure enables you to convert your iOS sender app from Cast SDK
v2 to CAF Sender, which is based on the
[GCKCastContext](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_context)
singleton.

## Introduction

- CAF Sender is still distributed on the [Google Cast developer website](https://developers.google.com/cast/docs/ios_sender_setup) and [CocoaPods](https://cocoapods.org/pods/google-cast-sdk), like v2.
- New classes have been added that take on responsibility for complying with the Google Cast design checklist.
- CAF Sender provides widgets that comply with the Cast UX requirements; v2 did not provide any UI components and required you to implement these widgets.
- CAF Sender design is consistent with the Cast Android SDK design.
- CAF Sender supports Bitcode, like v2.
- Closed captioning in CAF is similar to v2.

## Dependencies

CAF Sender supports iOS version 8 and later.

## Initialization

In CAF, an explicit initialization step is required for the Cast framework. This
involves initializing the
[`GCKCastContext`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_context)
singleton, using an appropriate
[`GCKCastOptions`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_options)
to specify the Web Receiver application ID and any other global
options. This is typically done in the `AppDelegate`
`https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didFinishLaunchingWithOptions:` method:

    GCKCastOptions *options = [[GCKCastOptions alloc]
        initWithReceiverApplicationID:applicationID];
    [GCKCastContext setSharedInstanceWithOptions:options];

This step was not necessary in v2.

## Device discovery

In CAF, the discovery process is started and stopped automatically by the
framework when the app comes to the foreground and goes to the background,
respectively. The `GCKDeviceScanner` and `GCKFilterCriteria` classes from v2 are
deprecated and should not be used.

## Cast button and Cast dialog

In CAF, the Cast button and dialog are provided by the framework. The Cast
button can be instantiated and added to the navigation bar as follows:

    GCKUICastButton *castButton =
        [[GCKUICastButton alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
    castButton.tintColor = [UIColor whiteColor];
    self.navigationItem.rightBarButtonItem =
        [[UIBarButtonItem alloc] initWithCustomView:castButton];

The Cast button can also be added to the storyboard.

When someone taps the button, the Cast dialog is presented automatically.

## Device control

In CAF, device control is largely handled by the framework. The sender
application does not need to handle connecting to the device and launching the
Web Receiver application. The v2 class
[`GCKDeviceManager`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_device_manager)
is deprecated and should
not be used. Interaction between sender and Web Receiver is now represented as a
"session". The CAF
[`GCKSessionManager`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_session_manager)
class handles session lifecycle and
automatically starts and stops sessions in response to user gestures: a session
is started when the user selects a Cast device in the Cast dialog and is ended
when the user taps the "Stop Casting" button in the Cast dialog or when the
sender app itself terminates. The sender application can be notified of session
lifecycle events by registering a
[`GCKSessionManagerListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p)
with the
[`GCKSessionManager`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_session_manager).
The
[`GCKSessionManagerListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p)
protocol defines callback methods for all session lifecycle events.

The
[`GCKCastSession`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_session)
class represents a session with a Cast device. The class
has methods for controlling the device volume and mute states, which was
previously done in v2 using methods on
[`GCKDeviceManager`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_device_manager).

In v2, the
[`GCKDeviceManagerDelegate`](https://developers.google.com/cast/v3/reference/ios/protocol_g_c_k_device_manager_delegate-p)
protocol provided notifications of changes
to the device state, including volume, mute state, standby status, and so on.
In CAF, volume/mute state change notifications are delivered via callback
methods in the
[`GCKSessionManagerListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p)
protocol; these listeners are registered with the
[`GCKSessionManager`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_session_manager).
All of the remaining device state notifications are
delivered via a
[`GCKCastDeviceStatusListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_cast_device_status_listener-p)
protocol; these listeners are registered with the
[`GCKCastSession`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_session).

## Reconnection logic

As with v2, CAF attempts to re-establish network connections that
are lost due to temporary WiFi signal loss or other network errors. This is now
done at the session level; a session can enter a "suspended" state when the
connection is lost, and will transition back to a "connected" state when
connectivity is restored. The framework takes care of reconnecting to the
Web Receiver application and reconnecting any Cast channels as part of this process.

In addition, CAF also adds automatic session resumption. If the sender
application is sent to the background or is terminated (by swiping-away or
because of a crash) while a Cast session is in progress, the framework will
attempt to resume that session when the sender application returns to the
foreground or is relaunched; this is handled automatically by the
[`GCKSessionManager`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_cast_device_status_listener-p),
which will issue the appropriate callbacks on any registered
[`GCKSessionManagerListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p)
instances.

## Custom channel registration

In v2, custom channels (implemented using either a
[`GCKCastChannel`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_channel)
subclass or a
[`GCKGenericChannel`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_generic_channel)
and delegate) were registered with the
[`GCKDeviceManager`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_device_manager).
In CAF, custom channels are instead registered with the
[`GCKCastSession`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_session)
instance. The registration can be done in the
[`GCKSessionManagerListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p)
`https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_session_manager_listener-p#ab760f41d01385fddd46e33197c55ef20`
callback method. For media applications, it is no longer necessary to explicitly
register the
[`GCKMediaControlChannel`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_media_control_channel);
see the following section for more details.

## Media control

The v2 class
[`GCKMediaControlChannel`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_media_control_channel)
is deprecated and should not be used. In CAF, it is superseded by the new
[`GCKRemoteMediaClient`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_remote_media_client)
class, which provides equivalent functionality in a more convenient API.
It is not necessary to explicitly initialize or register this object; the
framework will automatically instantiate the object and register the underlying
media channel at session start time if the Web Receiver application being connected
to supports the media namespace.

The
[`GCKRemoteMediaClient`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_remote_media_client)
can be accessed with the
`https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_session#a3a822b45be11d3759aceac55527504a8`
property of the
[`GCKCastSession`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_session)
object.

In v2, all media requests issued on the
[`GCKMediaControlChannel`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_media_control_channel)
would return a numeric request ID, and methods on
[`GCKMediaControlChannelDelegate`](https://developers.google.com/cast/v3/reference/ios/protocol_g_c_k_media_control_channel_delegate-p)
would provide this ID when sending notifications about request completion or
failure.

In CAF, all media requests issued on the
[`GCKRemoteMediaClient`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_remote_media_client)
will return a
[`GCKRequest`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_request)
object; this object has an associated
[`GCKRequestDelegate`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_request_delegate-p)
protocol
which can be used to track the progress and eventual outcome of the request.

The v2
[`GCKMediaControlChannel`](https://developers.google.com/cast/v3/reference/ios/interface_g_c_k_media_control_channel);
would send notifications about changes in the media player state on the Web Receiver
via the
[`GCKMediaControlChannelDelegate`](https://developers.google.com/cast/v3/reference/ios/protocol_g_c_k_media_control_channel_delegate-p).
In CAF, the
[`GCKRemoteMediaClient`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_remote_media_client)
provides equivalent callbacks via its
[`GCKRemoteMediaClientListener`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_remote_media_client_listener-p)
protocol. Any number of listeners can be registered with the
`GCKRemoteMediaClient`, which allows multiple sender components to share the
single instance of `GCKRemoteMediaClient` that is associated with the session.

In v2, the sender application had to take on the burden of keeping the user
interface in sync with the media player state on the Web Receiver. In CAF, the class
[`GCKUIMediaController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_media_controller)
takes on most of this responsibility; see the
[codelab tutorial](https://codelabs.developers.google.com/codelabs/cast-videos-ios/)
documentation for examples on how to use this component.

## Introductory overlay

V2 does not provide an
[introductory overlay UI](https://developers.google.com/cast/docs/design_checklist/cast-button#prompting).

CAF adds class
[`GCKCastContext`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_context)
with a method
`https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_context#ab714866063a7d91b9e74b534e1b55b8f`
that a sender app can use to highlight the Cast button when it is first shown
to users.

## Mini controller

In v2, you need to implement a mini controller from scratch in the
sender app.

In CAF, the framework provides a control bar,
[`GCKUIMiniMediaControlsViewController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_mini_media_controls_view_controller),
which you can add to the scenes where you want to show the persistent
controls. There are two ways to add the mini controller to a sender app:

- Let the Cast framework manage the layout of the mini controller by wrapping
  your existing view controller with the
  [`GCKUICastContainerViewController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_cast_container_view_controller)
  and adding a
  [`GCKUIMiniMediaControlsViewController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_mini_media_controls_view_controller)
  at the bottom of its view.

- Add the mini controller directly to your existing view controller by using
  `https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_cast_context#ab26e1d13aa2a56f2fc158be68982c37e`
  to create a
  [`GCKUIMiniMediaControlsViewController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_mini_media_controls_view_controller)
  instance and then adding it to the container view controller as a subview.

## Expanded controller

In v2, you need to implement an expanded controller from scratch in
the sender app.

CAF adds
[`GCKUIMediaController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_media_controller),
which you could use to more easily implement an expanded controller.

CAF adds a pre-built expanded controller widget
[`GCKUIExpandedMediaControlsViewController`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_u_i_expanded_media_controls_view_controller)
which you can simply add to your app. You no longer need to implement a custom expanded
controller using `GCKUIMediaController`.

## Debug logging

The
[`GCKLogger`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_logger)
and
[`GCKLoggerDelegate`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_logger_delegate-p)
classes from v2 are carried over into CAF, with some changes and enhancements.

The
[`GCKLoggerDelegate`](https://developers.google.com/cast/docs/reference/ios/protocol_g_c_k_logger_delegate-p)
`-[logFromFunction:message:]` method has
been deprecated in favor of
`-[logMessage:fromFunction:]`.

Framework log messages can now be filtered by constructing an appropriate
[`GCKLoggerFilter`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_logger_filter)
instance and assigning it by setting the
`-[filter]` property of the
[`GCKLogger`](https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_logger) singleton.

## Sample apps

We recommend looking at the
[codelabs](https://codelabs.developers.google.com/codelabs/cast-videos-ios/) and
[sample apps](https://github.com/googlecast/CastVideos-ios) written for CAF.