Как я могу выполнить действие при изменении состояния? - PullRequest
2 голосов
/ 11 июня 2019
enum SectionType: String, CaseIterable {
    case top = "Top"
    case best = "Best"
}

struct ContentView : View {
    @State private var selection: Int = 0

    var body: some View {
        SegmentedControl(selection: $selection) {
            ForEach(SectionType.allCases.identified(by: \.self)) { type in
                Text(type.rawValue).tag(type)
            }
        }
    }
}

Как запустить код (например, print("Selection changed to \(selection)") при изменении состояния $selection? Я просмотрел документы и ничего не смог найти.

Ответы [ 2 ]

2 голосов
/ 13 июня 2019

В настоящее время вы не можете использовать didSet для @State, но вы можете использовать для BindableObject свойства.Мое решение состояло в том, чтобы создать BindableObject как это:

import SwiftUI
import Combine

final class SelectionStore: BindableObject {
    var didChange = PassthroughSubject<SelectionStore, Never>()

    var selection: SectionType = .top {
        didSet {
            print("Selection changed to \(selection)")
        }
    }
}

Затем использовать его так:

import SwiftUI

enum SectionType: String, CaseIterable {
    case top = "Top"
    case best = "Best"
}

struct ContentView : View {
    @ObjectBinding var store = SelectionStore()

    var body: some View {
        SegmentedControl(selection: $store.selection) {
            ForEach(SectionType.allCases.identified(by: \.self)) { type in
                Text(type.rawValue).tag(type)
            }
        }
    }
}
1 голос
/ 12 июня 2019

Не совсем отвечаю на ваш вопрос, но вот правильный способ настроить SegmentedControl (не хотел публиковать этот код в качестве комментария, потому что он выглядит некрасиво). Замените вашу ForEach версию следующим кодом:

ForEach(0..<SectionType.allCases.count) { index in 
    Text(SectionType.allCases[index].rawValue).tag(index)
}

Пометка представлений регистрами или даже строками делает его неадекватным - выбор не работает.

Вы также можете добавить следующее после объявления SegmentedControl, чтобы убедиться, что выбор работает:

Text("Value: \(SectionType.allCases[self.selection].rawValue)")

Полная версия body:

var body: some View {
    VStack {
        SegmentedControl(selection: self.selection) {
            ForEach(0..<SectionType.allCases.count) { index in
                Text(SectionType.allCases[index].rawValue).tag(index)
                }
            }

        Text("Value: \(SectionType.allCases[self.selection].rawValue)")
    }
}

По поводу вашего вопроса - я попытался добавить didSet обозреватель к selection, но он вылетает из-за редактора Xcode и выдает ошибку «Ошибка сегментации: 11» при попытке сборки.

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