MultipeerConnectivity MCPeerID не соответствует Codable - PullRequest
0 голосов
/ 06 июня 2018

Я пишу простую программу чата P2P и до сих пор храню свойство displayName MCPeerID в виде строки в моей модели, чтобы определить, кому отправлять конкретное сообщение.При каждой операции отправки я выполняю поиск в массиве connectedPeers и копирую MCPeerID в список получателей всякий раз, когда displayName совпадает со строкой, которую я имею в моей модели.

Это может быть проблематично в случае, когда два партнера имеютодно и то же имяИ я также не удовлетворен тем, что выполняю поиск для каждой отправки.Поэтому я пытаюсь использовать MCPeerID непосредственно в моей модели.Тем не менее, Xcode жалуется, что MCPeerID не соответствует ни Кодируемым, ни Декодируемым, и я не уверен, как это исправить.

Моя модель представляет собой тему, в которой содержится список участников, а также журнал того, кто сказалкакие.Таким образом, я могу синхронизировать нового участника, когда он присоединяется, и обновлять существующих участников, когда добавляются новые сообщения.Моя модель выглядит примерно так:

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 Ответ

0 голосов
/ 10 августа 2018

Здесь, кажется, есть несколько проблем (p2p - сложная тема):

1. идентификация пользователей (бизнес-уровень),

Имя партнера MCPeerID (displayName:) не являетсяидентификатор пира, он просто нацелен на зрителя (например, на пользователей чата).Пункт 3) ниже показывает, как одноранговый узел может включать в себя другую информацию о пользователях при рекламе своего присутствия.

2. определение одноранговых узлов (сетевой уровень),

Framework (MC) создает для вас уникальный идентификатор однорангового узла и рекомендует повторно использовать приложение (т. Е. Сохранять и перезагружать) при его запуске.( MCPeerID - официальные документы - пример objetive-c с использованием хранилища NSUserDefaults 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. сериализация

Пример Apple в пункте 2) выше показывает, как сериализовать MCPeerID с помощью API UserDefaults.

Как правило, когда кто-то расширяет 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
}
...