问题
I am currently making a test app where you can draw and send pictures using multipeer connectivity. There is a connection view controller for the host and a separate one for the other peers. When peers have connected the host will play the game and all the peer's view controllers will go to the drawing VC proving they are connected. However, when I want to send data in the drawing VC, the console says the connected peers the session is 0 even though there are connected peers. I can test that because when the disconnect I get the change state notice in the console. So can someone please show me what is wrong with my code? Thanks.
Ps I am fairly new to iOS development so my code may have some major problems.
Connection Manager File:
import UIKit
import MultipeerConnectivity
class ConnectionManager: NSObject {
var localPeerId = MCPeerID(displayName: UIDevice.current.name)
var service = "PI-Connect"
var session: MCSession
var browser: MCNearbyServiceBrowser
var advertiser: MCAdvertiserAssistant
var connectionDelegate: ConnectionManagerDelegate?
var serviceDelegate: ServiceManagerDelegate?
var gameStarted : Bool
override init() {
self.session = MCSession(peer: self.localPeerId)
self.browser = MCNearbyServiceBrowser(peer: self.localPeerId, serviceType: service)
self.advertiser = MCAdvertiserAssistant(serviceType: service, discoveryInfo: nil, session: session)
gameStarted = false
super.init()
self.session.delegate = self
self.browser.delegate = self
self.advertiser.delegate = self
}
func startBrowsing() {
browser.startBrowsingForPeers()
}
func stopBrowsing() {
browser.stopBrowsingForPeers()
}
func startAdvertising() {
advertiser.start()
}
func stopAdvertising() {
advertiser.stop()
}
func startGame(gameStarted: String) {
NSLog("%@", "Start game: \(gameStarted) to \(session.connectedPeers.count) peers")
if session.connectedPeers.count > 0 {
do {
try session.send(gameStarted.data(using: .utf8)!, toPeers: session.connectedPeers, with: .reliable)
}
catch let error {
NSLog("%@", "Error for sending: \(error)")
}
}
}
func sendImage(imageData: Data) {
displayConnectedPeers()
NSLog("%@", "Attempting to send image to \(session.connectedPeers.count) peers")
if session.connectedPeers.count > 0 {
do {
try session.send(imageData, toPeers: session.connectedPeers, with: .reliable)
NSLog("%@", "Image sent")
}
catch let error {
NSLog("%@", "Error for sending image: \(error)")
}
}
}
func displayConnectedPeers() {
NSLog("%@", "Connected peers: \(session.connectedPeers.count)")
}
}
extension ConnectionManager: MCNearbyServiceBrowserDelegate {
func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
NSLog("%@", "didNotStartBrowsingForPeers: \(error)")
}
func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
NSLog("%@", "foundPeer: \(peerID)")
NSLog("%@", "invitePeer: \(peerID)")
browser.invitePeer(peerID, to: session, withContext: nil, timeout: 10)
}
func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
NSLog("%@", "lostPeer: \(peerID)")
self.connectionDelegate?.foundHost(manager: self)
}
}
extension ConnectionManager: MCAdvertiserAssistantDelegate {
func advertiserAssistantDidDismissInvitation(_ advertiserAssistant: MCAdvertiserAssistant) {
NSLog("%@", "Peer dismissed connection")
}
func advertiserAssistantWillPresentInvitation(_ advertiserAssistant: MCAdvertiserAssistant) {
NSLog("%@", "Peer accepted connection")
}
}
extension ConnectionManager: MCSessionDelegate {
func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
NSLog("%@", "peer \(peerID) didChangeState: \(state)")
self.connectionDelegate?.foundHost(manager: self)
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
NSLog("%@", "didReceiveData: \(data)")
if gameStarted == false {
stopBrowsing()
self.connectionDelegate?.hostInitsGame(manager: self)
NSLog("%@", "Game Started")
gameStarted = true
}
if gameStarted == true {
self.serviceDelegate?.changeImage(manager: self, imageData: data)
}
}
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")
}
}
extension browsingForPeers : ConnectionManagerDelegate {
func foundHost(manager: ConnectionManager) {
OperationQueue.main.addOperation {
if self.connectionManager.session.connectedPeers.count > 0 {
self.header.text = "\(self.connectionManager.session.connectedPeers[0].displayName)'s game"
self.activityMonitor.alpha = 0
}
if self.connectionManager.session.connectedPeers.count == 0 {
self.header.text = "Searching for game"
self.activityMonitor.alpha = 1
}
}
}
func hostInitsGame(manager: ConnectionManager) {
OperationQueue.main.addOperation {
self.switchViewControllers(active: true)
}
}
}
extension ViewController : ServiceManagerDelegate {
func changeImage(manager: ConnectionManager, imageData: Data) {
self.imageView.image = nil
self.imageView.image = UIImage(data: imageData)
}
}
protocol ConnectionManagerDelegate {
func hostInitsGame(manager: ConnectionManager)
func foundHost(manager: ConnectionManager)
}
protocol ServiceManagerDelegate {
func changeImage(manager: ConnectionManager, imageData: Data)
}
Browser File
import UIKit
class browsingForPeers: UIViewController {
let connectionManager = ConnectionManager()
@IBOutlet weak var header: UITextField!
@IBOutlet weak var activityMonitor: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
connectionManager.connectionDelegate = self
connectionManager.startBrowsing()
// Constants().host = false
}
func switchViewControllers(active: Bool) {
if active == true {
performSegue(withIdentifier: "browsingToDrawing", sender: self)
}
}
}
The searching controller is the same as the browser except it advertises instead and sends the data when the play button is clicked.
And finally the drawing controller (This is the one with the problem, and I removed all the drawing code)
import UIKit
import MultipeerConnectivity
class ViewController: UIViewController {
var globalConstant: Constants?
let connectionManager = ConnectionManager()
@IBOutlet var imageView: UIImageView!
@IBOutlet weak var more: UIButton!
@IBOutlet weak var brushOptions: UIButton!
@IBOutlet weak var colorOptions: UIButton!
@IBOutlet weak var eraser: UIButton!
@IBOutlet weak var brushSml: UIButton!
@IBOutlet weak var brushMed: UIButton!
@IBOutlet weak var brushLrg: UIButton!
@IBOutlet weak var redButton: UIButton!
@IBOutlet weak var orangeButton: UIButton!
@IBOutlet weak var yellowButton: UIButton!
@IBOutlet weak var greenButton: UIButton!
@IBOutlet weak var lightBlueButton: UIButton!
@IBOutlet weak var blueButton: UIButton!
@IBOutlet weak var pinkButton: UIButton!
@IBOutlet weak var greyButton: UIButton!
@IBOutlet weak var blackButton: UIButton!
@IBOutlet weak var slider: UISlider!
var uiimage: UIImage!
var ciimage: CIImage!
var data: Data!
override var prefersStatusBarHidden: Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
connectionManager.serviceDelegate = connectionManager.connectionDelegate as! ServiceManagerDelegate?
NSLog("%@", "View loaded with \ (connectionManager.session.connectedPeers.count) peers") //Outputs 0
// connectionManager.session.disconnect()
// NSLog("%@", "Disconnected")
@IBAction func doneButtonClicked(_ sender: UIButton) {
imageView.isUserInteractionEnabled = false
uiimage = imageView.image
if uiimage != nil {
data = UIImagePNGRepresentation(uiimage)
connectionManager.sendImage(imageData: data)
imageView.image = nil
imageView.image = UIImage(data: data)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Sorry for the weird formatting Xcode copies in a weird way the doesn't keep tabbing. Thanks in advanced, Matt.
回答1:
I was creating a new instance of the class when I called it in the different classes. That is why all my values that had not been initialized were equal to nil. This is the way I fixed it...
let connectionManager = ConnectionManager()
this was creating a instance and not a reference.
to
var connectionManager: ConnectionManager?
this is creating a reference to the class that already exists.
The other thing I had to do was when I segue to another view controller, pass all the values forward.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationViewController = segue.destination as? ViewController {
destinationViewController.connectionManager = self.connectionManager
}
}
I hope this helps anyone else who is having this issue.
来源:https://stackoverflow.com/questions/42966582/swift-3-passing-variables-and-functions-between-view-controllers