Init with Chromecast in Swift

2019-06-05 12:43发布

问题:

I recently started to work with Google Cast API in iOS and I'm trying to get it to work with Apple new programming language Swift. I used as a reference Google Sample apps at https://github.com/googlecast/CastHelloText-ios and the problem is when I start the emulator I get an error message called: "-[GCKDeviceManager init]: unrecognized selector sent to instance 0x7fcd7a52d340" I know that I forgot something, but what and where do I need to put it??

For making it easer to help me, here is my code.

class SettingsController: UIViewController, UITextFieldDelegate, GCKDeviceScannerListener, GCKDeviceManagerDelegate, GCKMediaControlChannelDelegate {

var deviceScanner : GCKDeviceScanner!
var deviceManager : GCKDeviceManager!
var mediaInformation : GCKMediaInformation!
var applicationMetadata : GCKApplicationMetadata!
var mediaControlChannel : GCKMediaControlChannelDelegate!
var selectedDevice : GCKDevice!
var textChannelVar : textChannel!
var chromecastButton : UIButton!
var btnImage : UIImage!
var btnImageSelected : UIImage!
var kReceiverAppID = "642B7ADB"

func chooseDevice() {
    if self.selectedDevice == nil {
        let alertController = UIAlertController(title: "Choose an device..", message: "Tap on a prefered device", preferredStyle: .ActionSheet)

        for selectedDevice in self.deviceScanner.devices {
            alertController.addAction(UIAlertAction(title: selectedDevice.friendlyName, style: .Default, handler: { alertAction in
                self.connectToDevice()
            }))
        }

        alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: { AlertAction in
            alertController.dismissViewControllerAnimated(true, completion: nil)
        }))

        self.presentViewController(alertController, animated: true, completion: { () -> Void in
            if self.selectedDevice != nil {
                self.connectToDevice()
            }
        })
    }
    else {
        self.updateButtonStates()

        self.mediaInformation.metadata.stringForKey(kGCKMetadataKeyTitle)

        var alertController =  UIAlertController(title: "Casting to: \(self.selectedDevice.friendlyName)", message: nil, preferredStyle: UIAlertControllerStyle.ActionSheet)
        alertController.addAction(UIAlertAction(title: "Disconnect", style: .Default, handler: { alertAction in
            println("de waarde van self.mediaInformation is : \(self.mediaInformation)")
            if self.mediaInformation != nil {
                println("else uiactionsheet")
                (self.mediaInformation != nil ? 1 : 0)
                alertController.dismissViewControllerAnimated(true, completion: nil)
            }
        }))
        alertController.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: { alertAction in
            if self.mediaInformation != nil {
                println("else uiactionsheet")
                (self.mediaInformation != nil ? 2 : 1)
                alertController.dismissViewControllerAnimated(true, completion: nil)
            }
        }))
        self.presentViewController(alertController, animated: true, completion: nil)
    }
}

func isConnected() -> Bool {
    return self.deviceManager.isConnected
}

func connectToDevice() {
    if self.selectedDevice == nil {
        self.deviceManager = GCKDeviceManager(device: self.selectedDevice, clientPackageName:"CFBundleIdentifier")
        self.deviceManager.delegate = self
        self.deviceManager.connect()
        return
    }
}

func deviceDisconnected() {
    self.deviceManager = nil
    self.selectedDevice = nil
    self.textChannelVar = nil
    NSLog("Device disconneted: \(self.selectedDevice.friendlyName)")
}

func updateButtonStates() {
    if (self.deviceScanner.devices.count == 0) {
        chromecastButton.setImage(btnImage, forState: .Normal)
        chromecastButton.hidden = true
    }
    else {
        chromecastButton.setImage(btnImage, forState: .Normal)
        chromecastButton.hidden = false
        if (self.deviceManager != nil) {
            if self.deviceManager.isConnected {
                chromecastButton.setImage(btnImageSelected, forState: .Normal)
            }
        }
        else {
            chromecastButton.setImage(btnImageSelected, forState: .Normal)
        }
    }
}

func deviceDidComeOnline(device: GCKDevice!) {
    NSLog("device found! \(device.friendlyName)")
    self.updateButtonStates()
}

func deviceDidGoOffline(device: GCKDevice!) {
    self.updateButtonStates()
}

func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
    if self.selectedDevice == nil {
        if buttonIndex < self.deviceScanner.devices.count {
            self.selectedDevice = self.deviceScanner.devices[buttonIndex] as GCKDevice
            NSLog("Selecting device: \(self.selectedDevice.friendlyName)")
            self.connectToDevice()
        }
    }
    else {
        if buttonIndex == 1 {
            NSLog("Disconnecting device: \(self.selectedDevice.friendlyName)")
            self.deviceManager.leaveApplication()
            self.deviceManager.disconnect()
            self.deviceDisconnected()
            self.updateButtonStates()
        }
        else if buttonIndex == 0 {
        }
    }
}

func deviceManagerDidConnect(deviceManager: GCKDeviceManager!) {
    NSLog("Connected!")

    self.updateButtonStates()

    self.deviceManager.launchApplication(kReceiverAppID)
}

func deviceManager(deviceManager: GCKDeviceManager!, didConnectToCastApplication applicationMetadata: GCKApplicationMetadata!, sessionID: String!, launchedApplication: Bool) {
    NSLog("application has launched \(launchedApplication)")

}

func deviceManager(deviceManager: GCKDeviceManager!, didFailToConnectToApplicationWithError error: NSError!) {
    self.showError(error)

    self.deviceDisconnected()
    self.updateButtonStates()
}

func deviceManager(deviceManager: GCKDeviceManager!, didFailToConnectWithError error: NSError!) {
    self.showError(error)

    self.deviceDisconnected()
    self.updateButtonStates()
}

func deviceManager(deviceManager: GCKDeviceManager!, didDisconnectWithError error: NSError!) {
    NSLog("Received notification that device disconnected")

    if error != nil {
        self.showError(error)
    }

    self.deviceDisconnected()
    self.updateButtonStates()
}

func showError(error: NSError) {
    var alert = UIAlertController(title: "Something went wrong", message: error.description, preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
    self.presentViewController(alert, animated: true, completion: nil)
}

override func viewDidLoad() {
    super.viewDidLoad()

    kReceiverAppID = kGCKMediaDefaultReceiverApplicationID

    btnImage = UIImage(named: "icon-cast-identified.png")
    btnImageSelected = UIImage(named: "icon-cast-connected")

    self.chromecastButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
    self.chromecastButton.addTarget(self, action: "chooseDevice", forControlEvents: .TouchDown)
    self.chromecastButton.frame = CGRectMake(0, 0, 39, 34)
    self.chromecastButton.setImage(nil, forState: .Normal)
    self.chromecastButton.hidden = true


    self.deviceScanner = GCKDeviceScanner()
    self.deviceScanner.addListener(self)
    self.deviceScanner.startScan()

    self.view.addSubview(self.chromecastButton)
}

What my main goal is to show a webpage on the big screen, what we normally see in an webview. Sorry for the long code. If you need more info for helping me, don't hesitate to ask. Thank you!

回答1:

I haven't used this library, but in the link you provide they're initializing the GCKDeviceManager like this:

self.deviceManager =
  [[GCKDeviceManager alloc] initWithDevice:self.selectedDevice
                         clientPackageName:[info objectForKey:@"CFBundleIdentifier"]];

This should translate into this swift code:

self.deviceManager = GCKDeviceManager(self.selectedDevice, clientPackageName:info["CFBundleIdentifier"])

This means your code that looks like this is invalid (or at least the GCKDeviceManager init):

var deviceScanner = GCKDeviceScanner()
var deviceManager = GCKDeviceManager()
var mediaInformation = GCKMediaInformation()
var selectedDevice = GCKDevice()

You should change it to look like this instead:

var deviceScanner : GCKDeviceScanner!
var deviceManager : GCKDeviceManager!
var mediaInformation : GCKMediaInformation!
var selectedDevice : GCKDevice!

You'll need to ensure these values are assigned to before accessing them or it'll crash. Otherwise, you can switch the types to be optionals.