Почему SwiftUI загружает элементы в обратном порядке? - PullRequest
0 голосов
/ 27 апреля 2020

У меня потоковое приложение состоит из нескольких каналов, и у каждого канала есть видеорегистраторы. На главной странице все каналы отображаются в строках в соответствии с их категориями. А когда пользователь нажимает на элемент канала, он переходит на подробную страницу, которая содержит видеорегистраторы в горизонтально прокручиваемой строке. Все каналы и элементы DVR имеют изображения, и я загружаю изображения из URL с помощью библиотеки URLImage (https://github.com/dmytro-anokhin/url-image). Проблема в том, что когда я запускаю приложение, изображения каналов загружаются справа внизу вверх слева, то есть от последнего элемента к первому элементу. Когда я нажимаю на канал и перехожу к подробному экрану, изображения для видеорегистраторов начинают загружаться справа налево, то есть от последнего элемента к первому элементу. И это создает проблему, потому что каналы имеют слишком много данных DVR, и загрузка всех изображений занимает 5 секунд. Было бы замечательно, если бы он начал загружать изображения из первого элемента, поэтому даже если это займет 5 секунд, пользователь не поймет и не осуществит это.

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

    ForEach(1..<chan.getDVR().count, id: \.self){index in

       Button(action:
       {
           self.str = self.chan.getDVR()[index].getHlsStreamURL()
           self.refresh = false
           self.ind = index

       }) {
            dvrItem(DVRItem: self.chan.getDVR()[index])
                .buttonStyle(PlainButtonStyle())
                .padding(.trailing,3)
                .cornerRadius(7)

       }.buttonStyle(PlainButtonStyle())             
    }

и dvrItem:

struct dvrItem: View {

        var DVRItem: dvr

        var body: some View {
             VStack( alignment: .leading) {
                URLImage(URL(string: DVRItem.getLogoUrlHD().replacingOccurrences(of: "http", with: "https", options: .literal, range: nil))!,  placeholder: { _ in Image("nologo").resizable().aspectRatio(contentMode: .fill).clipped() } ){
                    proxy in
                    proxy.image
                        .resizable()                     // Make image resizable
                        .aspectRatio(contentMode: .fill) // Fill the frame
                        .clipped()                       // Clip overlaping parts
                }
                .frame(width: 198, height: 114)
                .cornerRadius(7)
                .padding(.leading, 10)
                .padding(.top, 5)
                Text(self.DVRItem.getName())
                    .foregroundColor(Color.white)
                    .padding(.leading, 5)
                    .padding(.trailing, 5)

                Text(self.DVRItem.getDescription())
                    .foregroundColor(Color(red: 80.0/150, green: 80.0/150, blue: 80.0/150))
                    .lineLimit(nil)
                    .padding(.leading, 5)
                    .padding(.trailing, 5)
                Spacer()
                    .frame(height: 5)

            }
        }
    }

    struct dvrItem_Previews: PreviewProvider {
        static var previews: some View {
            dvrItem(DVRItem: channels[0].getDVR()[0])
        }
    }

Что я делаю не так? Кстати, я пытался загрузить только первые 10 элементов DVR, например ForEach(1..<10, id: \.self){index in, но это дало ошибку во время выполнения.

1 Ответ

0 голосов
/ 06 мая 2020

После многих попыток я решил проблему с помощью опции библиотеки URLImage.

У URLImages есть опция задержки, которую можно использовать для задержки процесса загрузки изображения. И использование выглядит следующим образом:

    URLImage(URL(string: DVRItem.getLogoUrlHD().replacingOccurrences(of: "http", with: "https", options: .literal, range: nil))!, delay: 0.25,  placeholder: { _ in Image("nologo").resizable().aspectRatio(contentMode: .fill).clipped() } ){
        proxy in
        proxy.image
            .resizable()                     // Make image resizable
            .aspectRatio(contentMode: .fill) // Fill the frame
            .clipped()                       // Clip overlaping parts
    }

Я обновил свой DVRItem и добавил новую переменную с именем index:

    var ind: Int

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

struct dvrItem: View {

    var DVRItem: dvr
    var ind: Int

    var body: some View {
         VStack( alignment: .leading) {
            URLImage(URL(string: DVRItem.getLogoUrlHD().replacingOccurrences(of: "http", with: "https", options: .literal, range: nil))!, delay: (self.ind < 5) ? 0 : (self.ind < 20 ? 0.15 : 0.25),  placeholder: { _ in Image("nologo").resizable().aspectRatio(contentMode: .fill).clipped() } ){
                proxy in
                proxy.image
                    .resizable()                     // Make image resizable
                    .aspectRatio(contentMode: .fill) // Fill the frame
                    .clipped()                       // Clip overlaping parts
            }
            .frame(width: 198, height: 114)
            .cornerRadius(7)
            .padding(.leading, 10)
            .padding(.top, 5)
            Text(self.DVRItem.getName())
                .foregroundColor(Color.white)
                .padding(.leading, 5)
                .padding(.trailing, 5)

            Text(self.DVRItem.getDescription())
                .foregroundColor(Color(red: 80.0/150, green: 80.0/150, blue: 80.0/150))
                .lineLimit(nil)
                .padding(.leading, 5)
                .padding(.trailing, 5)
            Spacer()
                .frame(height: 5)

        }
    }
}

struct dvrItem_Previews: PreviewProvider {
    static var previews: some View {
        dvrItem(DVRItem: channels[0].getDVR()[0], ind: 0)
    }
}

И я вызываю DVRItem следующим образом и присваиваю ind значения индекса:

ForEach(1..<chan.getDVR().count, id: \.self){index in

   Button(action:
   {
       self.str = self.chan.getDVR()[index].getHlsStreamURL()
       self.refresh = false
       self.ind = index

   }) {
        dvrItem(DVRItem: self.chan.getDVR()[index], ind: index)
            .buttonStyle(PlainButtonStyle())
            .padding(.trailing,3)
            .cornerRadius(7)

   }.buttonStyle(PlainButtonStyle())             
}

Я до сих пор не знаю, почему он начинает загружаться из последнего пункта, но это решило мои проблемы. Я попробовал аналогичные решения, как в этом посте В SwiftUI, где находятся события управления, то есть scrollViewDidScroll для определения нижней части списка данных , но они не работают для горизонтальных прокруток.

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