Обновите данные в реальном времени до строки UITableview в swift - PullRequest
0 голосов
/ 09 мая 2018

У меня есть сервер websocket, который отправляет данные каждые две секунды в зависимости от моей подписки. Мне нужно обновить строку на основе таблицы. В настоящее время я использую Starscream модуль для реализации websocket. как обновить значение определенной строки каждые две секунды

import UIKit
import Starscream
struct Stocks: Codable {
    let changepercent: String
    let changeprice: String
    let close: String
    let currentprice: String
    let high: String
    let id: Int
    let low: String
    let name: String
    let `open`: String
    let type: String
    let instid: String
    let exchange: String
}
class ViewController: UIViewController, WebSocketDelegate,UITableViewDelegate,UITableViewDataSource {
    @IBOutlet weak var stocktableView: UITableView!

    var arrContacts = [Stocks]()
    var socket: WebSocket!

    override func viewDidLoad() {
        super.viewDidLoad()
       var request = URLRequest(url: URL(string: "ws://192.168.18.97:8080/sss/landingstream")!)
            //var request = URLRequest(url: URL(string: "ws://192.168.18.97:8080/Setrega/landingstream")!)
        request.timeoutInterval = 5
        socket = WebSocket(request: request)

        socket.delegate = self
        socket.connect()
    }

    // MARK: Websocket Delegate Methods.

    func websocketDidConnect(socket: WebSocketClient) {

        print("websocket is connected")
    }

    func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
        if let e = error as? WSError {
            print("websocket is disconnected: \(e.message)")
        } else if let e = error {
            print("websocket is disconnected: \(e.localizedDescription)")
        } else {
             print("websocket disconnected")
        }
    }

    func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
        print("Received text: \(text)")
        let decoder = JSONDecoder()
        do {
            let iexEvent: Stocks = try decoder.decode(Stocks.self, from: text.data(using: .utf8)!)

            DispatchQueue.main.async {

                self.stocktableView.reloadData()

            }
        } catch {
            print(error)
        }
    }

    func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
        print("Received data: \(data.count)")
    }

    // MARK: Write Text Action

    @IBAction func writeText(_ sender: UIBarButtonItem) {
        socket.write(string: "{\"requestType\": \"INSTRUMENT_PRICE\",\"topic\": \"SBIN\"}")

    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.arrContacts.count;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "StocksCell", for: indexPath)
        cell.textLabel?.text = arrContacts[indexPath.row].changeprice
        return cell
    }
    // MARK: Disconnect Action

    @IBAction func disconnect(_ sender: UIBarButtonItem) {
        if socket.isConnected {
            sender.title = "Connect"
            socket.disconnect()
        } else {
            sender.title = "Disconnect"
            socket.connect()
        }
    }

}

1 Ответ

0 голосов
/ 09 мая 2018

Вместо этого:

DispatchQueue.main.async {

    self.stocktableView.reloadData()
}

Попробуйте найти строки, которые были изменены с помощью этой функции:

final func indexesOfStocks(stocks:[Stocks]) -> [Int] {

    return stocks.reduce([]) { (currentResult, currentStocks) in

        if let currentStockIndex = self.arrContacts.index(where: { currentStocks.id == $0.id }) {

            return currentResult + [currentStockIndex]
        }
        return currentResult
    }
}

Обновить свойство arrContacts:

final func updateArrContacts(indexesOfStocksValue:[Int], iexEvents:[Stocks]) {

    for i in stride(from: 0, to: indexesOfStocksValue.count, by: 1) {

        self.arrContacts[indexesOfStocksValue[i]] = iexEvents[i]
    }
}

И перезагрузить строки только для элементов обновления:

final func updateRows(stocksIndexes:[Int]) {

    DispatchQueue.main.async {

        self.stocktableView.performBatchUpdates({

            let indexesToUpdate = stocksIndexes.reduce([], { (currentResult, currentStocksIndex) -> [IndexPath] in

                if currentStocksIndex < self.stocktableView.numberOfRows(inSection: 0) {

                    return currentResult + [IndexPath.init(row: currentStocksIndex, section: 0)]
                }
                return currentResult
            })
            self.stocktableView.reloadRows(at: indexesToUpdate, with: UITableViewRowAnimation.automatic)
        }) { (_) in

        }
    }
}

Теперь вы можете обновить строки с этим кодом:

let indexesOfStocksValue = self.indexesOfStocks(stocks: iexEvents) // iexEvents is an array of Stocks
self.updateArrContacts(indexesOfStocksValue: indexesOfStocksValue, iexEvents: iexEvents)
self.updateRows(stocksIndexes: indexesOfStocksValue)

Это решение основано на идее, что после websocketDidReceiveMessage: должны обновляться только существующие элементы в arrContacts. Новые элементы не будут добавлены и никакие элементы не будут удалены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...