Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 触发CombineTest以在联合收割机中传播初始值_Swift_Reactive Programming_Combinelatest_Combine - Fatal编程技术网

Swift 触发CombineTest以在联合收割机中传播初始值

Swift 触发CombineTest以在联合收割机中传播初始值,swift,reactive-programming,combinelatest,combine,Swift,Reactive Programming,Combinelatest,Combine,我有两个字符串发布器和一个返回AnyPublisher的计算属性。逻辑非常简单,但我想知道是否有任何方法可以传播初始值。我认为这应该是可能的,因为出版商有初始值 在VC中,我从ViewModel(从textField)向发布者分配新值 然后我将Publisher(combineLatest)分配给我的按钮: _ = viewModel.validatedText .receive(on: RunLoop.main) .assign(to: \.isEnabled, on: butto

我有两个字符串发布器和一个返回AnyPublisher的计算属性。逻辑非常简单,但我想知道是否有任何方法可以传播初始值。我认为这应该是可能的,因为出版商有初始值

在VC中,我从ViewModel(从textField)向发布者分配新值

然后我将Publisher(combineLatest)分配给我的按钮:

_ = viewModel.validatedText
   .receive(on: RunLoop.main)
   .assign(to: \.isEnabled, on: button)
在VM中,我有两个发布者:

@Published var firstPublisher: String = ""
@Published var secondPublisher: String = ""
和联合测试:

var validatedText: AnyPublisher<Bool, Never> {
    return Publishers.CombineLatest($firstPublisher, $secondPublisher) {
        return !($0.isEmpty || $1.isEmpty)
        }.eraseToAnyPublisher()
}
var validatedText:AnyPublisher{
返回publisher.CombineTest($firstPublisher,$secondPublisher){
返回!($0.isEmpty | |$1.isEmpty)
}.删除任何发布者()
}

validatedText仅在我开始在两个文本字段中键入时才开始发布新值。我尝试在VM的init中分配一些新值,例如(分配给第一个和第二个发布者),但也不起作用。有没有办法,否则我将不得不设置按钮的初始状态(禁用它),而不使用联合收割机?

不幸的是,这似乎只是
@Published
的行为,但您可以在生成的发布服务器中通过预先设置初始值来解决此问题:

var validatedText: AnyPublisher<Bool, Never> {
    let validate: (String, String) -> Bool = {
        !($0.isEmpty || $1.isEmpty)
    }
    return Publishers.CombineLatest($firstPublisher, $secondPublisher, transform: validate)
        .prepend(validate(firstPublisher, secondPublisher))
        .eraseToAnyPublisher()
}
var validatedText:AnyPublisher{
让我们验证:(字符串,字符串)->Bool={
!($0.isEmpty | |$1.isEmpty)
}
返回publisher.CombineTest($firstPublisher,$secondPublisher,transform:validate)
.prepend(验证(第一个发布者,第二个发布者))
.删除任何发布者()
}
相反,如果您愿意采用这种方法,那么编写自己的属性委托以获得所需的行为是相当简单的:

import Combine

@propertyDelegate
struct InitialPublished<Value> : Publisher {
    typealias Output = Value
    typealias Failure = Never

    private let subject: CurrentValueSubject<Output, Failure>

    var value: Value {
        set { subject.value = newValue }
        get { subject.value }
    }

    init(initialValue: Value) {
        subject = CurrentValueSubject(initialValue)
    }

    func receive<S>(subscriber: S) where S: Subscriber, Value == S.Input, Failure == S.Failure {
        subject.receive(subscriber: subscriber)
    }
}
导入联合收割机
@财产继承人
结构初始值已发布:Publisher{
typealias输出=值
typealias故障=从不
私人租赁主体:CurrentValueSubject
var值:value{
设置{subject.value=newValue}
获取{subject.value}
}
init(initialValue:Value){
主题=当前值主题(初始值)
}
func receive(subscriber:S),其中S:subscriber,Value==S.Input,Failure==S.Failure{
subject.receive(订户:订户)
}
}

正是我想知道的,谢谢。
import Combine

@propertyDelegate
struct InitialPublished<Value> : Publisher {
    typealias Output = Value
    typealias Failure = Never

    private let subject: CurrentValueSubject<Output, Failure>

    var value: Value {
        set { subject.value = newValue }
        get { subject.value }
    }

    init(initialValue: Value) {
        subject = CurrentValueSubject(initialValue)
    }

    func receive<S>(subscriber: S) where S: Subscriber, Value == S.Input, Failure == S.Failure {
        subject.receive(subscriber: subscriber)
    }
}