Загрузка определенных json message_ids в соответствии с выбранным indexPath - PullRequest
3 голосов
/ 14 апреля 2019

Цель:
Когда я выбираю сообщение из списка сообщений чата в MessageListController с didSelectRowAt, я хочу, чтобы открытый сеанс чата в следующем ChatDetailController соответствовал тому же разговору, который был выбран. Очевидно.

Я работаю с WatchKit, но в этом образе iOS то же самое. Сообщение с Софией будет выбрано, и откроется чат с Софией. enter image description here
Я хочу передать json "message_id", то есть свойство chatMessageId из моей модели. Я уже передаю chatMessageId из MessageModel в ChatDetailController с этой строкой presentController(withName: "ChatDetailController", context: messageContext)

Вот распечатка переданных данных с использованием messageContext.

Пропущенный контекст: Необязательный (HTWatch_Extension.MessageModel (партнер: "9859", псевдоним: "Marco", сообщение: "Вы видели собаку?", Город: "Мадрид", countryBadgeImageURL: https://i.imgur.com/PJcyle7.jpg, messageListImageURL : https://i.imgur.com/PJcyle7.jpg, chatMessageId: "Tva9d2OJyWHRC1AqEfKjclRwXnlRDQ", статус: "offline"))

Какой следующий шаг? Как мне сказать ChatDetailController заполнить его таблицу разговором, который соответствует выбранной строке?

MessageListController

// ...code...

let messageObject = [MessageModel]()
//var chatObject = [ChatModel]()

// ...code...

override func table(_ table: WKInterfaceTable, didSelectRowAt rowIndex: Int) {

    var messageContext = messageObject[rowIndex]
    var chatContext = chatObject[rowIndex]

    do {
        guard let fileUrl = Bundle.main.url(forResource: "Chats", withExtension: "json") else {
            print("File could not be located")
            return
        }
        let data = try Data(contentsOf: fileUrl)
        let decoder = JSONDecoder()

        let msg = try decoder.decode([ChatModel].self, from: data)
        self.chatObject = msg

    } catch let error {
        print(error)
    }

    // I got part of this line from a previous question, but these property types do not match.
    // No matter what chatObject I create I cannot access it/assign it. 
    // Also I do not want to mutate messageContext which Xcode is telling me to do.
    messageContext.chatMessageId = (chatObject as AnyObject).filter { (dictionaryTemp:[String:String]) -> Bool in
        return dictionaryTemp["message_id"] == chatContext.chatMessageId
    } 

    // WatchKit's model presentation method.
    presentController(withName: "ChatDetailController", context: messageContext)
}

ChatDetailController

var chats: [ChatModel] = []

    var messageModel: MessageModel? {
        didSet {
            guard let model = messageModel else { return }             
            partnerLabel.setText(model.nickname)             
        }
    }

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        if let message = context as? MessageModel {

            self.messageModel = message
            print("Passed context: \(String(describing: messageModel))")
        } else {
            print("Passed context error: \(String(describing: context))")
        }

        do {
            guard let fileUrl = Bundle.main.url(forResource: "Chats", withExtension: "json") else {
                print("File could not be located")
                return
            }
            let data = try Data(contentsOf: fileUrl)
            let decoder = JSONDecoder()

            let msg = try decoder.decode([ChatModel].self, from: data)
            self.chats = msg

        } catch let error {
            print(error)
        }

        DispatchQueue.main.async(execute: {

            self.setupTable(chatMessageArray: self.chats as [AnyObject])
        })      
    }

ChatModel

public struct ChatModel: Codable {
// ... other properties
public var chatMessageId: String

enum CodingKeys: String, CodingKey {
    // ... other cases
    case chatMessageId = "message_id"
}

init (message:String , fromId:String, toID : String, imgUrl : URL?, chatMessageId : String) {
    // ... other properties
    self.chatMessageId = chatMessageId
   }    
  }
 // .... decoders etc
}

MessageModel

public struct MessageModel: Codable {
    // ...
    public var chatMessageId: String

enum CodingKeys: String, CodingKey {
    // ... other cases
    case chatMessageId = "message_id"
}
// ... init/decoders etc
}

Messages.json

[
  {
    "userid": "4444",
    "nickname": "Marco",
    "online_status": "offline",
    "message": "Have you seen his dog?",
    "city": "Madrid",
    "flag_url": "https://i.imgur.com/PJcyle7.jpg",
    "creationDate": "2016-02-22 15:18:40",
    "avatar_url": "https://i.imgur.com/PJcyle7.jpg",
    "message_id": "Tva9d2OJyWHRC1AqEfKjclRwXnlRDQ" // different id
  },
  {
      "userid": "12121",
      "nickname": "Tom",
      "online_status": "online",
      "message": "Where is the pizza shop?",
      "city": "Kyoto",
      "flag_url": "https://i.imgur.com/PJcyle7.jpg",
      "creationDate": "2016-02-22 15:18:40",
      "avatar_url": "https://i.imgur.com/PJcyle7.jpg",
      "message_id": "EnotMkk8REEd0DHGvUgnd45wBap80E" // different id
  }
]

Chats.json

2 разговора по 2 сообщения в каждом. Каждый разговор имеет уникальный fromId (партнер), toID (я) и уникальный message_id.

[
  {
    "fromId": "zz1234skjksmsjdfwe2zz",
    "toId": "qq43922sdkfjsfmmxdfqq",
    "messageText": "Have you seen is dog?",
    "imageUrl": "https://i.imgur.com/PJcyle7.jpg",
    "message_id": "Tva9d2OJyWHRC1AqEfKjclRwXnlRDQ", // conversation 1  - same message id as the 1st message in Messages.josn with nickname Marco.
    "read": "true"                                      
  },
  {
      "fromId": "zz1234skjksmsjdfwe2zz",
      "toId": "qq43922sdkfjsfmmxdfqq",
      "messageText": "Yes I have. It's cute.",
      "imageUrl": "https://i.imgur.com/PJcyle7.jpg",
      "message_id": "Tva9d2OJyWHRC1AqEfKjclRwXnlRDQ", // conversation 1
      "read": "true"
  },
  {
      "fromId": "bb888skjaaasjdfwe2333",
      "toId": "qq43922sdkfjsfmmxdfqq",
      "messageText": "What kind of pizza do you want?",
      "imageUrl": "https://i.imgur.com/PJcyle7.jpg",
      "message_id": "EnotMkk8REEd0DHGvUgnd45wBap80E", // conversation 2 - same message id as the 2nd message in Messages.josn with nickname Tom.
      "read": "true"
  },
  {
      "fromId": "bb888skjaaasjdfwe2333",
      "toId": "qq43922sdkfjsfmmxdfqq",
      "messageText": "I like ham & pineapple pizza.",
      "imageUrl": "https://i.imgur.com/PJcyle7.jpg",
      "message_id": "EnotMkk8REEd0DHGvUgnd45wBap80E", // conversation 2
      "read": "true"
  }
]

Ответы [ 2 ]

4 голосов
/ 23 апреля 2019
let msg = try decoder.decode([ChatModel].self, from: data)
self.chats = msg

Вы сохраняете все данные чата, содержащиеся в Chats.json, в chats свойстве.

Чтобы отфильтровать чаты, попробуйте заменить вторую строку, как показано ниже

self.chats = msg.filter { chat in
    return chat.chatMessageId == self.messageModel.chatMessageId
}

или, хотя я не знаю, почему все чаты содержатся в одном файле json, для каждого чата будет лучше разделить файл json на несколько файлов, например Chat-Tva9d2OJyWHRC1AqEfKjclRwXnlRDQ.json.

Надеюсь, это поможет.

1 голос
/ 30 апреля 2019

Ваш метод MessageListController didSelectRowAt должен быть таким простым.

 //MessageListController

    // ...code...

    let messageObject = [MessageModel]()
//    var chatObject = [ChatModel]()

    // ...code...

    override func table(_ table: WKInterfaceTable, didSelectRowAt rowIndex: Int) {

        //creating a context with the message object at selected row. 
        var messageContext = messageObject[rowIndex]
        // WatchKit's model presentation method. passing the context along.
        presentController(withName: "ChatDetailController", context: messageContext)

//        Rest of the codes not required in your MessageListController
    }

    // ...code...

Ваш MessageListController будет таким.

// ChatDetailController
    var chats: [ChatModel] = []

    var messageModel: MessageModel? {
        didSet {
            guard let model = messageModel else { return }
            partnerLabel.setText(model.nickname)
        }
    }

    override func awake(withContext context: Any?) {
        super.awake(withContext: context)

        if let message = context as? MessageModel {

            self.messageModel = message
            print("Passed context: \(String(describing: messageModel))")
        } else {
            print("Passed context error: \(String(describing: context))")
        }

        do {
            guard let fileUrl = Bundle.main.url(forResource: "Chats", withExtension: "json") else {
                print("File could not be located")
                return
            }
            let data = try Data(contentsOf: fileUrl)
            let decoder = JSONDecoder()

            //msg holds all chat messages in the file
            let msg = try decoder.decode([ChatModel].self, from: data)
            // We should filter the chats in the msg array with the selected message content
            self.chats = msg.filter({
                $0.chatMessageId == messageModel?.chatMessageId
            })

//            self.chats only holds the chats with chatMessageId

        } catch let error {
            print(error)
        }

        DispatchQueue.main.async(execute: {

            self.setupTable(chatMessageArray: self.chats as [AnyObject])
        })

Надеюсь, это решит вашу проблему. Happy Coding:)

...