私はSwiftUIとCombineをいじってみましたが、ビューの既存の@Stateプロパティを取得して新しいものを作成する方法があると思います。
たとえば、ユーザーのパスワードとpasswordConfirmフィールドを保持するパスワード作成ビューがあります。これらの2つの@Stateプロパティを取得し、ビューで使用できる新しい@Stateを派生させて、入力が有効かどうかをアサートしたいと考えています。簡単にするために、空ではなく等しくないようにします。
Apple docsは 発行者がいます と言いますが、私はそれを理解しているようには見えませんが。
これは機能しない疑似コードです:
_import SwiftUI
import Combine
struct CreatePasswordView : View {
@State var password = ""
@State var confirmation = ""
lazy var valid = {
return self.$password.publisher()
.combineLatest(self.$confirmation)
.map { $0 != "" && $0 == $1 }
}
var body: some View {
SecureField($password, placeholder: Text("password"))
SecureField($confirmation, placeholder: Text("confirm password"))
NavigationButton(destination: NextView()) { Text("Done") }
.disabled(!valid)
}
}
_
誰でも見つかりました。これに対処する適切な方法/それが可能かどうか
ベータ2の更新:
ベータ2のパブリッシャーが利用可能になったため、このコードの前半が機能するようになりました。結果のパブリッシャーをビュー内で使用する後半は、まだわかりません(disabled(!valid)
)。
_import SwiftUI
import Combine
struct CreatePasswordView : View {
@State var password = ""
@State var confirmation = ""
lazy var valid = {
Publishers.CombineLatest(
password.publisher(),
confirmation.publisher(),
transform: { String($0) != "" && $0 == $1 }
)
}()
var body: some View {
SecureField($password, placeholder: Text("password"))
SecureField($confirmation, placeholder: Text("confirm password"))
NavigationButton(destination: NextView()) { Text("Done") }
.disabled(!valid)
}
}
_
ありがとう。
Combine
は現在ベータ版であるため、私は@State/@Published
で遊んでいませんが、達成しようとしていることの簡単な回避策を次に示します。
パスワード、パスワードの確認、およびそれが有効かどうかを保持するビューモデルを実装します
class ViewModel: NSObject, BindableObject {
var didChange = PassthroughSubject<Void, Never>()
var password: String = "" {
didSet {
didChange.send(())
}
}
var passwordConfirmation: String = "" {
didSet {
didChange.send(())
}
}
var isPasswordValid: Bool {
return password == passwordConfirmation && password != ""
}
}
このようにして、ビューはパスワードまたは確認が変更されるたびに再計算されます。
次に、ビューモデルに@ObjectBinding
を作成します。
struct CreatePasswordView : View {
@ObjectBinding var viewModel: ViewModel
var body: some View {
NavigationView {
VStack {
SecureField($viewModel.password,
placeholder: Text("password"))
SecureField($viewModel.passwordConfirmation,
placeholder: Text("confirm password"))
NavigationButton(destination: EmptyView()) { Text("Done") }
.disabled(!viewModel.isPasswordValid)
}
}
}
}
ビューをNavigationView
に入れなければなりませんでした。NavigationButton
は、ビューの1つにない場合、それ自体を有効にできないようです。