Home > Software design >  How to return Observable<String> based on the conditions of Observable<Bool> RxSwift
How to return Observable<String> based on the conditions of Observable<Bool> RxSwift

Time:06-30

I'm quite new to RxSwift.

Is there any way I can create a function that will return Observable based on the conditions of two functions below

func isValidPassword(_ str: PublishSubject<String>) -> Observable<Bool> {
    return str.asObservable().map {
        validator.isValidPasswordRegex($0) && $0.count >= 8
    }
}



func isNotEmpty(_ str: PublishSubject<String>) -> Observable<Bool> {
    return str.asObservable().map {
        $0.count != 0
    }
}

This code below is just an example of what I'm trying to achieve, hoped you got the idea.

func someFunc(_ str:PublishSubject<String>) -> Observable<String> {
   if !isValidPassword(str){
      return "Not a valid password" //should return as an observable string
   }
   if isNotEmpty(str){
      return "String is not empty" //should return as an observable string
   }
}

CodePudding user response:

I'm not sure about what you want to achieve here but I think you should use filter operator and not map. In this way you don't change the type of the starting observable but you remove elements that don't respect your conditions.

func isValidPassword(_ str: String) -> Bool {
  validator.isValidPasswordRegex(str) && str.count >= 8
}

func someFunc(_ str: PublishSubject<String>) -> Observable<String> {
  str
    .filter(isValidPassword)
    .filter { !$0.isEmpty }
}

CodePudding user response:

Let me introduce you to zip... It allows you to combine multiple Observables.

func someFunc(_ str: Observable<String>) -> Observable<String> {
    Observable.zip(isValidPassword(str), isNotEmpty(str))
        .map { isValidPassword, isNotEmpty -> String in
            if !isValidPassword {
                return "Not a valid password"
            }
            if isNotEmpty {
                return "String is not empty"
            }
            return "" // you didn't specify what it should return here...
        }
}

Note that I updated the type signatures of your existing functions:

func isValidPassword(_ str: Observable<String>) -> Observable<Bool>
func isNotEmpty(_ str: Observable<String>) -> Observable<Bool>

Passing Subjects around like that is a recipe for disaster.

Subjects provide a convenient way to poke around Rx, however they are not recommended for day to day use. -- Introduction to Rx

UPDATE

I think the code would be better if you implemented like this though:

func errorMessage(text: Observable<String>) -> Observable<String> {
    text.map(errorMessage)
}

func errorMessage(_ str: String) -> String {
    if !isValidPassword(str) {
        return "Not a valid password"
    }
    if isNotEmpty(str) {
        return "String is not empty"
    }
    return ""
}

func isValidPassword(_ str: String) -> Bool
func isNotEmpty(_ str: String) -> Bool

It's much easier to test this way.

  • Related