SwiftUI:Кэширование строк при выводе List

swiftui

#1

Я получаю пост-запросом строку json, парсю её через Codable в массив структур (типа ассоциативного массива) и вывожу оператором List(), который принимает в качестве аргумента этот массив и выводит в цикле оператором Text(“строка”).

Так вот, парсятся данные нормально. Получается массив строк с полями (квартира, дата, описание)
Но при попытке вывести этот список при помощи List() видно, что для тех строк, в которых один и то же номер квартиры, выводятся и те же самые данные из первого элемента с этим номером квартиры.

Грубо говоря, в массиве строчки
квартира 111, дата 17.02.2020, описание “000”
квартира 123, дата 01.03.2020, описание “123”
квартира 123, дата 10.03.2020, описание “456”
квартира 123, дата 12.03.2020, описание “789”

а выводятся
квартира 111, дата 17.02.2020, описание “000”
квартира 123, дата 12.03.2020, описание “123”
квартира 123, дата 12.03.2020, описание “123”
квартира 123, дата 12.03.2020, описание “123”

Так вот, я хочу понять, куда копать. Где в выводе происходит кэширование при выводе строчек массива?
Вот код, если его запустить, покажет, что данные начинают кэшироваться, начиная с пятой строки массива:

import SwiftUI

import Combine

struct TestView: View {
@State var flag = false
@State private var edss = Edc2
@State private var datas = EdcData2

@State var cnt = 0

var body: some View {
            List(self.edss, id: \.kv ) { item in
                 VStack(alignment: .leading) {

                     Text(item.kv)
                    Text(item.data1)
                     Text( item.vid)
                     Text( item.ispol)
                    Text(item.data2)
                }
          } .onAppear {
                    self.getPost(0)
                }
}

func getPost(_ run:Int){

let json = “”"
{“data”:[{“val”:“24246”,“title”:“Июнь 2020”},{“val”:“24245”,“title”:“МАй 2020”},{“val”:“24244”,“title”:“Апрель 2020”},{“val”:“24243”,“title”:“Март 2020”}],“items”:[{“kv”:“57”,“data1”:“01.06.2020 16:42:28”,“vid”:“stroka 1”,“ispol”:“ispol 1”,“data2”:“02.06.2020 10:47:22”},{“kv”:“69”,“data1”:“01.06.2020 15:34:06”,“vid”:“stroka 2”,“ispol”:“ispol 1”,“data2”:""},{“kv”:“144”,“data1”:“05.06.2020 14:57:50”,“vid”:“stroka 3”,“ispol”:“ispol 2”,“data2”:""},{“kv”:“173”,“data1”:“09.06.2020 11:40:08”,“vid”:“stroka 4”,“ispol”:“ispolnitel 3”,“data2”:""},{“kv”:“179”,“data1”:“03.06.2020 18:09:10”,“vid”:“stroka 5”,“ispol”:“ispol 4”,“data2”:""},{“kv”:“179”,“data1”:“05.06.2020 10:05:31”,“vid”:“stroka 6”,“ispol”:“ispol 4”,“data2”:""},{“kv”:“208”,“data1”:“01.06.2020 12:33:33”,“vid”:“stroka 7”,“ispol”:“ispol 3”,“data2”:""},{“kv”:“208”,“data1”:“01.06.2020 15:22:35”,“vid”:“stroka 8”,“ispol”:“ispol 1”,“data2”:""},{“kv”:“208”,“data1”:“09.06.2020 12:11:56”,“vid”:“stroka 9”,“ispol”:“ispol 5”,“data2”:""},{“kv”:“245”,“data1”:“01.06.2020 11:33:21”,“vid”:“stroka 10”,“ispol”:“ispol 3”,“data2”:""},{“kv”:“245”,“data1”:“05.06.2020 14:24:27”,“vid”:“stroka 11”,“ispol”:“ispol 1”,“data2”:""}]}
“”".data(using: .utf8)!

            if  let decrez = try? JSONDecoder().decode(ItemArrayE2.self, from: json)
                 {
                    DispatchQueue.main.async {
                        self.datas = decrez.data!
                        self.edss = decrez.items!
                       
                  
                    }
               }
}

}

struct ItemArrayE2: Codable {

enum CodingKeys: String, CodingKey {
   case items
    case data
}

var data:[EdcData2]?
var items:[Edc2]?

init(from decoder: Decoder) throws {

  let container = try decoder.container(keyedBy: CodingKeys.self)
  self.data = try? container.decode([EdcData2].self, forKey: .data)
   self.items = try? container.decode([Edc2].self, forKey: .items)
}

}

struct EdcData2: Codable {
var title:String
var val:String

      init(from decoder: Decoder) throws {
        
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.title = try container.decode(String.self, forKey: .title)
        self.val = try container.decode(String.self, forKey: .val)

    }

}

struct Edc2: Codable {
var kv:String
var data1:String
var vid:String
var ispol:String
var data2:String

      init(from decoder: Decoder) throws {
        
        let container = try decoder.container(keyedBy: CodingKeys.self)

        self.kv = try container.decode(String.self, forKey: .kv)
        self.data1 = try container.decode(String.self, forKey: .data1)
        self.vid = try container.decode(String.self, forKey: .vid)
        self.ispol = try container.decode(String.self, forKey: .ispol)
        
        self.data2 = try container.decode(String.self, forKey: .data2)
        
       
        

    }

}

struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}


#2

Создайте отдельный ID для ваших квартир
Вы выставили для списка идентификатор номер квартиры, вот он и смотрит по первому элементу


#3

В сам массив json добавить уникальный идентификатор строки? Спасибо, попробую. :slight_smile:


#4

Нет, в вашу структуру.


#5

при парсинге в каждый объект добавляйте параметр
let id = UUID()

В List передавайте массив без указания по какому параметру пересчитывать - он сам поймёт, что надо. Если не получится, то конкретно укажите List(self.edss, id: \.id )


#6

Спасибо, всё получилось.