error: cannot invoke 'onNext' with an argument list of type '(String)' RxSwift - swift

Why is the following RxSwift code not compiling and how do I solve the problem? This line observer.onNext("test123") is the problem.
final class TestA<String>: ObservableType {
typealias E = String
private let _observable: Observable<String>
init() {
_observable = Observable<String>.create { observer -> Disposable in
print("mark 1")
observer.onNext("test123")
observer.onCompleted()
return Disposables.create()
}
}
func subscribe<O>(_ observer: O) -> Disposable where O : ObserverType, O.E == E {
return _observable.subscribe(observer)
}
}
let observable = TestA<String>()
print("mark 2")
observable.subscribe(onNext: { element in
print(element)
})
I am testing in the playground and get the following error:
Playground execution failed:
error: Introduction.xcplaygroundpage:25:26: error: cannot invoke 'onNext' > with an argument list of type '(String)'
observer.onNext("test123")
^
Introduction.xcplaygroundpage:25:26: note: expected an argument list of > type '(String)'
observer.onNext("test123")
^
One of the reasons behind this setup with the class is that I want to pass in the dependencies with constructor injection and use them in the create closure in order to avoid having to capture self. I also want to avoid having all those Observable.creates in the wild and have a more OOP approach.

The swift compiler was not helpful with this error...
The problem here is that, when declaring TestA, you override the name String to represent the generic parameter for TestA. It is then an error to sent a Swift.String as a parameter to an observer expecting a TestA.String, which could be anything.
You can fix the issue with removing the unused generic parameter (final class TestA: ObservableType { ...), or taking the value sent to onNext as a parameter to the init, depending on the use case.
final class TestA<Element>: ObservableType {
typealias E = Element
private let _observable: Observable<Element>
init(_ value: Element) {
_observable = Observable<Element>.create { observer -> Disposable in
print("mark 1")
observer.onNext(value)
observer.onCompleted()
return Disposables.create()
}
}
func subscribe<O>(_ observer: O) -> Disposable where O : ObserverType, O.E == E {
return _observable.subscribe(observer)
}
}

Related

How can I create an operator to implement error chaining?

I want to implement the following operator »:
throwingFunction(arg: T?)».doStuff()
/* if throwingFunction throws an error:
print or log the error
else
returns an object having the doStuff() Method
OR
An Alternative design that I'm open to is
Instead of a throwing Error, the `throwingFunction()`
can be swapped out for a method that returns `Result`
OR
a custom Type, with a generic payload type.
*/
Here is an example of something similar to what I'm looking for. It is a custom implementation of optional chaining made possible using the KeyPath object (credit to Sergey Smagleev
).
precedencegroup Chaining {
associativity: left
}
infix operator ~> : Chaining
extension Optional {
static func ~><T>(value: Wrapped?, key: KeyPath<Wrapped, T> ) -> T? {
return value.map { $0[keyPath: key] }
}
static func ~><T>(value: Wrapped?, key: KeyPath<Wrapped, T?> ) -> T? {
return value.flatMap { $0[keyPath: key] }
}
}
struct Object {
let anotherOptionalObject: AnotherObject?
}
struct AnotherObject {
let value: String
}
let optionalObject: Object? = Object(anotherOptionalObject: AnotherObject(value: "Hello world"))
print(optionalObject~>\.anotherOptionalObject~>\.value) //this prints Optional("Hello world")
print(optionalObject?.anotherOptionalObject?.value) //this also prints Optional("Hello world")
Except, I want the implementation to provide an opportunity for me to handle the error by printing or logging it.
prefix and postfix are unary operators i.e. they only accept one operand, whereas an infix operator is a binary operator i.e. it accepts two operands.
So, static func »(value:key:) -> Preferred? is not correct because it's taking two operands whereas you have defined » as a postfix operator.
For some reason I get "» is not a postfix unary operator" when I don't use the escape syntax. But apart from that it seems to work.
precedencegroup Chaining {
associativity: left
}
infix operator » : Chaining
extension Result {
static func »<T>(value: Self, key: KeyPath<Success, T>) -> T? {
switch value {
case .success(let win):
return win[keyPath: key]
case .failure(let fail):
print(fail.localizedDescription)
return nil
}
}
}
// I included a custom type so that it could be customizable if needed.
enum Err<Wrapped> {
static func »<T>(value: Self, key: KeyPath<Wrapped, T>) -> T? {
switch value {
case .error(let err):
print(err.localizedDescription)
return nil
case .some(let wrapper):
return wrapper[keyPath: key]
}
}
case error(Error)
case some(Wrapped)
}
func errorWrapped() -> Err<String> {
.some("Hello World")
}
func pleaseWork() {
print(errorWrapped()»\.isEmpty)
}

RxSwift - Construct the Observable using function inside transform function

Here's my code snippet:
open class SomeClass {
let driver: Driver<Bool>
init(input: Observable<String>) {
driver = input
.map( { s -> Bool in self.convert(text: s) }) // error 'self' captured by a closure before all members were initialized
.asDriver(onErrorJustReturn: false)
}
func convert(text: String) -> Bool {
// Do some complex calculation
return true
}
}
Explanation: In my SomeClass, I have a driver object of type Driver<Bool>, then inside my init, I'll take an Observable<String> and map it to a Observable<Bool>.
However in order to do the conversion I need to call the func convert() inside the mapping closure, thus I'm getting the error
'self' captured by a closure before all members were initialized
Can someone please show me how to get through this?
The simplest solution is to move convert out of the class:
open class SomeClass {
let driver: Driver<Bool>
init(input: Observable<String>) {
driver = input
.map( { s -> Bool in convert(text: s) }) // error 'self' captured by a closure before all members were initialized
.asDriver(onErrorJustReturn: false)
}
}
func convert(text: String) -> Bool {
// Do some complex calculation
return true
}
You should probably make convert(text:) private to avoid name pollution.

Returning an object that conforms to a generic constraint

I am trying to create a Builder for my ComplexObject:
import Foundation
class ComplexObject {
// lots of stuff
init<ObjectType, T>(_ closure: ((ObjectType) -> T)) {
// lots of init/setup code
}
// other initializers with generics, constructed
// by other Builders than ConcreteBuilder<O> below
}
protocol BuilderType {
associatedtype ObjectType
func title(_: String) -> Self
func build<T>(_ closure: ((ObjectType) -> T)) -> ComplexObject
}
struct Injected<O> {
//...
}
extension ComplexObject {
static func newBuilder<Builder: BuilderType, O>(someDependency: Injected<O>) -> Builder where Builder.ObjectType == O {
// vvvv
return ConcreteBuilder(someDependency: someDependency)
// ^^^^
// Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'
}
struct ConcreteBuilder<O>: BuilderType {
private let dependency: Injected<O>
private var title: String
init(someDependency: Injected<O>) {
self.dependency = someDependency
}
func title(_ title: String) -> ConcreteBuilder<O> {
var builder = self
builder.title = title
return builder
}
func build<T>(_ closure: ((O) -> T)) -> ComplexObject {
return ComplexObject(closure)
}
}
}
but swiftc complains about the return ConcreteBuilder(...) line
Cannot convert return expression of type 'ComplexObject.ConcreteBuilder<O>' to return type 'Builder'
I also tried
static func newBuilder<Builder: BuilderType>(someDependency: Injected<Builder.ObjectType>) -> Builder {
return ConcreteBuilder(someDependency: someDependency)
}
with the same result. I see that I could just expose ConcreteBuilder, but I hoped to be able to hide that implementation detail. What am I missing here?
I'm not sure how to solve this issue, but the root of the problem is that newBuilder(someDependancy:) has a generic type signature, but it's really not generic.
Its return type asserts that function can return an object of any type T: BuilderType where Builder.ObjectType == O, but that's clearly not the case. Asking this function to return any type besides a ConcreteBuilder isn't supported. At best, you could use a force cast, but if someone writes let myBuilder: MyBuilder = ComplexObject.newBuilder(someDependancy: dec), the code would crash (even if MyBuilder satisfies your generic constraints) because you're trying to force cast ConcreteBuilder to MyBuilder.
As far as a solution... I don't have one. Fundamentally you just want to return BuilderType, but I don't think that's possible because it has an associated type.
Will this do ?
return ConcreteBuilder(someDependency: someDependency) as! Builder

Using Swift generics in a RxSwift getter function - various problems

Here's the function:
func registerFor<Element>(relayId id: String) -> Driver<Element>? {
guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
return relay.asObservable()
.distinctUntilChanged { a, b in
return a != b
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: Element())
}
The distinctUntilChanged line throws the following error:
Contextual closure type '(Element) throws -> _' expects 1 argument,
but 2 were used in closure body
The asDriver line throws the following error (of course):
Non-nominal type 'Element' does not support explicit initialization
Context: I have a class that ideally has a collection of BehaviorRelays of various types (Strings, Ints, etc). Element stands in generically for these types, but that creates two problems:
distinctUntilChanged insists of having a closure (eg: if this method returned Driver<String> it would be content simply to use distinctUntilChanged() but the generic Element makes it complain about missing a closure);
onErrorJustReturn requires a concrete value, but Element is generic.
The following "workaround" might work but I suspect there are better solutions
protocol Inii {
init()
}
func registerFor(relayId id: String, def: Inii.Type) -> Driver<Inii>? {
return relays[id]?.asObservable()
.distinctUntilChanged { _, _ in
return true
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: def.init())
}
Although I'm still unsure what to put in the distinctUntilChanged closure.
Appendix A
I believe that the following is what is required if one is implementing the distinctUntilChanged closure for a non-generic type:
.distinctUntilChanged { previousValue, currentValue in
return previousValue == currentValue
}
However, when used with the generic Element the following error is still thrown:
Contextual closure type '(Inii) throws -> _' expects 1 argument,
but 2 were used in closure body
Appendix B
Here's another alternative with a slightly different problem:
protocol Inii {
init()
}
var relay = BehaviorRelay<String>(value: "")
func registerFor<Element>(def: Element.Type) -> Driver<Element> where Element: Inii {
return relay.asObservable()
.distinctUntilChanged { previousValue, currentValue in
return previousValue == currentValue
}.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: def.init())
}
Error in this case being:
Member 'next' in 'Event<_>' produces result of type 'Event<Element>',
but context expects 'Event<_>'
at the observer.on line
You can use distinctUntilChanged() without a closure as long as Element conforms to Equatable:
protocol EmptyInit {
init()
}
func registerFor<Element>(relayId id: String) -> Driver<Element>? where Element: Equatable, Element: EmptyInit {
guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
return relay.asObservable()
.distinctUntilChanged()
.flatMapLatest { value in
return Observable.create { observer in
observer.on(.next(value))
return Disposables.create()
}
}.asDriver(onErrorJustReturn: Element())
}

Swift protocol with constrained associated type error "Type is not convertible"

I have created 2 protocols with associated types. A type conforming to Reader should be able to produce an instance of a type conforming to Value.
The layer of complexity comes from a type conforming to Manager should be able to produce a concrete Reader instance which produces a specific type of Value (either Value1 or Value2).
With my concrete implementation of Manager1 I'd like it to always produce Reader1 which in turn produces instances of Value1.
Could someone explain why
"Reader1 is not convertible to ManagedReaderType?"
When the erroneous line is changed to (for now) return nil it all compiles just fine but now I can't instantiate either Reader1 or Reader2.
The following can be pasted into a Playground to see the error:
import Foundation
protocol Value {
var value: Int { get }
}
protocol Reader {
typealias ReaderValueType: Value
func value() -> ReaderValueType
}
protocol Manager {
typealias ManagerValueType: Value
func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType?
}
struct Value1: Value {
let value: Int = 1
}
struct Value2: Value {
let value: Int = 2
}
struct Reader1: Reader {
func value() -> Value1 {
return Value1()
}
}
struct Reader2: Reader {
func value() -> Value2 {
return Value2()
}
}
class Manager1: Manager {
typealias ManagerValueType = Value1
let v = ManagerValueType()
func read<ManagerReaderType: Reader where ManagerReaderType.ReaderValueType == ManagerValueType>() -> ManagerReaderType? {
return Reader1()// Error: "Reader1 is not convertible to ManagedReaderType?" Try swapping to return nil which does compile.
}
}
let manager = Manager1()
let v = manager.v.value
let a: Reader1? = manager.read()
a.dynamicType
The error occurs because ManagerReaderType in the read function is only a generic placeholder for any type which conforms to Reader and its ReaderValueType is equal to the one of ManagerReaderType. So the actual type of ManagerReaderType is not determined by the function itself, instead the type of the variable which gets assigned declares the type:
let manager = Manager1()
let reader1: Reader1? = manager.read() // ManagerReaderType is of type Reader1
let reader2: Reader2? = manager.read() // ManagerReaderType is of type Reader2
if you return nil it can be converted to any optional type so it always works.
As an alternative you can return a specific type of type Reader:
protocol Manager {
// this is similar to the Generator of a SequenceType which has the Element type
// but it constraints the ManagerReaderType to one specific Reader
typealias ManagerReaderType: Reader
func read() -> ManagerReaderType?
}
class Manager1: Manager {
func read() -> Reader1? {
return Reader1()
}
}
This is the best approach with protocols due to the lack of "true" generics (the following isn't supported (yet)):
// this would perfectly match your requirements
protocol Reader<T: Value> {
fun value() -> T
}
protocol Manager<T: Value> {
func read() -> Reader<T>?
}
class Manager1: Manager<Value1> {
func read() -> Reader<Value1>? {
return Reader1()
}
}
So the best workaround would be to make Reader a generic class and Reader1 and Reader2 subclass a specific generic type of it:
class Reader<T: Value> {
func value() -> T {
// or provide a dummy value
fatalError("implement me")
}
}
// a small change in the function signature
protocol Manager {
typealias ManagerValueType: Value
func read() -> Reader<ManagerValueType>?
}
class Reader1: Reader<Value1> {
override func value() -> Value1 {
return Value1()
}
}
class Reader2: Reader<Value2> {
override func value() -> Value2 {
return Value2()
}
}
class Manager1: Manager {
typealias ManagerValueType = Value1
func read() -> Reader<ManagerValueType>? {
return Reader1()
}
}
let manager = Manager1()
// you have to cast it, otherwise it is of type Reader<Value1>
let a: Reader1? = manager.read() as! Reader1?
This implementation should solve you problem, but the Readers are now reference types and a copy function should be considered.