SwiftUI NavigationLink выбранное значение сбрасывается на ноль - PullRequest
0 голосов
/ 27 марта 2020

У меня есть приложение SwiftUI watchOS, которое использует NavigationLink s для маршрутизации между несколькими представлениями. Я использую NavigationLink tag и selection параметры, чтобы иметь возможность контролировать, какой вид виден. В моем реальном приложении я хочу иметь возможность вернуться к представлению с индексом 0, когда пользователь запускает приложение из-за затруднений. Однако всякий раз, когда значение $selection отличается от nil или 0, а $selection устанавливается на 0 из моей модели представления, кратко отображается представление с индексом 0, затем $selection сбрасывается на nil с помощью SwiftUI (дважды ) без какого-либо вмешательства пользователя, вызывающего его.

Я создал пример приложения, демонстрирующего это поведение, с таймером, который приближает пользователя к запуску из-за сложности. Я сделал все, кроме значения выбора, константой, чтобы попытаться исключить разницу в качестве возможного источника.

Вот рисунок, демонстрирующий, что происходит:

A screen recording demonstrating this bug

import SwiftUI

struct Item: Identifiable {
    let id: Int
    let text: String
}

class ContentViewModel: ObservableObject {
    @Published public var selectedIndex: Int? {
        didSet {
            print("ContentViewModel selectedIndex = \(String(describing: selectedIndex))")
        }
    }
    public let items: [Item] = [
        Item(id: 0, text: "Zero"),
        Item(id: 1, text: "One"),
        Item(id: 2, text: "Two"),
        Item(id: 3, text: "Three"),
        Item(id: 4, text: "Four")
    ]

    private var timer: Timer?
    init() {
        self.timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { [unowned self] _ in
            print("ContentViewModel timer fired")
            self.selectedIndex = 0
        }
    }
}

struct ContentView: View {
    @ObservedObject private var viewModel = ContentViewModel()

    var body: some View {
        List(self.viewModel.items) { (item: Item) in
            NavigationLink(destination: Text(item.text), tag: item.id, selection: self.$viewModel.selectedIndex) {
                Text(item.text)
            }
        }
    }
}

Вот что вошло в консоль:

ContentViewModel selectedIndex = Optional(2)
ContentViewModel timer fired
ContentViewModel selectedIndex = Optional(0)
ContentViewModel selectedIndex = nil
ContentViewModel selectedIndex = nil
ContentViewModel selectedIndex = Optional(3)
ContentViewModel timer fired
ContentViewModel selectedIndex = Optional(0)
ContentViewModel selectedIndex = nil
ContentViewModel selectedIndex = nil

Я бы хотел любую помощь или указатели, которые вы можете предоставить!

Примечание: я бегу последние версии всего, Xcode 11.4, Swift 5.2, watchOS 6.2.

1 Ответ

1 голос
/ 27 марта 2020

Похоже, проблема связана только с watchOS, такого поведения на iOS не наблюдается. Стоит отправить отзыв в Apple.

Здесь возможен временный обходной путь. Протестировано с Xcode 11.4.

self.timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { [unowned self] _ in
    print("ContentViewModel timer fired")
    self.selectedIndex = nil                                   // << reset
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {    // postpone !!
        self.selectedIndex = 0                                 // << next
    }
}
...