I'm trying to implement concatMap within RxSwift but when I tried to set a new value to the observable within the concatMap I'm getting this error:
Reentrancy anomaly was detected.
> Debugging: To debug this issue you can set a breakpoint in /Users/SuperUser/repos/RxObserver/Pods/RxSwift/RxSwift/Rx.swift:96 and observe the call stack.
> Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`
This behavior breaks the grammar because there is overlapping between sequence events.
Observable sequence is trying to send an event before sending of previous event has finished.
> Interpretation: This could mean that there is some kind of unexpected cyclic dependency in your code,
or that the system is not behaving in the expected way.
> Remedy: If this is the expected behavior this message can be suppressed by adding `.observeOn(MainScheduler.asyncInstance)`
or by enqueuing sequence events in some other way.
Here is my code:
public let myNumbers = BehaviorRelay<String>(value: "")
override func viewDidLoad() {
super.viewDidLoad()
processNumbers()
myNumbers.accept("one")
myNumbers.accept("two")
}
func processNumbers() {
Observable.of(myNumbers).concatMap{ $0
}.subscribe(onNext:{
print($0)
if $0 == "one" || $0 == "two"{
self.myNumbers.accept("YEAH!")
}
}).disposed(by: disposeBag)
}
Any of you know why I am getting this error or how can I change my implementation to avoid getting this error/warning?
I'll really appreciate your help.
Any of you knows why I may getting this error?
> Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`
This behavior breaks the grammar because there is overlapping between sequence events.
Observable sequence is trying to send an event before sending of previous event has finished.
how can change my implementation to avoid getting this error/warning ?
> Remedy: If this is the expected behavior this message can be suppressed by adding `.observeOn(MainScheduler.asyncInstance)`
or by enqueuing sequence events in some other way.
I found a way to fix this issue:
func processNumbers() {
Observable.of(myNumbers).concatMap{ $0
}
.observeOn(MainScheduler.asyncInstance)
.subscribe(onNext:{
print($0)
if $0 == "one" || $0 == "two"{
self.myNumbers.accept("YEAH!")
}
}).disposed(by: disposeBag)
}
By adding this line of code .observeOn(MainScheduler.asyncInstance) the error/warning goes away!!
Related
I'm using project reactor and I have a very long flow in which I get an exception (when parsing a string to json with Jackson). The thing is that even though I use
.map(this::parser)
.onErrorResume(err -> {
log.error(myMsg);
return Mono.empty();
})
.flatMap(writeToPulsar)
.subscribe()
The flow won't continue. I do see the error log and the flow doesn't throw an exception, but the flow won't continue to get executed. Any reason for this to happen?
When I change the code to the (unwanted) .onErrorContinue(), the data pipeline won't get stopped:
.map(this::parser)
.onErrorContinue((err, msg) -> {
log.error(myMsg);
})
.flatMap(writeToPulsar)
.subscribe()
As a part of the error handling you are returning Mono.empty() and it means your flow will be completed without emitting any result and flatMap will not be executed.
Not sure about the expected behavior but if you want to continue the flow - return some "default" value from onErrorResume instead or use switchIfEmpty operator to provide another publisher.
I'm somewhat familiar with basic RxJS concepts like Observables, Observers and Subjects but RxJS Notifications concept is completely new to me.
What is it for? When should I use it?
The documentation you quoted mentions :
This class is particularly useful for operators that manage notifications, like materialize, dematerialize, observeOn, and others. Besides wrapping the actual delivered value, it also annotates it with metadata of, for instance, what type of push message it is (next, error, or complete).
So the question turns out to be about use cases for materialize and the like.
Basically, you use materialize to get meta-information about the dataflow without incurring into the associated side-effects (an error incurring in a stream for example propagates, a stream which completes can lead to the completion of other streams etc.). dematerialize allows to restore the side-effects.
Here are uses case from former SO questions :
Receiving done notifications from observables built using switch
RxJs - parse file, group lines by topics, but I miss the end
A use case: as errors or completions are propagated immediately, you can't for example delay them. To do so, you can try this approach:
// sample stream
interval(500).pipe(
mapTo('normal value'),
// sometimes value, sometimes throw
map(v => {
if (randomInt() > 50) {
throw new Error('boom!')
} else return v;
}),
materialize(),
// turns Observable<T> into Notification<Observable<T>>
// so we can delay or what you want
delay(500),
// and we need to do some magic and change Notification of error into
// Notification of value (error message)
map(n => n.hasValue? n : new Notification('N', n.error.message, null)),
// back to normal
dematerialize()
)
// now it never throw so in console we will have
// `normal value` or `boom!` but all as... normal values (next() emmision)
// and delay() works as expected
.subscribe(v => console.log(v))
I have a function that returns the last word typed on a third party keyboard:
var lastWordTyped: String? {
let proxy = self.textDocumentProxy as! UITextDocumentProxy
if let documentContext = proxy.documentContextBeforeInput as NSString? {
let length = documentContext.length
if length > 0 && NSCharacterSet.alphanumericCharacterSet().characterIsMember(documentContext.characterAtIndex(length - 1)) {
let components = documentContext.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet) as! [String]
println(components)
return components[components.endIndex - 1]
}
}
return nil
}
For some reason although the function works normally and returns the correct output, I looked at the output in the log by chance and discovered that it was butchering the output and outputting it many times (as seen in the picture below).
Would this cause the memory usage of my keyboard to increase? Does it slow it down?
How can I fix this?
Edit 1: This error is not reproducible when using the simulator.
println is not synchronized, so if there are multiple threads calling your code, their output can overlap.
I'd suggest replacing println(components) with NSLog(components) to get a better view on what's actually going on.
After updating Xcode to 6.3 today I finally was able to totally remove sqlite.swift and reinstall it. And after having fixed about 50 errors caused by something changing I am down to about 15 errors remaining and all of them have something to do with the new sqlite.swift.
I have searched for new docs to cover the syntax changes to no avail. Some errors I have found other posts about and was able to fix.
So this function that used to work now complains about the ? after the delete()?... The error message is "Optional chain has no effect, expression already produces Int?'. The recommendation is to remove the ?
func delete(id: Int) {
let rows = db[schema.tableName]
rows.filter(schema.id == id).delete()?
}
If I remove the ? after delete() then it tells me "cannot invoke 'delete' with no argument". I searched the source code and the code completion, all of which does not show any arguments.
Also on update statements I now get this error:
Example code:
rows.filter(schema.id == id)
.update(schema.acctID <- acctID, schema.accessCode <- accessCode, schema.status <- 0)
Error: cannot invoke 'update' with an argument list of type '(Setter, Setter, Setter)'
Swift 1.2 removed the ability to coerce using a trailing ?. You can use ! if the statement shouldn't fail:
func delete(id: Int) {
let rows = db[schema.tableName]
rows.filter(schema.id == id).delete()!
}
Or you can chain the delete() call to a tuple member, instead:
rows.filter(schema.id == id).delete().changes
This has been a continual support issue, so the interface may change in the near future.
The update() call needs to be fixed the same way:
rows.filter(schema.id == id)
.update(
schema.acctID <- acctID,
schema.accessCode <- accessCode,
schema.status <- 0)! // or .changes
I'm trying to intercept events using Gdk.Window.AddFilter(Gdk.FilterFunc) in Mono. So far, I have been able to hook up the filter function, but now I am trying to use the events in the filter function.
This is what I have in the filter function so far:
private Gdk.FilterReturn FilterFunction(IntPtr xEvent, Gdk.Event evnt)
{
if (evnt.Type == Gdk.EventType.KeyPress)
{
Gdk.EventKey eventKey = (Gdk.EventKey)evnt; // fails here
if (eventKey.Key == this.key && eventKey.State == this.modifiers)
{
this.OnPressed(EventArgs.Empty);
}
}
return Gdk.FilterReturn.Continue;
}
How can I convert the Gdk.Event to Gdk.EventKey? I have tried casting it, but that doesn't seem to work.
Edit: Oops! The problem was that I had accidentally added a semicolon to the if statement, making it an empty statement. For some reason, the Gdk.Event does not correspond to the XEvent, so I am now pursuing a solution that uses the XEvent instead.
Why don't you try printing out the type so you can see what it really is? (it may not be EventKey)
Like:
Console.WriteLine (evnt.GetType ());
(or pause it in a debugger and examine it to see the type)