我目前在解雇另一个警报控制器后出现延迟提示新警报控制器的问题。
我的情况如下:
使用MPC进行对等连接有两个角色:主服务器和从服务器。
理想情况:只有一个主人可用
但是,当设备之间没有连接时,每个设备都可以设置为Master
当两个主设备连接时,与理想情况会发生冲突。
因此,我想选举师父。
当两个设备都是Master的时候
现在已经连接,然后Master选举的警报控制器将在每个设备中提示。当其中一个设备选项卡“保持为主”按钮时,另一个设备将关闭选举警报控制器并提示“xxx保持为主”警报。
但是,我发现延迟解雇之前的警报控制器。
MainVC中的代码:
/* PARENT */
class User extends React.Component {
buttonClicked(page)
{
this.setState({ page }, () => console.log(`NEW STATE`, this.state));
}
render()
{
return (
<Toolbar buttonClicked={page => this.buttonClicked(page)}/>
)
}
}
/* CHILD */
class Toolbar extends React.Component {
render()
{
let page = 3;
return (
<button value={page} onClick={page=> this.props.buttonClicked(e.target.value)}>
{page}
</button>
)
}
}
MPCHandler中的代码:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(testing), name: NSNotification.Name(rawValue: "hasMaster"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(stayAsMaster), name: NSNotification.Name(rawValue: "StayAsMaster"), object: nil)
}
func testing(notification: Notification){
if(appDelegate.mpcHandler.checkNoOfPeersConnected()>0){
if self.appDelegate.masterSlaveDataController.checkHasMaster() && self.appDelegate.masterSlaveDataController.checkMaster(){
self.promptHasMaster()
}
else{
DispatchQueue.main.asyncAfter(deadline: .now()){
if self.appDelegate.masterSlaveDataController.checkHasMaster() && self.appDelegate.masterSlaveDataController.checkMaster(){
self.promptHasMaster()
}
}
}
}
}
func promptHasMaster(){//prompt Elect Master Alert Controller
let alertController = UIAlertController(title: "Elect Master", message: "There are more than one masters in the connection. One of you has to give up the master role and switch to slave!", preferredStyle: .alert)
let peerID = self.appDelegate.mpcHandler.session.myPeerID
let m = UIAlertAction(title: "Stay as Master", style: .default, handler: { (alert) in
self.appDelegate.mpcHandler.send(d: self.mToDictionary(peerID: peerID, action: "stayAsMaster")!)
})
let s = UIAlertAction(title: "Switch to Slave", style: .default, handler: { (alert) in
self.appDelegate.mpcHandler.send(d: self.mToDictionary(peerID: peerID, action: "switchToSlave")!)
})
alertController.addAction(m)
alertController.addAction(s)
self.present(alertController, animated: true, completion: nil)
}
//Create NSDictionary for sending peerID
func mToDictionary(peerID: MCPeerID, action: String) -> [NSDictionary]?{
var dict: [NSDictionary] = [["action" : action]]
let d = ["peerID" : peerID] as NSDictionary
dict.append(d)
return dict
}
func stayAsMaster(notification: Notification){
let peerId = NSDictionary(dictionary: notification.userInfo!)
print("stay as master", peerId.allValues)
if presentedViewController == nil {
let alertController = UIAlertController(title: String(describing: peerId.allValues) + " remains as Master", message: "", preferredStyle: .alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alertController.addAction(dismiss)
self.present(alertController, animated: true, completion: nil)
} else{
let alertController = UIAlertController(title: String(describing: peerId.allValues) + " remains as Master", message: "", preferredStyle: .alert)
let dismiss = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alertController.addAction(dismiss)
self.dismiss(animated: false) { () -> Void in
self.present(alertController, animated: true, completion: nil)
}
}
}
当我在一台设备的警报控制器中选中“保持为主”时,另一台设备的Xcode控制台立即打印func send(d: [NSDictionary]){
NSLog("%@", "Send data: \(d) to \(session.connectedPeers.count) peers")
if session.connectedPeers.count > 0{
do {
let data = NSKeyedArchiver.archivedData(withRootObject: d)
try self.session.send(data, toPeers: session.connectedPeers, with: .reliable)
} catch {
NSLog("%@", "Error for sending data: \(error)")
}
}
}
func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {
NSLog("%@", "didReceive: \(data)")
if var dict: [NSDictionary] = NSKeyedUnarchiver.unarchiveObject(with: data) as? [NSDictionary]{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let d = dict.removeFirst()
switch d.value(forKey: "action") as! String {
case "stayAsMaster":
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "StayAsMaster"), object: nil, userInfo: [peerID:dict.first!])
default: break
}
}
}
,但几秒钟后它会关闭当前的警报控制器。
有人有什么想法吗?感谢您提前提供任何帮助。
答案 0 :(得分:1)
我在您的代码中发现了一些潜在的问题,请尝试更改这些:
每当您在DispatchQueue.main.async
DispatchQueue.main.async {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "StayAsMaster"), object: nil, userInfo: [peerID:dict.first!])
}
请添加removeObserver
(或者您可能会在deinit
后崩溃):
deinit {
NotificationCenter.default.removeObserver(self)
}