Integrate Cast Into Your iOS App

This developer guide describes how to add Google Cast support to your iOS sender app using the iOS Sender SDK.

The mobile device or laptop is the sender which controls the playback, and the Google Cast device is the receiver which displays the content on the TV.

The sender framework refers to the Cast class library binary and associated resources present at runtime on the sender. The sender app or Cast app refers to an app also running on the sender. The Web Receiver app refers to the HTML application running on the Web Receiver.

The sender framework uses an asynchronous callback design to inform the sender app of events and to transition between various states of the Cast app life cycle.

App flow

The following steps describe the typical high-level execution flow for a sender iOS app:

  • The Cast framework starts GCKDiscoveryManager based on the properties provided in GCKCastOptions to begin scanning for devices.
  • When the user clicks on the Cast button, the framework presents the Cast dialog with the list of discovered Cast devices.
  • When the user selects a Cast device, the framework attempts to launch the Web Receiver app on the Cast device.
  • The framework invokes callbacks in the sender app to confirm that the Web Receiver app was launched.
  • The framework creates a communication channel between the sender and Web Receiver apps.
  • The framework uses the communication channel to load and control media playback on the Web Receiver.
  • The framework synchronizes the media playback state between sender and Web Receiver: when the user makes sender UI actions, the framework passes those media control requests to the Web Receiver, and when the Web Receiver sends media status updates, the framework updates the state of the sender UI.
  • When the user clicks on the Cast button to disconnect from the Cast device, the framework will disconnect the sender app from the Web Receiver.

To troubleshoot your sender, you need to enable logging .

For a comprehensive list of all classes, methods and events in the Google Cast iOS framework, see the Google Cast iOS API Reference . The following sections cover the steps for integrating Cast into your iOS app.

Call methods from main thread

Initialize the Cast context

The Cast framework has a global singleton object, the GCKCastContext , which coordinates all of the framework's activities. This object must be initialized early in the application's lifecycle, typically in the -[application:didFinishLaunchingWithOptions:] method of the app delegate, so that automatic session resumption on sender app restart can trigger properly.

A GCKCastOptions object must be supplied when initializing the GCKCastContext . This class contains options that affect the behavior of the framework. The most important of these is the Web Receiver application ID, which is used to filter discovery results and to launch the Web Receiver app when a Cast session is started.

The -[application:didFinishLaunchingWithOptions:] method is also a good place to set up a logging delegate to receive the logging messages from the framework. These can be useful for debugging and troubleshooting.

Swift
 @UIApplicationMain 
 class 
  
 AppDelegate 
 : 
  
 UIResponder 
 , 
  
 UIApplicationDelegate 
 , 
  
 GCKLoggerDelegate 
  
 { 
  
 let 
  
 kReceiverAppID 
  
 = 
  
 kGCKDefaultMediaReceiverApplicationID 
  
 let 
  
 kDebugLoggingEnabled 
  
 = 
  
 true 
  
 var 
  
 window 
 : 
  
 UIWindow 
 ? 
  
 func 
  
 applicationDidFinishLaunching 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 ) 
  
 { 
  
 let 
  
 criteria 
  
 = 
  
 GCKDiscoveryCriteria 
 ( 
 applicationID 
 : 
  
 kReceiverAppID 
 ) 
  
 let 
  
 options 
  
 = 
  
 GCKCastOptions 
 ( 
 discoveryCriteria 
 : 
  
 criteria 
 ) 
  
 GCKCastContext 
 . 
 setSharedInstanceWith 
 ( 
 options 
 ) 
  
 // Enable logger. 
  
 GCKLogger 
 . 
 sharedInstance 
 (). 
 delegate 
  
 = 
  
 self 
  
 ... 
  
 } 
  
 // MARK: - GCKLoggerDelegate 
  
 func 
  
 logMessage 
 ( 
 _ 
  
 message 
 : 
  
 String 
 , 
  
 at 
  
 level 
 : 
  
 GCKLoggerLevel 
 , 
  
 fromFunction 
  
 function 
 : 
  
 String 
 , 
  
 location 
 : 
  
 String 
 ) 
  
 { 
  
 if 
  
 ( 
 kDebugLoggingEnabled 
 ) 
  
 { 
  
 print 
 ( 
 function 
  
 + 
  
 " - " 
  
 + 
  
 message 
 ) 
  
 } 
  
 } 
 } 
Objective-C

AppDelegate.h

 @interface 
 AppDelegate 
  
 () 
  
< GCKLoggerDelegate 
> @end 

AppDelegate.m

 @implementation 
 AppDelegate 
 static 
  
 NSString 
  
 * 
 const 
  
 kReceiverAppID 
  
 = 
  
 @"AABBCCDD" 
 ; 
 static 
  
 const 
  
 BOOL 
  
 kDebugLoggingEnabled 
  
 = 
  
 YES 
 ; 
 - 
 ( 
 BOOL 
 ) 
 application: 
 ( 
 UIApplication 
  
 * 
 ) 
 application 
 didFinishLaunchingWithOptions 
 :( 
 NSDictionary 
  
 * 
 ) 
 launchOptions 
  
 { 
  
 GCKDiscoveryCriteria 
  
 * 
 criteria 
  
 = 
  
 [[ 
 GCKDiscoveryCriteria 
  
 alloc 
 ] 
  
 initWithApplicationID 
 : 
 kReceiverAppID 
 ]; 
  
 GCKCastOptions 
  
 * 
 options 
  
 = 
  
 [[ 
 GCKCastOptions 
  
 alloc 
 ] 
  
 initWithDiscoveryCriteria 
 : 
 criteria 
 ]; 
  
 [ 
 GCKCastContext 
  
 setSharedInstanceWithOptions 
 : 
 options 
 ]; 
  
 // Enable logger. 
  
 [ 
 GCKLogger 
  
 sharedInstance 
 ]. 
 delegate 
  
 = 
  
 self 
 ; 
  
 ... 
  
 return 
  
 YES 
 ; 
 } 
 ... 
 #pragma mark - GCKLoggerDelegate 
 - 
 ( 
 void 
 ) 
 logMessage: 
 ( 
 NSString 
  
 * 
 ) 
 message 
  
 atLevel 
 :( 
 GCKLoggerLevel 
 ) 
 level 
  
 fromFunction 
 :( 
 NSString 
  
 * 
 ) 
 function 
  
 location 
 :( 
 NSString 
  
 * 
 ) 
 location 
  
 { 
  
 if 
  
 ( 
 kDebugLoggingEnabled 
 ) 
  
 { 
  
 NSLog 
 ( 
 @"%@ - %@, %@" 
 , 
  
 function 
 , 
  
 message 
 , 
  
 location 
 ); 
  
 } 
 } 
 @end 

The Cast UX widgets

The Cast iOS SDK provides these widgets that comply with the Cast Design Checklist:

  • Introductory Overlay : The GCKCastContext class has a method, presentCastInstructionsViewControllerOnceWithCastButton , which can be used to spotlight the Cast button the first time a Web Receiver is available. The sender app can customize the text, position of the title text and the Dismiss button.

  • Cast Button : Starting with Cast iOS sender SDK 4.6.0, the cast button is always visible when the sender device is connected to Wi-Fi. The first time the user taps on the Cast button after initially starting the app, a permissions dialog appears so the user can grant the app local network access to devices on the network. Subsequently, when the user taps on the cast button, a cast dialog is displayed which lists the discovered devices. When the user taps on the cast button while the device is connected, it displays the current media metadata (such as title, name of the recording studio and a thumbnail image) or allows the user to disconnect from the cast device. When the user taps on the cast button while there are no devices available, a screen will be displayed giving the user information on why devices not be found and how to troubleshoot.

  • Mini Controller : When the user is casting content and has navigated away from the current content page or expanded controller to another screen in the sender app, the mini controller is displayed at the bottom of the screen to allow the user to see the currently casting media metadata and to control the playback.

  • Expanded Controller : When the user is casting content, if they click on the media notification or mini controller, the expanded controller launches, which displays the currently playing media metadata and provides several buttons to control the media playback.

Add a Cast button

The framework provides a Cast button component as a UIButton subclass. It can be added to the app's title bar by wrapping it in a UIBarButtonItem . A typical UIViewController subclass can install a Cast button as follows:

Swift
 let 
  
 castButton 
  
 = 
  
 GCKUICastButton 
 ( 
 frame 
 : 
  
 CGRect 
 ( 
 x 
 : 
  
 0 
 , 
  
 y 
 : 
  
 0 
 , 
  
 width 
 : 
  
 24 
 , 
  
 height 
 : 
  
 24 
 )) 
 castButton 
 . 
 tintColor 
  
 = 
  
 UIColor 
 . 
 gray 
 navigationItem 
 . 
 rightBarButtonItem 
  
 = 
  
 UIBarButtonItem 
 ( 
 customView 
 : 
  
 castButton 
 ) 
Objective-C
 GCKUICastButton 
  
 * 
 castButton 
  
 = 
  
 [[ 
 GCKUICastButton 
  
 alloc 
 ] 
  
 initWithFrame 
 : 
 CGRectMake 
 ( 
 0 
 , 
  
 0 
 , 
  
 24 
 , 
  
 24 
 )]; 
 castButton 
 . 
 tintColor 
  
 = 
  
 [ 
 UIColor 
  
 grayColor 
 ]; 
 self 
 . 
 navigationItem 
 . 
 rightBarButtonItem 
  
 = 
  
 [[ 
 UIBarButtonItem 
  
 alloc 
 ] 
  
 initWithCustomView 
 : 
 castButton 
 ]; 

By default, tapping the button will open the Cast dialog that is provided by the framework.

GCKUICastButton can also be added directly to the storyboard.

Configure device discovery

In the framework, device discovery happens automatically. There is no need to explicitly start or stop the discovery process unless you implement a custom UI.

Discovery in the framework is managed by the class GCKDiscoveryManager , which is a property of the GCKCastContext . The framework provides a default Cast dialog component for device selection and control. The device list is ordered lexicographically by device friendly name.

How session management works

The Cast SDK introduces the concept of a Cast session, the establishment of which combines the steps of connecting to a device, launching (or joining) a Web Receiver app, connecting to that app, and initializing a media control channel. See the Web Receiver Application life cycle guide for more information about Cast sessions and the Web Receiver life cycle.

Sessions are managed by the class GCKSessionManager , which is a property of the GCKCastContext . Individual sessions are represented by subclasses of the class GCKSession : for example, GCKCastSession represents sessions with Cast devices. You can access the currently active Cast session (if any), as the currentCastSession property of GCKSessionManager .

The GCKSessionManagerListener interface can be used to monitor session events, such as session creation, suspension, resumption, and termination. The framework automatically suspends sessions when the sender app is going into the background and attempts to resume them when the app returns to the foreground (or is relaunched after an abnormal/abrupt app termination while a session was active).

If the Cast dialog is being used, then sessions are created and torn down automatically in response to user gestures. Otherwise, the app can start and end sessions explicitly via methods on GCKSessionManager .

If the app needs to do special processing in response to session lifecycle events, it can register one or more GCKSessionManagerListener instances with the GCKSessionManager . GCKSessionManagerListener is a protocol which defines callbacks for such events as session start, session end, and so on.

Stream transfer

Preserving session state is the basis of stream transfer, where users can move existing audio and video streams across devices using voice commands, Google Home App, or smart displays. Media stops playing on one device (the source) and continues on another (the destination). Any Cast device with the latest firmware can serve as sources or destinations in a stream transfer.

To get the new destination device during the stream transfer, use the GCKCastSession#device property during the [sessionManager:didResumeCastSession:] callback.

See Stream transfer on Web Receiver for more information.

Automatic reconnection

The Cast framework adds reconnection logic to automatically handle reconnection in many subtle corner cases, such as:

  • Recover from a temporary loss of WiFi
  • Recover from device sleep
  • Recover from backgrounding the app
  • Recover if the app crashed

How media control works

If a Cast session is established with a Web Receiver app that supports the media namespace, an instance of GCKRemoteMediaClient will be created automatically by the framework; it can be accessed as the remoteMediaClient property of the GCKCastSession instance.

All methods on GCKRemoteMediaClient which issue requests to the Web Receiver will return a GCKRequest object which can be used to track that request. A GCKRequestDelegate can be assigned to this object to receive notifications about the eventual result of the operation.

It is expected that the instance of GCKRemoteMediaClient may be shared by multiple parts of the app, and indeed some internal components of the framework such as the Cast dialog and mini media controls do share the instance. To that end, GCKRemoteMediaClient supports the registration of multiple GCKRemoteMediaClientListener s.

The GCKMediaMetadata class represents information about a media item you want to cast. The following example creates a new GCKMediaMetadata instance of a movie and sets the title, subtitle, recording studio's name, and two images.

Swift
 let 
  
 metadata 
  
 = 
  
 GCKMediaMetadata 
 () 
 metadata 
 . 
 setString 
 ( 
 "Big Buck Bunny (2008)" 
 , 
  
 forKey 
 : 
  
 kGCKMetadataKeyTitle 
 ) 
 metadata 
 . 
 setString 
 ( 
 "Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " 
  
 + 
  
 "himself. When one sunny day three rodents rudely harass him, something " 
  
 + 
  
 "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " 
  
 + 
  
 "tradition he prepares the nasty rodents a comical revenge." 
 , 
  
 forKey 
 : 
  
 kGCKMetadataKeySubtitle 
 ) 
 metadata 
 . 
 addImage 
 ( 
 GCKImage 
 ( 
 url 
 : 
  
 URL 
 ( 
 string 
 : 
  
 "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/images/BigBuckBunny.jpg" 
 ) 
 ! 
 , 
  
 width 
 : 
  
 480 
 , 
  
 height 
 : 
  
 360 
 )) 
Objective-C
 GCKMediaMetadata 
  
 * 
 metadata 
  
 = 
  
 [[ 
 GCKMediaMetadata 
  
 alloc 
 ] 
  
 initWithMetadataType 
 : 
 GCKMediaMetadataTypeMovie 
 ]; 
 [ 
 metadata 
  
 setString 
 : 
 @"Big Buck Bunny (2008)" 
  
 forKey 
 : 
 kGCKMetadataKeyTitle 
 ]; 
 [ 
 metadata 
  
 setString 
 : 
 @"Big Buck Bunny tells the story of a giant rabbit with a heart bigger than " 
  
 "himself. When one sunny day three rodents rudely harass him, something " 
  
 "snaps... and the rabbit ain't no bunny anymore! In the typical cartoon " 
  
 "tradition he prepares the nasty rodents a comical revenge." 
  
 forKey 
 : 
 kGCKMetadataKeySubtitle 
 ]; 
 [ 
 metadata 
  
 addImage 
 : 
 [[ 
 GCKImage 
  
 alloc 
 ] 
  
 initWithURL 
 :[[ 
 NSURL 
  
 alloc 
 ] 
  
 initWithString 
 : 
 @"https://commondatastorage.googleapis.com/" 
  
 "gtv-videos-bucket/sample/images/BigBuckBunny.jpg" 
 ] 
  
 width 
 : 
 480 
  
 height 
 : 
 360 
 ]]; 

See the Image Selection and Caching section on the use of images with media metadata.

Load media

To load a media item, create a GCKMediaInformation instance using the media's metadata. Then get the current GCKCastSession and use its GCKRemoteMediaClient to load the media on the receiver app. You can then use GCKRemoteMediaClient for controlling a media player app running on the receiver, such as for play, pause, and stop.

Swift
 let 
  
 url 
  
 = 
  
 URL 
 . 
 init 
 ( 
 string 
 : 
  
 "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" 
 ) 
 guard 
  
 let 
  
 mediaURL 
  
 = 
  
 url 
  
 else 
  
 { 
  
 print 
 ( 
 "invalid mediaURL" 
 ) 
  
 return 
 } 
 let 
  
 mediaInfoBuilder 
  
 = 
  
 GCKMediaInformationBuilder 
 . 
 init 
 ( 
 contentURL 
 : 
  
 mediaURL 
 ) 
 mediaInfoBuilder 
 . 
 streamType 
  
 = 
  
 GCKMediaStreamType 
 . 
 none 
 ; 
 mediaInfoBuilder 
 . 
 contentType 
  
 = 
  
 "video/mp4" 
 mediaInfoBuilder 
 . 
 metadata 
  
 = 
  
 metadata 
 ; 
 mediaInformation 
  
 = 
  
 mediaInfoBuilder 
 . 
 build 
 () 
 guard 
  
 let 
  
 mediaInfo 
  
 = 
  
 mediaInformation 
  
 else 
  
 { 
  
 print 
 ( 
 "invalid mediaInformation" 
 ) 
  
 return 
 } 
 if 
  
 let 
  
 request 
  
 = 
  
 sessionManager 
 . 
 currentSession 
 ?. 
 remoteMediaClient 
 ?. 
 loadMedia 
 ( 
 mediaInfo 
 ) 
  
 { 
  
 request 
 . 
 delegate 
  
 = 
  
 self 
 } 
Objective-C
 GCKMediaInformationBuilder 
  
 * 
 mediaInfoBuilder 
  
 = 
  
 [[ 
 GCKMediaInformationBuilder 
  
 alloc 
 ] 
  
 initWithContentURL 
 : 
  
 [ 
 NSURL 
  
 URLWithString 
 : 
 @"https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" 
 ]]; 
 mediaInfoBuilder 
 . 
 streamType 
  
 = 
  
 GCKMediaStreamTypeNone 
 ; 
 mediaInfoBuilder 
 . 
 contentType 
  
 = 
  
 @"video/mp4" 
 ; 
 mediaInfoBuilder 
 . 
 metadata 
  
 = 
  
 metadata 
 ; 
 self 
 . 
 mediaInformation 
  
 = 
  
 [ 
 mediaInfoBuilder 
  
 build 
 ]; 
 GCKRequest 
  
 * 
 request 
  
 = 
  
 [ 
 self 
 . 
 sessionManager 
 . 
 currentSession 
 . 
 remoteMediaClient 
  
 loadMedia 
 : 
 self 
 . 
 mediaInformation 
 ]; 
 if 
  
 ( 
 request 
  
 != 
  
 nil 
 ) 
  
 { 
  
 request 
 . 
 delegate 
  
 = 
  
 self 
 ; 
 } 

Also see the section on using media tracks .

4K video format

To determine what video format your media is, use the videoInfo property of GCKMediaStatus to get the current instance of GCKVideoInfo . This instance contains the type of HDR TV format and the height and width in pixels. Variants of 4K format are indicated in the hdrType property by enum values GCKVideoInfoHDRType .

Add mini controllers

According to the Cast Design Checklist , a sender app should provide a persistent control known as the mini controller that should appear when the user navigates away from the current content page. The mini controller provides instant access and a visible reminder for the current Cast session.

The Cast framework provides a control bar, GCKUIMiniMediaControlsViewController , which can be added to the scenes in which you want to show the mini controller.

When your sender app is playing a video or audio live stream, the SDK automatically displays a play/stop button in place of the play/pause button in the mini controller.

See Customize iOS Sender UI for how your sender app can configure the appearance of the Cast widgets.

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 its own view controller.
  • Manage the layout of the mini controller widget yourself by adding it to your existing view controller by providing a subview in the storyboard.

Wrap using the GCKUICastContainerViewController

The first way is to use the GCKUICastContainerViewController which wraps another view controller and adds a GCKUIMiniMediaControlsViewController at the bottom. This approach is limited in that you cannot customize the animation and cannot configure the behavior of the container view controller.

This first way is typically done in the -[application:didFinishLaunchingWithOptions:] method of the app delegate:

Swift
 func 
  
 applicationDidFinishLaunching 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 ) 
  
 { 
  
 ... 
  
 // Wrap main view in the GCKUICastContainerViewController and display the mini controller. 
  
 let 
  
 appStoryboard 
  
 = 
  
 UIStoryboard 
 ( 
 name 
 : 
  
 "Main" 
 , 
  
 bundle 
 : 
  
 nil 
 ) 
  
 let 
  
 navigationController 
  
 = 
  
 appStoryboard 
 . 
 instantiateViewController 
 ( 
 withIdentifier 
 : 
  
 "MainNavigation" 
 ) 
  
 let 
  
 castContainerVC 
  
 = 
  
 GCKCastContext 
 . 
 sharedInstance 
 (). 
 createCastContainerController 
 ( 
 for 
 : 
  
 navigationController 
 ) 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
  
 = 
  
 true 
  
 window 
  
 = 
  
 UIWindow 
 ( 
 frame 
 : 
  
 UIScreen 
 . 
 main 
 . 
 bounds 
 ) 
  
 window 
 !. 
 rootViewController 
  
 = 
  
 castContainerVC 
  
 window 
 !. 
 makeKeyAndVisible 
 () 
  
 ... 
 } 
Objective-C
 - 
 ( 
 BOOL 
 ) 
 application: 
 ( 
 UIApplication 
  
 * 
 ) 
 application 
  
 didFinishLaunchingWithOptions 
 :( 
 NSDictionary 
  
 * 
 ) 
 launchOptions 
  
 { 
  
 ... 
  
 // Wrap main view in the GCKUICastContainerViewController and display the mini controller. 
  
 UIStoryboard 
  
 * 
 appStoryboard 
  
 = 
  
 [ 
 UIStoryboard 
  
 storyboardWithName 
 : 
 @"Main" 
  
 bundle 
 : 
 nil 
 ]; 
  
 UINavigationController 
  
 * 
 navigationController 
  
 = 
  
 [ 
 appStoryboard 
  
 instantiateViewControllerWithIdentifier 
 : 
 @"MainNavigation" 
 ]; 
  
 GCKUICastContainerViewController 
  
 * 
 castContainerVC 
  
 = 
  
 [[ 
 GCKCastContext 
  
 sharedInstance 
 ] 
  
 createCastContainerControllerForViewController 
 : 
 navigationController 
 ]; 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
  
 = 
  
 YES 
 ; 
  
 self 
 . 
 window 
  
 = 
  
 [[ 
 UIWindow 
  
 alloc 
 ] 
  
 initWithFrame 
 : 
 UIScreen 
 . 
 mainScreen 
 . 
 bounds 
 ]; 
  
 self 
 . 
 window 
 . 
 rootViewController 
  
 = 
  
 castContainerVC 
 ; 
  
 [ 
 self 
 . 
 window 
  
 makeKeyAndVisible 
 ]; 
  
 ... 
 } 
Swift
 var 
  
 castControlBarsEnabled 
 : 
  
 Bool 
  
 { 
  
 set 
 ( 
 enabled 
 ) 
  
 { 
  
 if 
  
 let 
  
 castContainerVC 
  
 = 
  
 self 
 . 
 window 
 ?. 
 rootViewController 
  
 as 
 ? 
  
 GCKUICastContainerViewController 
  
 { 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
  
 = 
  
 enabled 
  
 } 
  
 else 
  
 { 
  
 print 
 ( 
 "GCKUICastContainerViewController is not correctly configured" 
 ) 
  
 } 
  
 } 
  
 get 
  
 { 
  
 if 
  
 let 
  
 castContainerVC 
  
 = 
  
 self 
 . 
 window 
 ?. 
 rootViewController 
  
 as 
 ? 
  
 GCKUICastContainerViewController 
  
 { 
  
 return 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
  
 } 
  
 else 
  
 { 
  
 print 
 ( 
 "GCKUICastContainerViewController is not correctly configured" 
 ) 
  
 return 
  
 false 
  
 } 
  
 } 
 } 
Objective-C

AppDelegate.h

 @interface 
 AppDelegate 
: UIResponder 
  
< UIApplicationDelegate 
> @property 
  
 ( 
 nonatomic 
 , 
  
 strong 
 ) 
  
 UIWindow 
  
 * 
 window 
 ; 
 @property 
  
 ( 
 nonatomic 
 , 
  
 assign 
 ) 
  
 BOOL 
  
 castControlBarsEnabled 
 ; 
 @end 

AppDelegate.m

 @implementation 
 AppDelegate 
 ... 
 - 
  
 ( 
 void 
 ) 
 setCastControlBarsEnabled 
 : 
 ( 
 BOOL 
 ) 
 notificationsEnabled 
  
 { 
  
 GCKUICastContainerViewController 
  
 * 
 castContainerVC 
 ; 
  
 castContainerVC 
  
 = 
  
 ( 
 GCKUICastContainerViewController 
  
 * 
 ) 
 self 
 . 
 window 
 . 
 rootViewController 
 ; 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
  
 = 
  
 notificationsEnabled 
 ; 
 } 
 - 
  
 ( 
 BOOL 
 ) 
 castControlBarsEnabled 
  
 { 
  
 GCKUICastContainerViewController 
  
 * 
 castContainerVC 
 ; 
  
 castContainerVC 
  
 = 
  
 ( 
 GCKUICastContainerViewController 
  
 * 
 ) 
 self 
 . 
 window 
 . 
 rootViewController 
 ; 
  
 return 
  
 castContainerVC 
 . 
 miniMediaControlsItemEnabled 
 ; 
 } 
 ... 
 @end 

Embed in existing view controller

The second way is to add the mini controller directly to your existing view controller by using createMiniMediaControlsViewController to create a GCKUIMiniMediaControlsViewController instance and then adding it to the container view controller as a subview.

Set up your view controller in the app delegate:

Swift
 func 
  
 application 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 , 
  
 didFinishLaunchingWithOptions 
  
 launchOptions 
 : 
  
 [ 
 UIApplicationLaunchOptionsKey 
 : 
  
 Any 
 ]?) 
  
 -> 
  
 Bool 
  
 { 
  
 ... 
  
 GCKCastContext 
 . 
 sharedInstance 
 (). 
 useDefaultExpandedMediaControls 
  
 = 
  
 true 
  
 window 
 ?. 
 clipsToBounds 
  
 = 
  
 true 
  
 let 
  
 rootContainerVC 
  
 = 
  
 ( 
 window 
 ?. 
 rootViewController 
  
 as 
 ? 
  
 RootContainerViewController 
 ) 
  
 rootContainerVC 
 ?. 
 miniMediaControlsViewEnabled 
  
 = 
  
 true 
  
 ... 
  
 return 
  
 true 
 } 
Objective-C
-  
 ( 
 BOOL 
 ) 
 application 
 : 
 ( 
 UIApplication 
  
 * 
 ) 
 application 
  
 didFinishLaunchingWithOptions 
 :( 
 NSDictionary 
  
 * 
 ) 
 launchOptions 
  
 { 
  
 ... 
  
 [ 
 GCKCastContext 
  
 sharedInstance 
 ]. 
 useDefaultExpandedMediaControls 
  
 = 
  
 YES 
 ; 
  
 self 
 . 
 window 
 . 
 clipsToBounds 
  
 = 
  
 YES 
 ; 
  
 RootContainerViewController 
  
 * 
 rootContainerVC 
 ; 
  
 rootContainerVC 
  
 = 
  
 ( 
 RootContainerViewController 
  
 * 
 ) 
 self 
 . 
 window 
 . 
 rootViewController 
 ; 
  
 rootContainerVC 
 . 
 miniMediaControlsViewEnabled 
  
 = 
  
 YES 
 ; 
  
 ... 
  
 return 
  
 YES 
 ; 
 } 

In your root view controller, create a GCKUIMiniMediaControlsViewController instance and add it to the container view controller as a subview:

Swift
 let 
  
 kCastControlBarsAnimationDuration 
 : 
  
 TimeInterval 
  
 = 
  
 0.20 
 @objc 
 ( 
 RootContainerViewController 
 ) 
 class 
  
 RootContainerViewController 
 : 
  
 UIViewController 
 , 
  
 GCKUIMiniMediaControlsViewControllerDelegate 
  
 { 
  
 @IBOutlet 
  
 weak 
  
 private 
  
 var 
  
 _miniMediaControlsContainerView 
 : 
  
 UIView 
 ! 
  
 @IBOutlet 
  
 weak 
  
 private 
  
 var 
  
 _miniMediaControlsHeightConstraint 
 : 
  
 NSLayoutConstraint 
 ! 
  
 private 
  
 var 
  
 miniMediaControlsViewController 
 : 
  
 GCKUIMiniMediaControlsViewController 
 ! 
  
 var 
  
 miniMediaControlsViewEnabled 
  
 = 
  
 false 
  
 { 
  
 didSet 
  
 { 
  
 if 
  
 self 
 . 
 isViewLoaded 
  
 { 
  
 self 
 . 
 updateControlBarsVisibility 
 () 
  
 } 
  
 } 
  
 } 
  
 var 
  
 overriddenNavigationController 
 : 
  
 UINavigationController 
 ? 
  
 override 
  
 var 
  
 navigationController 
 : 
  
 UINavigationController 
 ? 
  
 { 
  
 get 
  
 { 
  
 return 
  
 overriddenNavigationController 
  
 } 
  
 set 
  
 { 
  
 overriddenNavigationController 
  
 = 
  
 newValue 
  
 } 
  
 } 
  
 var 
  
 miniMediaControlsItemEnabled 
  
 = 
  
 false 
  
 override 
  
 func 
  
 viewDidLoad 
 () 
  
 { 
  
 super 
 . 
 viewDidLoad 
 () 
  
 let 
  
 castContext 
  
 = 
  
 GCKCastContext 
 . 
 sharedInstance 
 () 
  
 self 
 . 
 miniMediaControlsViewController 
  
 = 
  
 castContext 
 . 
 createMiniMediaControlsViewController 
 () 
  
 self 
 . 
 miniMediaControlsViewController 
 . 
 delegate 
  
 = 
  
 self 
  
 self 
 . 
 updateControlBarsVisibility 
 () 
  
 self 
 . 
 installViewController 
 ( 
 self 
 . 
 miniMediaControlsViewController 
 , 
  
 inContainerView 
 : 
  
 self 
 . 
 _miniMediaControlsContainerView 
 ) 
  
 } 
  
 func 
  
 updateControlBarsVisibility 
 () 
  
 { 
  
 if 
  
 self 
 . 
 miniMediaControlsViewEnabled 
  
 && 
  
 self 
 . 
 miniMediaControlsViewController 
 . 
 active 
  
 { 
  
 self 
 . 
 _miniMediaControlsHeightConstraint 
 . 
 constant 
  
 = 
  
 self 
 . 
 miniMediaControlsViewController 
 . 
 minHeight 
  
 self 
 . 
 view 
 . 
 bringSubview 
 ( 
 toFront 
 : 
  
 self 
 . 
 _miniMediaControlsContainerView 
 ) 
  
 } 
  
 else 
  
 { 
  
 self 
 . 
 _miniMediaControlsHeightConstraint 
 . 
 constant 
  
 = 
  
 0 
  
 } 
  
 UIView 
 . 
 animate 
 ( 
 withDuration 
 : 
  
 kCastControlBarsAnimationDuration 
 , 
  
 animations 
 : 
  
 {() 
  
 -> 
  
 Void 
  
 in 
  
 self 
 . 
 view 
 . 
 layoutIfNeeded 
 () 
  
 }) 
  
 self 
 . 
 view 
 . 
 setNeedsLayout 
 () 
  
 } 
  
 func 
  
 installViewController 
 ( 
 _ 
  
 viewController 
 : 
  
 UIViewController 
 ?, 
  
 inContainerView 
  
 containerView 
 : 
  
 UIView 
 ) 
  
 { 
  
 if 
  
 let 
  
 viewController 
  
 = 
  
 viewController 
  
 { 
  
 self 
 . 
 addChildViewController 
 ( 
 viewController 
 ) 
  
 viewController 
 . 
 view 
 . 
 frame 
  
 = 
  
 containerView 
 . 
 bounds 
  
 containerView 
 . 
 addSubview 
 ( 
 viewController 
 . 
 view 
 ) 
  
 viewController 
 . 
 didMove 
 ( 
 toParentViewController 
 : 
  
 self 
 ) 
  
 } 
  
 } 
  
 func 
  
 uninstallViewController 
 ( 
 _ 
  
 viewController 
 : 
  
 UIViewController 
 ) 
  
 { 
  
 viewController 
 . 
 willMove 
 ( 
 toParentViewController 
 : 
  
 nil 
 ) 
  
 viewController 
 . 
 view 
 . 
 removeFromSuperview 
 () 
  
 viewController 
 . 
 removeFromParentViewController 
 () 
  
 } 
  
 override 
  
 func 
  
 prepare 
 ( 
 for 
  
 segue 
 : 
  
 UIStoryboardSegue 
 , 
  
 sender 
 : 
  
 Any 
 ?) 
  
 { 
  
 if 
  
 segue 
 . 
 identifier 
  
 == 
  
 "NavigationVCEmbedSegue" 
  
 { 
  
 self 
 . 
 navigationController 
  
 = 
  
 ( 
 segue 
 . 
 destination 
  
 as 
 ? 
  
 UINavigationController 
 ) 
  
 } 
  
 } 
 ... 
Objective-C

RootContainerViewController.h

 static 
  
 const 
  
 NSTimeInterval 
  
 kCastControlBarsAnimationDuration 
  
 = 
  
 0.20 
 ; 
 @interface 
 RootContainerViewController 
  
 () 
  
< GCKUIMiniMediaControlsViewControllerDelegate 
>  
 { 
  
 __weak 
  
 IBOutlet 
  
 UIView 
  
 * 
 _miniMediaControlsContainerView 
 ; 
  
 __weak 
  
 IBOutlet 
  
 NSLayoutConstraint 
  
 * 
 _miniMediaControlsHeightConstraint 
 ; 
  
 GCKUIMiniMediaControlsViewController 
  
 * 
 _miniMediaControlsViewController 
 ; 
 } 
 @property 
 ( 
 nonatomic 
 , 
  
 weak 
 , 
  
 readwrite 
 ) 
  
 UINavigationController 
  
 * 
 navigationController 
 ; 
 @property 
 ( 
 nonatomic 
 , 
  
 assign 
 , 
  
 readwrite 
 ) 
  
 BOOL 
  
 miniMediaControlsViewEnabled 
 ; 
 @property 
 ( 
 nonatomic 
 , 
  
 assign 
 , 
  
 readwrite 
 ) 
  
 BOOL 
  
 miniMediaControlsItemEnabled 
 ; 
 @end 

RootContainerViewController.m

 @implementation 
 RootContainerViewController 
- (void) 
 viewDidLoad 
  
 { 
  
 [ 
 super 
  
 viewDidLoad 
 ]; 
  
 GCKCastContext 
  
 * 
 castContext 
  
 = 
  
 [ 
 GCKCastContext 
  
 sharedInstance 
 ]; 
  
 _miniMediaControlsViewController 
  
 = 
  
 [ 
 castContext 
  
 createMiniMediaControlsViewController 
 ]; 
  
 _miniMediaControlsViewController 
 . 
 delegate 
  
 = 
  
 self 
 ; 
  
 [ 
 self 
  
 updateControlBarsVisibility 
 ]; 
  
 [ 
 self 
  
 installViewController 
 : 
 _miniMediaControlsViewController 
  
 inContainerView 
 : 
 _miniMediaControlsContainerView 
 ]; 
 } 
-  
 ( 
 void 
 ) 
 setMiniMediaControlsViewEnabled 
 : 
 ( 
 BOOL 
 ) 
 miniMediaControlsViewEnabled 
  
 { 
  
 _miniMediaControlsViewEnabled 
  
 = 
  
 miniMediaControlsViewEnabled 
 ; 
  
 if 
  
 ( 
 self 
 . 
 isViewLoaded 
 ) 
  
 { 
  
 [ 
 self 
  
 updateControlBarsVisibility 
 ]; 
  
 } 
 } 
-  
 ( 
 void 
 ) 
 updateControlBarsVisibility 
  
 { 
  
 if 
  
 ( 
 self 
 . 
 miniMediaControlsViewEnabled 
  
 && 
  
 _miniMediaControlsViewController 
 . 
 active 
 ) 
  
 { 
  
 _miniMediaControlsHeightConstraint 
 . 
 constant 
  
 = 
  
 _miniMediaControlsViewController 
 . 
 minHeight 
 ; 
  
 [ 
 self 
 . 
 view 
  
 bringSubviewToFront 
 : 
 _miniMediaControlsContainerView 
 ]; 
  
 } 
  
 else 
  
 { 
  
 _miniMediaControlsHeightConstraint 
 . 
 constant 
  
 = 
  
 0 
 ; 
  
 } 
  
 [ 
 UIView 
  
 animateWithDuration 
 : 
 kCastControlBarsAnimationDuration 
  
 animations 
 : 
 ^ 
 { 
  
 [ 
 self 
 . 
 view 
  
 layoutIfNeeded 
 ]; 
  
 }]; 
  
 [ 
 self 
 . 
 view 
  
 setNeedsLayout 
 ]; 
 } 
-  
 ( 
 void 
 ) 
 installViewController 
 : 
 ( 
 UIViewController 
  
 * 
 ) 
 viewController 
  
 inContainerView 
 :( 
 UIView 
  
 * 
 ) 
 containerView 
  
 { 
  
 if 
  
 ( 
 viewController 
 ) 
  
 { 
  
 [ 
 self 
  
 addChildViewController 
 : 
 viewController 
 ]; 
  
 viewController 
 . 
 view 
 . 
 frame 
  
 = 
  
 containerView 
 . 
 bounds 
 ; 
  
 [ 
 containerView 
  
 addSubview 
 : 
 viewController 
 . 
 view 
 ]; 
  
 [ 
 viewController 
  
 didMoveToParentViewController 
 : 
 self 
 ]; 
  
 } 
 } 
-  
 ( 
 void 
 ) 
 uninstallViewController 
 : 
 ( 
 UIViewController 
  
 * 
 ) 
 viewController 
  
 { 
  
 [ 
 viewController 
  
 willMoveToParentViewController 
 : 
 nil 
 ]; 
  
 [ 
 viewController 
 . 
 view 
  
 removeFromSuperview 
 ]; 
  
 [ 
 viewController 
  
 removeFromParentViewController 
 ]; 
 } 
-  
 ( 
 void 
 ) 
 prepareForSegue 
 : 
 ( 
 UIStoryboardSegue 
  
 * 
 ) 
 segue 
  
 sender 
 : 
 ( 
 id 
 ) 
 sender 
  
 { 
  
 if 
  
 ([ 
 segue 
 . 
 identifier 
  
 isEqualToString 
 : 
 @"NavigationVCEmbedSegue" 
 ]) 
  
 { 
  
 self 
 . 
 navigationController 
  
 = 
  
 ( 
 UINavigationController 
  
 * 
 ) 
 segue 
 . 
 destinationViewController 
 ; 
  
 } 
 } 
 ... 
 @end 

The GCKUIMiniMediaControlsViewControllerDelegate tells the host view controller when the mini controller should be visible:

Objective-C
 - 
 ( 
 void 
 ) 
 miniMediaControlsViewController: 
  
 ( 
 GCKUIMiniMediaControlsViewController 
  
 * 
 ) 
 miniMediaControlsViewController 
  
 shouldAppear 
 :( 
 BOOL 
 ) 
 shouldAppear 
  
 { 
  
 [ 
 self 
  
 updateControlBarsVisibility 
 ]; 
 } 
  

Add expanded controller

The Google Cast Design Checklist requires a sender app to provide an expanded controller for the media being cast. The expanded controller is a full screen version of the mini controller.

The expanded controller is a full screen view which offers full control of the remote media playback. This view should allow a casting app to manage every manageable aspect of a cast session, with the exception of Web Receiver volume control and session lifecycle (connect/stop casting). It also provides all the status information about the media session (artwork, title, subtitle, and so forth).

The functionality of this view is implemented by the GCKUIExpandedMediaControlsViewController class.

The first thing you have to do is enable the default expanded controller in the cast context. Modify the app delegate to enable the default expanded controller:

Swift
 func 
  
 applicationDidFinishLaunching 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 ) 
  
 { 
  
 .. 
  
 GCKCastContext 
 . 
 sharedInstance 
 (). 
 useDefaultExpandedMediaControls 
  
 = 
  
 true 
  
 ... 
 } 
Objective-C
 - 
 ( 
 BOOL 
 ) 
 application: 
 ( 
 UIApplication 
  
 * 
 ) 
 application 
 didFinishLaunchingWithOptions 
 :( 
 NSDictionary 
  
 * 
 ) 
 launchOptions 
  
 { 
  
 ... 
  
 [ 
 GCKCastContext 
  
 sharedInstance 
 ]. 
 useDefaultExpandedMediaControls 
  
 = 
  
 YES 
 ; 
  
 .. 
 } 

Add the following code to your view controller to load the expanded controller when the user starts to cast a video:

Swift
 func 
  
 playSelectedItemRemotely 
 () 
  
 { 
  
 GCKCastContext 
 . 
 sharedInstance 
 (). 
 presentDefaultExpandedMediaControls 
 () 
  
 ... 
  
 // Load your media 
  
 sessionManager 
 . 
 currentSession 
 ?. 
 remoteMediaClient 
 ?. 
 loadMedia 
 ( 
 mediaInformation 
 ) 
 } 
Objective-C
 - 
 ( 
 void 
 ) 
 playSelectedItemRemotely 
  
 { 
  
 [[ 
 GCKCastContext 
  
 sharedInstance 
 ] 
  
 presentDefaultExpandedMediaControls 
 ]; 
  
 ... 
  
 // Load your media 
  
 [ 
 self 
 . 
 sessionManager 
 . 
 currentSession 
 . 
 remoteMediaClient 
  
 loadMedia 
 : 
 mediaInformation 
 ]; 
 } 

The expanded controller will also be launched automatically when the user taps the mini controller.

When your sender app is playing a video or audio live stream, the SDK automatically displays a play/stop button in place of the play/pause button in the expanded controller.

See Apply Custom Styles to Your iOS App for how your sender app can configure the appearance of the Cast widgets.

Volume control

The Cast framework automatically manages the volume for the sender app. The framework automatically synchronizes with the Web Receiver volume for the supplied UI widgets. To sync a slider provided by the app, use GCKUIDeviceVolumeController .

Physical button volume control

The physical volume buttons on the sender device can be used to change the volume of the Cast session on the Web Receiver using the physicalVolumeButtonsWillControlDeviceVolume flag on the GCKCastOptions , which is set on the GCKCastContext .

Swift
 let 
  
 criteria 
  
 = 
  
 GCKDiscoveryCriteria 
 ( 
 applicationID 
 : 
  
 kReceiverAppID 
 ) 
 let 
  
 options 
  
 = 
  
 GCKCastOptions 
 ( 
 discoveryCriteria 
 : 
  
 criteria 
 ) 
 options 
 . 
 physicalVolumeButtonsWillControlDeviceVolume 
  
 = 
  
 true 
 GCKCastContext 
 . 
 setSharedInstanceWith 
 ( 
 options 
 ) 
Objective-C
 GCKDiscoveryCriteria 
  
 * 
 criteria 
  
 = 
  
 [[ 
 GCKDiscoveryCriteria 
  
 alloc 
 ] 
  
 initWithApplicationID 
 : 
 kReceiverAppID 
 ]; 
 GCKCastOptions 
  
 * 
 options 
  
 = 
  
 [[ 
 GCKCastOptions 
  
 alloc 
 ] 
  
 initWithDiscoveryCriteria 
  
 : 
 criteria 
 ]; 
 options 
 . 
 physicalVolumeButtonsWillControlDeviceVolume 
  
 = 
  
 YES 
 ; 
 [ 
 GCKCastContext 
  
 setSharedInstanceWithOptions 
 : 
 options 
 ]; 

Handle errors

It is very important for sender apps to handle all error callbacks and decide the best response for each stage of the Cast life cycle. The app can display error dialogs to the user or it can decide to end the Cast session.

Logging

GCKLogger is a singleton used for logging by the framework. Use the GCKLoggerDelegate to customize how you handle log messages.

Using the GCKLogger , the SDK produces logging output in the form of debug messages, errors, and warnings. These log messages aid debugging and are useful for troubleshooting and identifying problems. By default, the log output is suppressed, but by assigning a GCKLoggerDelegate , the sender app can receive these messages from the SDK and log them to the system console.

Swift
 @UIApplicationMain 
 class 
  
 AppDelegate 
 : 
  
 UIResponder 
 , 
  
 UIApplicationDelegate 
 , 
  
 GCKLoggerDelegate 
  
 { 
  
 let 
  
 kReceiverAppID 
  
 = 
  
 kGCKDefaultMediaReceiverApplicationID 
  
 let 
  
 kDebugLoggingEnabled 
  
 = 
  
 true 
  
 var 
  
 window 
 : 
  
 UIWindow 
 ? 
  
 func 
  
 applicationDidFinishLaunching 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 ) 
  
 { 
  
 ... 
  
 // Enable logger. 
  
 GCKLogger 
 . 
 sharedInstance 
 (). 
 delegate 
  
 = 
  
 self 
  
 ... 
  
 } 
  
 // MARK: - GCKLoggerDelegate 
  
 func 
  
 logMessage 
 ( 
 _ 
  
 message 
 : 
  
 String 
 , 
  
 at 
  
 level 
 : 
  
 GCKLoggerLevel 
 , 
  
 fromFunction 
  
 function 
 : 
  
 String 
 , 
  
 location 
 : 
  
 String 
 ) 
  
 { 
  
 if 
  
 ( 
 kDebugLoggingEnabled 
 ) 
  
 { 
  
 print 
 ( 
 function 
  
 + 
  
 " - " 
  
 + 
  
 message 
 ) 
  
 } 
  
 } 
 } 
Objective-C

AppDelegate.h

 @interface 
 AppDelegate 
  
 () 
  
< GCKLoggerDelegate 
> @end 

AppDelegate.m

 @implementation 
 AppDelegate 
 static 
  
 NSString 
  
 * 
 const 
  
 kReceiverAppID 
  
 = 
  
 @"AABBCCDD" 
 ; 
 static 
  
 const 
  
 BOOL 
  
 kDebugLoggingEnabled 
  
 = 
  
 YES 
 ; 
 - 
 ( 
 BOOL 
 ) 
 application: 
 ( 
 UIApplication 
  
 * 
 ) 
 application 
 didFinishLaunchingWithOptions 
 :( 
 NSDictionary 
  
 * 
 ) 
 launchOptions 
  
 { 
  
 ... 
  
 // Enable logger. 
  
 [ 
 GCKLogger 
  
 sharedInstance 
 ]. 
 delegate 
  
 = 
  
 self 
 ; 
  
 ... 
  
 return 
  
 YES 
 ; 
 } 
 ... 
 #pragma mark - GCKLoggerDelegate 
 - 
 ( 
 void 
 ) 
 logMessage: 
 ( 
 NSString 
  
 * 
 ) 
 message 
  
 atLevel 
 :( 
 GCKLoggerLevel 
 ) 
 level 
  
 fromFunction 
 :( 
 NSString 
  
 * 
 ) 
 function 
  
 location 
 :( 
 NSString 
  
 * 
 ) 
 location 
  
 { 
  
 if 
  
 ( 
 kDebugLoggingEnabled 
 ) 
  
 { 
  
 NSLog 
 ( 
 @"%@ - %@, %@" 
 , 
  
 function 
 , 
  
 message 
 , 
  
 location 
 ); 
  
 } 
 } 
 @end 

To enable debug and verbose messages as well, add this line to the code after setting the delegate (shown previously):

Swift
 let 
  
 filter 
  
 = 
  
 GCKLoggerFilter 
 . 
 init 
 () 
 filter 
 . 
 minimumLevel 
  
 = 
  
 GCKLoggerLevel 
 . 
 verbose 
 GCKLogger 
 . 
 sharedInstance 
 (). 
 filter 
  
 = 
  
 filter 
Objective-C
 GCKLoggerFilter 
  
 * 
 filter 
  
 = 
  
 [[ 
 GCKLoggerFilter 
  
 alloc 
 ] 
  
 init 
 ]; 
 [ 
 filter 
  
 setMinimumLevel 
 : 
 GCKLoggerLevelVerbose 
 ]; 
 [ 
 GCKLogger 
  
 sharedInstance 
 ]. 
 filter 
  
 = 
  
 filter 
 ; 

You can also filter the log messages produced by GCKLogger . Set the minimum logging level per class, for example:

Swift
 let 
  
 filter 
  
 = 
  
 GCKLoggerFilter 
 . 
 init 
 () 
 filter 
 . 
 setLoggingLevel 
 ( 
 GCKLoggerLevel 
 . 
 verbose 
 , 
  
 forClasses 
 : 
  
 [ 
 "GCKUICastButton" 
 , 
  
 "GCKUIImageCache" 
 , 
  
 "NSMutableDictionary" 
 ]) 
 GCKLogger 
 . 
 sharedInstance 
 (). 
 filter 
  
 = 
  
 filter 
Objective-C
 GCKLoggerFilter 
  
 * 
 filter 
  
 = 
  
 [[ 
 GCKLoggerFilter 
  
 alloc 
 ] 
  
 init 
 ]; 
 [ 
 filter 
  
 setLoggingLevel 
 : 
 GCKLoggerLevelVerbose 
  
 forClasses 
 : 
 @[ 
 @"GCKUICastButton" 
 , 
  
 @"GCKUIImageCache" 
 , 
  
 @"NSMutableDictionary" 
  
 ] 
 ]; 
 [ 
 GCKLogger 
  
 sharedInstance 
 ]. 
 filter 
  
 = 
  
 filter 
 ; 

The class names can be either literal names or glob patterns, for example, GCKUI\* and GCK\*Session .

Create a Mobile Website
View Site in Mobile | Classic
Share by: