iosswiftgamekit

Why doesn't GKVoiceChat transmit any audio in iOS?


My game has two UIViewControllers. The first one finds a match with the matchmakerViewController(didFindMatch:) method. Once the match is found, the player is taken to the second one.

The GKVoiceChat should be active in the second one. Though, I am currently setting it up in the first UIViewController. Is this the right approach? I can't find any way to do it in the second UIViewController, as I can't create a GKMatch variable wherever I want.

To add a GKVoiceChat, I use the following code:

func matchmakerViewController(viewController: GKMatchmakerViewController!,
    didFindMatch match: GKMatch!) {

        println("I found a match.")

       // Checking if the device has a microphone   
        if !GKVoiceChat.isVoIPAllowed() {
            return
        }

       // Creation of an audio session
       var audioSession:AVAudioSession = AVAudioSession.sharedInstance()
           audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: nil)
           audioSession.setActive(true, error: nil)

       // Setting up a voice channel
       let allChannel = match.voiceChatWithName("allChannel")
           allChannel.active = true
           allChannel.volume = 1.0        
           allChannel.start()

       // Redirect the player to a new UIViewController
        let storyboard = UIStoryboard(name: "Universal", bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("ViewController") as UIViewController
        self.dismissViewControllerAnimated(true, completion: nil)
        self.presentViewController(vc, animated: true, completion: nil)
}

What works


What doesn't


Solution

  • As mention in the comments, this looks like your allChannel object is being deallocated at the end of the method. I'm not sure what the purpose of your second view controller is, but I'd subclass UIViewController and create a property that you set and then check for, .e.g:

    class VoiceViewController: UIViewController {
        var voiceChat: GKVoiceChat?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            if let voiceChat = self.voiceChat {
                // Do something with your voiceChat property
            }
        }
    }
    

    Then, update your method to be:

    func matchmakerViewController(viewController: GKMatchmakerViewController!,
    didFindMatch match: GKMatch!) {
    
        println("I found a match.")
    
        // Checking if the device has a microphone
        if !GKVoiceChat.isVoIPAllowed() {
            return
        }
    
        // Creation of an audio session
        var error: NSError?
        var audioSession:AVAudioSession = AVAudioSession.sharedInstance()
        audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: &error)
        if let error = error {
            // Do something with the error, such as tell the user
            return
        }
    
        audioSession.setActive(true, error: &error)
        if let error = error {
            // Do something with the error, such as tell the user
            return
        }
    
        // Setting up a voice channel
        let allChannel = match.voiceChatWithName("allChannel")
        allChannel.active = true
        allChannel.volume = 1.0
        allChannel.start()
    
        // Redirect the player to a new UIViewController
        let storyboard = UIStoryboard(name: "Universal", bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("ViewController") as VoiceViewController
        vc.voiceChat = allChannel
        self.dismissViewControllerAnimated(true, completion: nil)
        self.presentViewController(vc, animated: true, completion: nil)
    }
    

    There's also a chance your issue is with your AVAudioSession, so I've also added error checking for that.

    If you choose to have the voice chat managed by the view controller your original method is in, so can do:

    var voiceChat: GKVoiceChat?
    
    func matchmakerViewController(viewController: GKMatchmakerViewController!,
    didFindMatch match: GKMatch!) {
    
        println("I found a match.")
    
        // Checking if the device has a microphone
        if !GKVoiceChat.isVoIPAllowed() {
            return
        }
    
        // Creation of an audio session
        var error: NSError?
        var audioSession:AVAudioSession = AVAudioSession.sharedInstance()
        audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, error: &error)
        if let error = error {
            // Do something with the error, such as tell the user
            return
        }
    
        audioSession.setActive(true, error: &error)
        if let error = error {
            // Do something with the error, such as tell the user
            return
        }
    
        // Setting up a voice channel
        let allChannel = match.voiceChatWithName("allChannel")
        allChannel.active = true
        allChannel.volume = 1.0
        allChannel.start()
        self.voiceChannel = allChannel
    
        // Redirect the player to a new UIViewController
        let storyboard = UIStoryboard(name: "Universal", bundle: nil)
        let vc = storyboard.instantiateViewControllerWithIdentifier("ViewController") as UIViewController
        self.dismissViewControllerAnimated(true, completion: nil)
        self.presentViewController(vc, animated: true, completion: nil)
    }