MultipeerConnectivity MCPeerID 不符合 Codable
Posted
技术标签:
【中文标题】MultipeerConnectivity MCPeerID 不符合 Codable【英文标题】:MultipeerConnectivity MCPeerID does not conform to Codable 【发布时间】:2018-06-06 12:51:18 【问题描述】:我正在编写一个简单的 P2P 聊天程序,到目前为止,我一直将 MCPeerID 的 displayName
属性作为字符串存储在我的模型中,以确定将特定消息发送给谁。在每次发送操作中,只要 displayName 与模型中的字符串匹配,我就会搜索 connectedPeers
数组并将 MCPeerID 复制到接收者列表中。
这在两个对等点具有相同名称的情况下可能会出现问题。而且我对每次发送都执行搜索也不满意。所以我试图在我的模型中直接使用 MCPeerIDs。但是,Xcode 抱怨 MCPeerID 不符合 Encodable 和 Decodable,我不知道如何解决这个问题。
我的模型代表一个主题,该主题维护参与者列表以及谁说了什么的日志。因此,我可以在新参与者加入时同步新参与者,并在添加新消息时更新现有参与者。我的模型如下所示:
import Foundation
import MultipeerConnectivity
class Task : Codable
var uuidStr: String = UUID().uuidString
var topic : String
var history : [String] = []
var users : [MCPeerID] = []
...
private enum CodingKeys: String, CodingKey
case uuidStr
case topic
case history
case users
func encode(to encoder: Encoder) throws
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(uuidStr, forKey: .uuidStr)
try container.encode(topic, forKey: .topic)
try container.encode(history, forKey: .history)
try container.encode(users, forKey: .users)
...
(我没有展示标准的 init(),因为这不是问题所在。)
查看文档后,我看到一个带有签名 MCPeerID.init?(coder: NSCoder)
和 func encode(with: NSCoder)
的方法,但我不确定如何指定 NSCoder 参数。任何有关如何序列化 users
属性的帮助将不胜感激。
【问题讨论】:
这个你搞定了吗? 【参考方案1】:这里似乎有几个问题(p2p是一个复杂的主题):
1. 识别用户(业务层面),
对等点名称 MCPeerID(displayName: ) 不是对等点标识符,它只是针对人类观众(例如聊天室用户)。下面的第 3) 点显示了一种方式,即对等方在宣传其存在时如何包含其他用户信息。
2. 识别对等点(网络级别),
框架 (MC) 会为您创建一个唯一的对等 ID,并建议在应用启动时重复使用(即持久化和重新加载)应用 (MCPeerID - official docs - example objetive-c using NSUserDefaults storage api)。
3. 共享对等会话信息(会话级别)
在你的模型中,你正在序列化任务,很好(虽然没有提到什么格式,.xml、.plist、.json 等),但我不明白你为什么要序列化这些 MCPeerID? 连接中的每个对等点都应该重新使用自己的 peerID,并且,如果他们希望向潜在的对等点宣传额外的信息,他们可以提供一个字典,其中包含有关对等点对象背后的业务用户的信息,例如:
myAdvertiser = MCNearbyServiceAdvertiser(peer: reusableLocalPeerID, discoveryInfo: ["uuidStr" : "my-user-id-here"], serviceType: "my-tasks-app")
(MCNearbyServiceAdvertiser docs)。
4. 分离关注点(数据级)
我会将框架 (MC) 从业务模型 (Task, User ...) 中分离出来,如下所示:
class Task: Codable var users: [User] ...
class User: Codable uid:String ...
struct PeerRecord: var peer:MCPeerID, var user_id:String, var name:String ...
var foundPeers:[MCPeerID]
var connectedPeers:[String:PeerRecord] // e.g. ["a-user-id": PeerRecord(peer: ...)]
5. 序列化
上面第 2) 点的 Apple 示例显示了如何使用 UserDefaults api 序列化 MCPeerID。
通常,当扩展 Codable 时,还希望在应用程序的某处使用编码器(JSON、XML 等), 将相关对象传递给此编码器的 .encode(...) 方法,例如:
func storeTasks(tasksCodable:[Task]) -> Bool
if let encoded_in_data_format = try? JSONEncoder().encode(tasksCodable)
UserDefaults.standard.set(encoded_in_data_format, forKey: "tasks")
return true
return false
【讨论】:
以上是关于MultipeerConnectivity MCPeerID 不符合 Codable的主要内容,如果未能解决你的问题,请参考以下文章
iOS 和 Windows 之间的 MultipeerConnectivity
如何创建用于 MultiPeerConnectivity 的 SecIdentityRef?