【问题标题】:Multipeer Connectivity not working after Xcode 11 updateXcode 11 更新后多点连接不起作用
【发布时间】:2020-02-22 02:34:35
【问题描述】:

我正在尝试构建一个基本应用程序,以使用 Multipeer Connectivity Framework 在附近的 iOS 设备之间发送消息。我尝试了很多教程,但似乎在 Xcode 11 中浏览附近的设备并接受请求并不能像以前那样工作。

这是我的视图控制器和委托方法:

import UIKit
import MultipeerConnectivity

class ViewController: UIViewController,MCSessionDelegate,MCBrowserViewControllerDelegate {

var peerID: MCPeerID?
var session: MCSession?

override func viewDidLoad() {
   super.viewDidLoad()
   peerID = MCPeerID(displayName: UIDevice.current.name)
   session = MCSession(peer: peerID!, securityIdentity: nil, encryptionPreference: .none)
   session!.delegate = self
}

func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
    switch state {
    case .connected: print("Connected to \(peerID.displayName)")
    case .connecting: print("Connecting: \(peerID.displayName)")
    case .notConnected: print("Not Connected: \(peerID.displayName)")
    default: print("")
    }
}

func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {

}

func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {

}

func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {

}

func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {

}

func browserViewControllerDidFinish(_ browserViewController: MCBrowserViewController) {
    browserViewController.dismiss(animated: true, completion: nil)
}

func browserViewControllerWasCancelled(_ browserViewController: MCBrowserViewController) {
    browserViewController.dismiss(animated: true, completion: nil)
}

}

我在 UI 中添加了 2 个按钮,一个用于托管,另一个用于加入。方法如下:

@IBAction func hostBtnTapped(_ sender: Any) {
    hostSession()
}

@IBAction func joinBtnTapped(_ sender: Any) {
    joinSession()
}

他们打电话:

func hostSession() {
    let advertiser = MCAdvertiserAssistant(serviceType: "mg-testing", discoveryInfo: nil, session: session!)
    advertiser.start()
}
func joinSession() {
    let browser = MCBrowserViewController(serviceType: "mg-testing", session: session!)
    browser.delegate = self
    self.present(browser, animated: true, completion: nil)
}

当我编译并运行它时,一切看起来都很好。我在我的第一台设备中单击“主机”并在我的第二台设备中进入“加入”模式(MCBrowserViewController 出现),但加入设备从未检测到托管设备。控制台没有输出,也没有错误。加入设备的“正在搜索...”指示器会永远转动,附近不会出现任何设备。这可能是什么原因造成的?我该如何解决?我正在使用 Xcode 11.0 和 iOS 12 & 13。

【问题讨论】:

    标签: ios swift multipeer-connectivity


    【解决方案1】:

    MCAdvertiserAssistantMCBrowserViewController 似乎没有针对最新版本的 iOS 和 Swift 进行更新,因此它们无法正常工作。

    我通过使用MCNearbyServiceAdvertiser 而不是MCAdvertiserAssistantMCNearbyServiceBrowser 而不是MCBrowserViewController 解决了这个问题。请注意,通过使用这些类,您需要自己执行基本操作,例如列出已建立的设备、显示和处理邀请警报等。

    您可以按如下方式使用这些类。

    定义:

     var advertiser: MCNearbyServiceAdvertiser!
     var browser: MCNearbyServiceBrowser!
    

    初始化:

    advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: "my-test")
    browser = MCNearbyServiceBrowser(peer: peerID, serviceType: "my-test")
    

    分配代表和开始:

    advertiser.delegate = self
    advertiser.startAdvertisingPeer()
    browser.delegate = self
    browser.startBrowsingForPeers()
    

    【讨论】:

    • 是的,最新的 Xcode 11.5 中存在 MCAdvertiserAssistant 的问题。使用 MCNearbyServiceAdvertiser 解决了我的问题。谢谢!
    • 您是否为此提交了错误报告?
    【解决方案2】:

    根据前任的回答,最大的问题似乎是MCAdvertiserAssistantMCBrowserViewController 对我来说很好。

    如果您的代码应该基于MCAdvertiserAssistantMCBrowserViewController 运行,请尝试将MCAdvertiserAssistant 替换为MCNearbyServiceAdvertiser

    所以这就是你所需要的一切,例如,如果你在 Paul Hudson 的 Swift 100 天内参与 Project 25。 (当我必须找到问题的解决方案时,我只是这样做了)

    var advertiser: MCNearbyServiceAdvertiser!
    advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: "my-test")
    advertiser.delegate = self
    advertiser.startAdvertisingPeer()
    

    MCNearbyServiceAdvertiserDelegate 添加到您的协议列表并实现委托方法:

    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
            invitationHandler(true, mcSession)
        }
    

    这只会接受每个连接,但也足够了,它应该可以工作。

    进一步调查:新的 Xcode 模板和 info.plist 中的新 UIApplicationSceneManifest 以及用于多窗口支持的新 SceneDelegate 似乎存在问题。

    当我将其更改为旧的 info plist 和 AppDelegate 系统时,MCAdvertiserAssistant 即使使用新的 Xcode 和 Swift 也能正常工作。

    ps。基于最新的 Xcode 11.2 Beta 2

    【讨论】:

    • 关于清单的最后一部分让我免于头痛!
    • 保留指向 var 广告商的指针似乎也很重要(不要在 func 中声明)。
    • 您的出色解决方案对我有用。我正在为我的 iPhone 7 使用最新的 Xcode 11.5,以及最新的模拟器和 iOS 版本。
    【解决方案3】:

    此问题是由 UISceneDelegate 引起的。在您选择退出 UISceneDelegate 并重建您的项目之后,应该会很好。

    有关如何退出 UISceneDelegate 的更多信息,请查看帖子: Xcode 11 - Opt out of UISceneDelegate/SwiftUI on iOS 13

    【讨论】:

      【解决方案4】:

      对于 Xcode 12 和 iOS 14:

      也来自 hackingwithSwift 项目 25,我花了 2 个小时来比较代码:( 最终,我认为这是 Xcode 版本或 iOS 版本的问题。

      要修复它,首先将MCAdvertiserAssistant 替换为MCNearbyServiceAdvertiser

      改变startHosting方法如下:

          func startHosting(action: UIAlertAction) {
              advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: "hws-project25")
              advertiser.delegate = self
              advertiser.startAdvertisingPeer()
          }
      

      并实现这个新方法:我添加了一个 alertViewController 来显示授权提示,因为当我们进行上述更改时它不会出现。

          func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
              let ac = UIAlertController(title: "Project25", message: "'\(peerID.displayName)' wants to connect", preferredStyle: .alert)
              ac.addAction(UIAlertAction(title: "Accept", style: .default, handler: { [weak self] _ in
                  invitationHandler(true, self?.mcSession)
              }))
              ac.addAction(UIAlertAction(title: "Decline", style: .cancel, handler: { _ in
                  invitationHandler(false, nil)
              }))
              present(ac, animated: true)
          }
      

      还有一件事:

      对于 iOS 14,如果你想使用多点连接,你还需要在 info.plist 中添加这两个属性。

      1. 隐私 - 本地网络使用说明:“您的消息”
      2. Bonjour 服务:_yourServiceTypeName._tcp

      【讨论】:

      • 我在加入会话时无法搜索设备。注意:我已经从真机启动主机并从模拟器加入。
      • Bonjour services: _yourServiceTypeName _.tcp" ,我认为这个格式正确。忽略 _yourServiceTypeName 和 _.tcp 之间的空格
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      相关资源
      最近更新 更多