为啥 GKVoiceChat 在 iOS 中不传输任何音频?

Posted

技术标签:

【中文标题】为啥 GKVoiceChat 在 iOS 中不传输任何音频?【英文标题】:Why doesn't GKVoiceChat transmit any audio in iOS?为什么 GKVoiceChat 在 iOS 中不传输任何音频? 【发布时间】:2015-03-08 20:04:35 【问题描述】:

我的游戏有两个UIViewControllers。第一个使用matchmakerViewController(didFindMatch:) 方法找到匹配项。一旦找到匹配项,玩家将被带到第二个匹配项。

GKVoiceChat 应该在第二个中处于活动状态。不过,我目前正在第一个 UIViewController 中设置它。这是正确的方法吗?我在第二个UIViewController 中找不到任何方法,因为我无法在任何我想要的地方创建GKMatch 变量。

要添加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 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)

什么有效

游戏成功请求使用麦克风的权限; 代码编译得很好。不会发生崩溃或错误。 游戏成功认证用户,并重定向到第二个UIViewController

什么没有

没有声音传输 我听不到任何声音。为什么会这样?

【问题讨论】:

可能“allChannel”在您创建后立即自动发布。考虑到创建的通道是一个自动释放的对象(请参阅文档),并且您将它存储在函数本地的 allChannel 变量中,因此当函数退出时它会立即自动释放。您应该将其存储在实例属性中或将其传递给实例化的视图控制器,以便在某处保持强引用。最后,您将忽略 audioSession 函数返回的错误消息。您确定他们在配置音频会话时没有返回错误吗? 【参考方案1】:

正如 cmets 中提到的,这看起来像您的 allChannel 对象在方法结束时被释放。我不确定你的第二个视图控制器的目的是什么,但我会继承 UIViewController 并创建一个你设置然后检查的属性,例如:

class VoiceViewController: UIViewController 
    var voiceChat: GKVoiceChat?

    override func viewDidLoad() 
        super.viewDidLoad()
        if let voiceChat = self.voiceChat 
            // Do something with your voiceChat property
        
    

然后,将您的方法更新为:

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)

您的问题也可能与您的 AVAudioSession 有关,因此我还为此添加了错误检查。

如果您选择让原始方法所在的视图控制器管理语音聊天,那么可以这样做:

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)

【讨论】:

非常感谢您回答我的问题!我在第一个UIViewController 中实现了第二组代码并更新了matchmakerViewController(didFindMatch:) 方法。但是,如果二等舱是UIViewController,为什么还要放VoiceViewController?这将返回错误Use of undeclared type 'VoiceViewController'。再次感谢! 正如我提到的,我不知道那个视图控制器是做什么的,所以我添加了voiceChat 属性。您可以使用 matchmakerViewController 函数将该属性添加到视图控制器并设置该属性 感谢您的评论。第二个UIViewController 处理游戏本身并使用GKVoiceChat。顺便说一句,文档提到:“在 iOS 游戏中,在您可以使用语音聊天之前,您的游戏必须配置一个允许播放和录制的音频会话 (kAudioSessionCategory_PlayAndRecord)”所以我认为创建一个 AVAudioSession 是必要的。无论如何,再次感谢您的帮助。 我刚刚找到了那个注释,所以我从问题中删除了我对它的提及。我还更新了我的答案一个不使用新 VoiceViewController 类的示例 self.voiceChannel = allChannel 返回错误:'Home' does not have a member named 'voiceChannel',其中Home 是第一个UIViewController。因此,我从self.voiceChannel 中删除了self,错误为:Use of unresolved identifier 'voiceChannel'。所以我猜你的意思是self.voiceChat = allChannel 而不是self.voiceChannel = allChannel?谢谢!

以上是关于为啥 GKVoiceChat 在 iOS 中不传输任何音频?的主要内容,如果未能解决你的问题,请参考以下文章

IOS GKVoiceChat iphone

为啥 heightForHeaderInSection 在 iOS 4.3 中不起作用?

为啥 XML 存储在 iOS 中不可用?

为啥 GlutPostRedisplay 和 sleep 功能在此代码中不起作用?

为啥 jscript 在 iOS 7 的 Chrome 浏览器中不起作用?

为啥具有 ISO 8601 值的日期时间字段在 iOS webkit 浏览器中不起作用?