通过多个视图控制器实现多对等连接

时间:2018-09-30 19:33:59

标签: swift class multipeer-connectivity

我想做的是拥有多个视图控制器,其中一个通过多点连接将您与另一台设备连接起来。然后,我希望用户能够切换视图控制器并保持该连接。我对此进行了一些研究,发现我需要做一个自定义类并在那里做所有的multipeer事情。我找到了一个示例项目来说明这一点,但是只有一个问题,如果代码不在视图控制器中,我该如何制作MCBrowserViewController。

这是自定义类的代码:

import Foundation
import MultipeerConnectivity

protocol ColorServiceDelegate {

    func connectedDevicesChanged(manager : ColorService, connectedDevices: [String])
    func colorChanged(manager : ColorService, colorString: String)

}

class ColorService : NSObject {

    // Service type must be a unique string, at most 15 characters long
    // and can contain only ASCII lowercase letters, numbers and hyphens.
    private let ColorServiceType = "example-color"

    private let myPeerId = MCPeerID(displayName: UIDevice.current.name)
    private let serviceAdvertiser : MCNearbyServiceAdvertiser
    private let serviceBrowser : MCBrowserViewController

    var delegate : ColorServiceDelegate?

    lazy var session : MCSession = {
        let session = MCSession(peer: self.myPeerId, securityIdentity: nil, encryptionPreference: .required)
        session.delegate = self
        return session
    }()

    override init() {
        self.serviceAdvertiser = MCNearbyServiceAdvertiser(peer: myPeerId, discoveryInfo: nil, serviceType: ColorServiceType)
        self.serviceBrowser = MCBrowserViewController(peer: myPeerId, serviceType: ColorServiceType)

        super.init()

        self.serviceAdvertiser.delegate = self
        self.serviceAdvertiser.startAdvertisingPeer()


    }

    deinit {
        self.serviceAdvertiser.stopAdvertisingPeer()
        self.serviceBrowser.stopBrowsingForPeers()
    }

    func send(colorName : String) {
        NSLog("%@", "sendColor: \(colorName) to \(session.connectedPeers.count) peers")

        if session.connectedPeers.count > 0 {
            do {
                try self.session.send(colorName.data(using: .utf8)!, toPeers: session.connectedPeers, with: .reliable)
            }
            catch let error {
                NSLog("%@", "Error for sending: \(error)")
            }
        }

    }

}

extension ColorService : MCNearbyServiceAdvertiserDelegate {

    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {
        NSLog("%@", "didNotStartAdvertisingPeer: \(error)")
    }

    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
        NSLog("%@", "didReceiveInvitationFromPeer \(peerID)")
        invitationHandler(true, self.session)
    }

}

extension ColorService : MCNearbyServiceBrowserDelegate {

    func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
        NSLog("%@", "didNotStartBrowsingForPeers: \(error)")


    }
    // This is what pairs:
    func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
        NSLog("%@", "foundPeer: \(peerID)")
        NSLog("%@", "invitePeer: \(peerID)")
        browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: 10)
    }

    func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
        NSLog("%@", "lostPeer: \(peerID)")
    }

}

extension ColorService : MCSessionDelegate {

    func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
        switch state{
        case MCSessionState.connected:
            print("connected: \(peerID.displayName)")

        case MCSessionState.connecting:
            print("connecting: \(peerID.displayName)")
        case MCSessionState.notConnected:
            print("NotConnected: \(peerID.displayName)")

        }
    }

    func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
        let str = String(data: data, encoding: .utf8)!
        self.delegate?.colorChanged(manager: self, colorString: str)
    }

    func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {
        NSLog("%@", "didReceiveStream")
    }

    func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
        NSLog("%@", "didStartReceivingResourceWithName")
    }

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

    }

}

在声明MCBrowserViewController时我习惯的是:

let mcBrowser = MCBrowserViewController(serviceType: "doesnt-matter", session: self.mcSession)
mcBrowser.delegate = self
self.present(mcBrowser, animated: true, completion: nil)

但是我不知道如何从Viewcontroller外部做到这一点

1 个答案:

答案 0 :(得分:0)

您可以将import tkinter as tk image_data = ''' R0lGODdhyABkAKIAAAAAAP8mAP/7AP///wAAAAAAAAAAAAAAACH5BAkAAAQALAA AAADIAGQAAAP/KLrc/jDKSau9OOvNu/9gKI5kaZ5oqq5s675wLM90bd94ru987/ /AoHBILBqPyKRyyWw6n9CodEqtWq/YrHbL7Xq/4LB4TC6bz+i0es1uu9/wuHxOl wTu+Lx+z+8H6jZ+goOEg4AnhYmKi3yHHIyQkZGOE5KWl5CUCpicnYx1nqGihHCj pqd+a6irrHlnrbCwY7G0sl+1uKxeubyoXL3AplnBxMJWxciex8nMmFXN0JJU0dS ZUtXYiVPZ3ILb3eB63+Hk4+Tg5ufc6erY0+3Zz/Du8vPQV/bRw/nFv/zAu/7lAi Ow1qyCq14hFKVqobM3Dj/RiUhKE0U8miIUzIihNh3HEPo+toglsqTJkyhTqlzJs qXLlzBjypxJs6bNmzhz6tzJs6fPn0CDCh1KtKjRo0iTKlWZAAA7 ''' root = tk.Tk() image = tk.PhotoImage(data=image_data) label = tk.Button(root, image=image, text="Hello, world", compound="center") label.pack(padx=20, pady=20) root.mainloop() 设置为视图控制器类的属性。

此服务类并非旨在作为您共享的代码片段中的一个单例,在这里有意义的是为要显示的每个视图控制器实例化一个服务类。

要记住的一件事是:如果您要关闭视图控制器并重新呈现它们,那么您将拥有一个很强的引用(service)是其他类(也许是您正在显示的内容?),这样就不会取消对视图控制器的初始化并杀死您的会话。

如果您有更多信息,请告诉我是否有帮助,我可以编辑我的答案。