CombineLatest unsolved

Hello,

I'm trying the example from the Combine in Practice video, and I'm getting the below compile error.

Use of unresolved identifier 'CombineLatest'

I have been doing the classical things.

- clean the build folder.

- verified if there are loose or redundant connexions in the storyboard.

- close the projest and restart xcode.

- delete the project data below /Library/Developper.

Without any success.

If I jump to Jump to Definition on CombineLatest in the code I'm taken directly to the definition in the Combine file.

Any help or suggestions will be most helpfull.

Regards

Lars


Xcode : 11.4.1

OS : 10.15.5 beta2

Machine : MacMini 201

Memory : 32 GO



import UIKit

import Combine


class ViewController: UIViewController {


@Published var password: String = ""

@IBAction func passwordChanged(_ sender: UITextField) {

password = sender.text ?? ""

}


@Published var passwordAgain: String = ""

@IBAction func passwordAgainChanged(_ sender: UITextField) {

passwordAgain = sender.text ?? ""

}


var validatedPassword: AnyPublisher<String?, Never> {

return CombineLatest($password, $passwordAgain) { password, passwordAgain in

guard password == passwordAgain, password.count > 8 else {return nil }

return password

}

.map { $0 == "password1" ? nil : $0 }

.eraseToAnyPublisher()

}



override func viewDidLoad() {

super.viewDidLoad()

// Do any additional setup after loading the view.

}



}

Accepted Reply

Codes shown in WWDC videos are sort of cenceptual examples based on a beta version of the framework, which would not work as is in many cases.


Try something like this:

    var validatedPassword: AnyPublisher<String?, Never> {
        return Publishers.CombineLatest($password, $passwordAgain).map { (password, passwordAgain)->String? in
            guard password == passwordAgain, password.count > 8 else {return nil }
            return password
        }
        .map { $0 == "password1" ? nil : $0 }
        .eraseToAnyPublisher()
    }

Replies

Codes shown in WWDC videos are sort of cenceptual examples based on a beta version of the framework, which would not work as is in many cases.


Try something like this:

    var validatedPassword: AnyPublisher<String?, Never> {
        return Publishers.CombineLatest($password, $passwordAgain).map { (password, passwordAgain)->String? in
            guard password == passwordAgain, password.count > 8 else {return nil }
            return password
        }
        .map { $0 == "password1" ? nil : $0 }
        .eraseToAnyPublisher()
    }

Thank you for your answer/solution.

As functional programming is new to me I'm having some difficulty, but your answer showed me some of the logic of the construction.

But it also leads me to another question. In the below example (same origin as the previous one) the computation concerns a touple of strings.

I'm stuck on the optional part.

The tuple is optional.

And the validatedPassword is optional.

The compiler complains on the guard line that binding must be optional, not String(I assume let pwd = ...).

Trying to change password or validatedPassword the compiler rightly complains that that the Publisher is defined as <(String, String?..>.

So there is a missing step before the map, and one after ?

Is there a recommended way of building the chain of modifiers?

I'm not looking as much for a precise solution for this problem, as for a general approach to this kind of problems.

And documentation seem to be scare.

Do you have any recommendation that might guide me in the right direction ?

Regards

Lars

PS upgraded to no change


Xcode : 11.5 beta1

OS : 10.15.5 beta2

Machine : MacMini 201

Memory : 32 GO


var validatedCredentials: AnyPublisher<(String, String)?, Never> {

return Publishers.CombineLatest(validatedUserName, validatedPassword)

.map{ (username, password)->(String, String)? in

guard let uname = username , let pwd = password else {return nil }

return(uname, pwd)

}

.eraseToAnyPublisher()

}

The compiler complains on the guard line that binding must be optional, not String(I assume let pwd = ...).

I'm afraid you are using the wrong `validatedPassword` or `validatedUserName`.

    var validatedPassword: AnyPublisher<String?, Never> { //<- Here `String?`
        //...
    }

    var validatedUsername: AnyPublisher<String?, Never> { //<- Again `String?`, and not `validatedUserName`
        //...
    }

    var validatedCredentials: AnyPublisher<(String, String)?, Never> {
        //                              ↓not `validatedUserName`
        return Publishers.CombineLatest(validatedUsername, validatedPassword).map { username, password in
            guard let uname = username, let pwd = password else { return nil }
            return (uname, pwd)
        }
        .eraseToAnyPublisher()
    }


So there is a missing step before the map, and one after ?

I'm afraid you have missed some steps in the Video.


First, `validatedUsername` was declared as:

var validatedUsername: AnyPublisher<String, Never> {
    //...
}

But it is updated to the following in a step shown in the video:

var validatedUsername: AnyPublisher<String?, Never><string?, never=""> {
   //...
}


My apologies, your answer worked very well with the validatedUser variable, but my problem is now with the validatedCredentials.

Would you have any idea of where the proble is?

Thanks

Lars


Xcode : 11.5 beta1

OS : 10.15.5 beta2

Machine : MacMini 201

Memory : 32 GO


var validatedCredentials: AnyPublisher<(String, String)?, Never> {

return Publishers.CombineLatest(validatedUserName, validatedPassword)

.map{ (username, password)->(String, String)? in

guard let uname = username , let pwd = password else {return nil }

return(uname, pwd)

}

.eraseToAnyPublisher()

}

I cannot find `validatedUserName` in the codes shown in the video, so I do not understand what you are trying to do?


Have you read my last reply carefully? You are not using the code shown in the video.

I apologize I was wrong with my paste below the good one.

It gives me the error message on the guard statement

"Initializer for conditional binding must have Optional type, not 'Published<String>.Publisher.Output' (aka 'String')"


Regards

Lars



Xcode : 11.5 beta1

OS : 10.15.5 beta2

Machine : MacMini 201

Memory : 32 GO


var validatedCredentials: AnyPublisher<(String, String)?, Never> {

return Publishers.CombineLatest($userName, $password).map { username, password in

guard let uname = username, let pwd = password else { return nil }

return (uname, pwd)

}

.eraseToAnyPublisher()

}

Read my reply carefully.

Thank you very much, and I'll try to read better in the future :-)