Ignoring fast changes on a Boolean variable with RxSwift - boolean

I have a boolean Variable which is switching true/false. I need to ignore any changes which settles less than 1 second. In other words, I need just values which stays more than 1 second. How to get such output from RxSwift?
Sample1: If value is true, and changes to false and then after 0.5 seconds become true again, I need my output sequence to show nothing.
Sample2: Above scenario with 1.2 seconds lag between false and true, makes a false event in my output sequence.

You can use a combination of skip, debounce and distinctUntilChanged to achieve that:
aSwitch.rx.isOn
.skip(1) // 1
.debounce(1, scheduler: MainScheduler.instance) // 2
.distinctUntilChanged() // 3
.subscribe(onNext: { isOn in
print("IS ON: \(isOn)")
})
.disposed(by: disposeBag)
A little explanation:
// 1: This prevents the Switch from emitting its initial value. You can remove this if you need the initial value of the UISwitch
// 2: This waits until the UISwitch has not changed its value for at least 1 second before emitting the new value
// 3: This filters out values that have not changed. So no value is emitted if after one second of inactivity the value of the switch is the same as before the user started changing the value.

Related

RxSwift purpose of Observable

I am learning about RxSwift and trying to understand the main difference between Observable and PublishSubject aka Sequence.
As far as I understood, Sequences / PublishesSubject act as Observable and Observer. You can subscribe to these and they emit notifications if the value changes. PublishesSubject can be changed.
My question is, what is the purpose of Observables then? I can only create Observable with a fix value with just() or from(). But I can not change these values or append an item, right? So my Observable will only emit the value I assigned to it in the init. Why do I need Observable then, when the actual value is immutable?
Let´s think of a function which returns an Observable<UIImage>. Instead of returning that Observable and then subscribe on next, I can just return an UIImage. Why do I need a Observable?
If I create following Observable:
let observable = Observable.of(1,2,3)
I would have a static Marble diagram.. my Observable will emit 1,2 and 3. And afterwards..? It is ended?
I am just not getting the reason why I should use Observable. Any help is appreciated.
To help you understand, look at Observable.create. You will see that it takes a closure. This closure executes every time an observer subscribes to it.
So if you wanted to implement just using create, you would do something like:
func just(_ value: Int) -> Observable {
return Observable.create { observer in
observer.onNext(value)
observer.onCompleted()
return Disposables.create()
}
}
Sure, that will just emit the static value very time, but you could do other things...
let random = Observable<Int>.create { observer in
observer.onNext(Int.random(in: 0..<10))
observer.onCompleted()
return Disposables.create()
}
The above will emit a random value and then complete. You could also make a network request in the closure, or you could call onNext every time a button is tapped. RxCocoa has a bunch of them already... So for example:
let result = loginButton.rx.tap
.withLatestFrom(Observable.combineLatest(usernameTextField.rx.text, passwordTextField.rx.text))
.map { URLRequest.login(credentials: $0) }
.flatMapLatest { URLSession.shared.rx.data(request: $0) }
.subscribe(onNext: { print("data:", $0) }
loginButton.rx.tap emits a next event every time the button is tapped.
usernameTextField.rx.text & passwordTextField.rx.text emit next events every time the user enters data into one of the text fields.
URLSession.shared.rx.data(request:) emits a value when the server responds with data. All of these are (forms of) Observables.
If you really don't like the mutable state of Subjects, you can use normal Observables. This comes in handy when you want to convert your ViewModel to a function instead of a class.
To answer this specific question of yours,
Let´s think of a function which returns an Observable<UIImage>. Instead of returning that Observable and then subscribe on next, I can just return an UIImage. Why do I need a Observable?
Answer is, imagine a situation where you can't immediately return a UIImage. This could be a result of a network operation or, expensive drawing operation that could take time. So it has to be asynchronous. In order to achieve this, you can use Observable<UIImage> instead of UIImage. That way you can immediately return Observable<UIImage> but your subscriber won't receive the UIImage until it's actually finished processing.
Without Observables, you have to pass a block to achieve the same result. This is just one example. There are many use cases.

Fire last value when subscribing to publisher?

I have an AnyPublisher property that emits values. When someone subscribes to it, is there a way to emit the last value immediately and let it listen for future values from there?
You should use a CurrentValueSubject for this and erase that to AnyPublisher
let publisher = CurrentValueSubject<Int, Never>(1).eraseToAnyPublisher()
let c = publisher.sink(receiveValue: { int in
print(int)
})
The code above would immediately print 1 since that's the current value of the CurrentValueSubject.

swift combine declarative syntax

The declarative syntax of Swift Combine looks odd to me and it appears that there is a lot going on that is not visible.
For example the following code sample builds and runs in an Xcode playground:
[1, 2, 3]
.publisher
.map({ (val) in
return val * 3
})
.sink(receiveCompletion: { completion in
switch completion {
case .failure(let error):
print("Something went wrong: \(error)")
case .finished:
print("Received Completion")
}
}, receiveValue: { value in
print("Received value \(value)")
})
I see what I assume is an array literal instance being created with [1, 2, 3]. I guess it is an array literal but I'm not accustomed to seeing it "declared" without also assigning it to a variable name or constant or using _=.
I've put in an intentional new line after and then .publisher. Is Xcode ignoring the whitespace and newlines?
Because of this style, or my newness to visually parsing this style, I mistakenly thought ", receiveValue:" was a variadic parameter or some new syntax, but later realized it is actually an argument to .sink(...).
Cleaning up the code first
Formatting
To start, reading/understanding this code would be much easier if it was formatted properly. So let's start with that:
[1, 2, 3]
.publisher
.map({ (val) in
return val * 3
})
.sink(
receiveCompletion: { completion in
switch completion {
case .failure(let error):
print("Something went wrong: \(error)")
case .finished:
print("Received Completion")
}
},
receiveValue: { value in
print("Received value \(value)")
}
)
Cleaning up the map expression
We can further clean up the map, by:
Using an implicit return
map({ (val) in
return val * 3
})
Using an implicit return
map({ (val) in
val * 3
})
Remove unecessary brackets around param declaration
map({ val in
val * 3
})
Remove unecessary new-lines. Sometimes they're useful for visually seperating things, but this is a simple enough closure that it just adds uneeded noise
map({ val in val * 3 })
Use an implicit param, instead of a val, which is non-descriptive anyway
map({ $0 * 3 })
Use trailing closure syntax
map { $0 * 3 }
Final result
with numbered lines, so I can refer back easily.
/* 1 */[1, 2, 3]
/* 2 */ .publisher
/* 3 */ .map { $0 * 3 }
/* 4 */ .sink(
/* 5 */ receiveCompletion: { completion in
/* 6 */ switch completion {
/* 7 */ case .failure(let error):
/* 8 */ print("Something went wrong: \(error)")
/* 9 */ case .finished:
/* 10 */ print("Received Completion")
/* 11 */ }
/* 12 */ },
/* 13 */ receiveValue: { value in
/* 14 */ print("Received value \(value)")
/* 15 */ }
/* 16 */ )
Going through it.
Line 1, [1, 2, 3]
Line 1 is an array literal. It's an expression, just like 1, "hi", true, someVariable or 1 + 1. An array like this doesn't need to be assigned to anything for it to be used.
Interestingly, that doesn't mean necessarily that it's an array. Instead, Swift has the ExpressibleByArrayLiteralProtocol. Any conforming type can be initialized from an array literal. For example, Set conforms, so you could write: let s: Set = [1, 2, 3], and you would get a Set containing 1, 2 and 3. In the absence of other type information (like the Set type annotation above, for example), Swift uses Array as the preferred array literal type.
Line 2, .publisher
Line 2 is calling the publisher property of the array literal. This returns a Sequence<Array<Int>, Never>. That isn't a regular Swift.Sequence, which is a non-generic protocol, but rather, it's found in the Publishers namespace (a case-less enum) of the Combine module. So its fully qualified type is Combine.Publishers.Sequence<Array<Int>, Never>.
It's a Publisher whose Output is Int, and whose Failure type is Never (i.e. an error isn't possible, since there is no way to create an instance of the Never type).
Line 3, map
Line 3 is calling the map instance function (a.k.a. method) of the Combine.Publishers.Sequence<Array<Int>, Never> value above. Everytime an element passed through this chain, it'll be transformed by the closure given to map.
1 will go in, 3 will come out.
Then 2 will go in, and 6 will come out.
Finally 3 would go in, and 6 would come out.
The result of this expression so far is another Combine.Publishers.Sequence<Array<Int>, Never>
Line 4, sink(receiveCompletion:receiveValue:)
Line 4 is a call to Combine.Publishers.Sequence<Array<Int>, Never>.sink(receiveCompletion:receiveValue:). With two closure arguments.
The { completion in ... } closure is provided as an argument to the parameter labelled receiveCompletion:
The { value in ... } closure is provided as an argument to the parameter labelled receiveValue:
Sink is creating a new subscriber to the Subscription<Array<Int>, Never> value that we had above. When elements come through, the receiveValue closure will be called, and passed as an argument to its value parameter.
Eventually the publisher will complete, calling the receiveCompletion: closure. The argument to the completion param will be a value of type Subscribers.Completion, which is an enum with either a .failure(Failure) case, or a .finished case. Since the Failure type is Never, it's actually impossible to create a value of .failure(Never) here. So the completion will always be .finished, which would cause the print("Received Completion") to be called. The statement print("Something went wrong: \(error)") is dead code, which can never be reached.
Discussion on "declarative"
There's no single syntactic element that makes this code qualify as "declarative". A declarative style is a distinction from an "imperative" style. In an imperative style, your program consists of a series of imperatives, or steps to be completed, usually with a very rigid ordering.
In a declarative style, your program consists of a series of declarations. The details of what's necessary to fulfill those declarations is abstracted away, such as into libraries like Combine and SwiftUI. For example, in this case, you're declaring that print("Received value \(value)") of triple the number is to be printed whenever a number comes in from the [1, 2, 3].publisher. The publisher is a basic example, but you could imagine a publisher that's emitting values from a text field, where events are coming in an unknown times.
My favourite example for disguising imperative and declarative styles is using a function like Array.map(_:).
You could write:
var input: [InputType] = ...
var result = [ResultType]()
for element in input {
let transformedElement = transform(element)
result.append(result)
}
but there are a lot of issues:
It's a lot of boiler-plate code you end up repeating all over your code base, with only subtle differences.
It's trickier to read. Since for is such a general construct, many things are possible here. To find out exactly what happens, you need to look into more detail.
You've missed an optimization opportunity, by not calling Array.reserveCapacity(_:). These repeated calls to append can reach the max capacity of an the result arrays's buffer. At that point:
a new larger buffer must be allocated
the existing elements of result need to be copied over
the old buffer needs to be released
and finally, the new transformedElement has to be added in
These operations can get expensive. And as you add more and more elements, you can run out of capacity several times, causing multiple of these regrowing operations. By callined result.reserveCapacity(input.count), you can tell the array to allocate a perfectly sized buffer, up-front, so that no regrowing operations will be necessary.
The result array has to be mutable, even though you might not ever need to mutate it after its construction.
This code could instead be written as a call to map:
let result = input.map(transform)
This has many benefits:
Its shorter (though not always a good thing, in this case nothing is lost for having it be shorter)
It's more clear. map is a very specific tool, that can only do one thing. As soon as you see map, you know that input.count == result.count, and that the result is an array of the output of the transform function/closure.
It's optimized, internally map calls reserveCapacity, and it will never forget to do so.
The result can be immutable.
Calling map is following a more declarative style of programming. You're not fiddling around with the details of array sizes, iteration, appending, or whatever. If you have input.map { $0 * $0 }, you're saying "I want the input's elements squared", the end. The implementation of map would have the for loop, appends, etc. necessary to do that. While it's implemented in an imperative style, the function abstracts that away, and lets you write code at higher levels of abstraction, where you're not mucking about with irrelevant things like for loops.
Literals
First, about literals. You can use a literal anywhere you can use a variable containing that same value. There is no important difference between
let arr = [1,2,3]
let c = arr.count
and
let c = [1,2,3].count
Whitespace
Second, about whitespace. Simply put, Swift doesn't care if you split a statement before a dot. So there is no difference between
let c = [1,2,3].count
and
let c = [1,2,3]
.count
Chaining
And when you are chaining a lot of functions one after another, splitting is actually a great way to increase legibility. Instead of
let c = [1,2,3].filter {$0>2}.count
it's nicer to write
let c = [1,2,3]
.filter {$0>2}
.count
or for even greater clarity
let c = [1,2,3]
.filter {
$0>2
}
.count
Conclusions
That's all that's happening in the code you showed: a literal followed by a long chain of method calls. They are split onto separate lines for legibility, that's all.
So nothing you mentioned in your question has anything to do with Combine. It's just basic stuff about the Swift language. Everything you're talking about could (and does) happen in code that doesn't use Combine at all.
So from a syntactical point of view, nothing is "going on that is not visible", except to know that each method call returns a value to which the next method call can be applied (just like in my own example code above, where I apply .count to the result of .filter). Of course, since your example is Combine, something is "going on that is not visible", namely that each of these values is a publisher, an operator, or a subscriber (and the subscribers do actually subscribe). But that is basically just a matter of knowing what Combine is. So:
[1,2,3] is an array which is a sequence, so it has a publisher method.
The publisher method, which can be applied to a sequence, produces a publisher.
The map method (Combine's map, not Array's map) can be applied to a publisher, and produces another object that is a publisher.
The sink method can be applied to that, and produces a subscriber, and that's the end of the chain.

action does not wait till function call ends

I have 2 actions that i put in a sequence. In the first action I am calling a method to calculate the new waiting time for the next action. The next action is just a wait for this duration, but the second action always executes straight away, so the time must be 0. I debugged it and in the method spawnFlowers i get the time returned as 3.5 seconds.
these are my 2 actions
let spawnFlowerAction = SKAction.run {
self.WaitTime = self.calculateWaitingTime()
}
let waitForNewFlower = SKAction.wait(forDuration: self.WaitTime)
I execute it this way:
let spawnSeq = SKAction.sequence([spawnFlowerAction, waitForNewFlower])
let spawnRepeat = SKAction.repeat(spawnSeq, count: 4)
self.run(spawnRepeat)
Result: 4 times spawned without waiting, printing 4 different calculated times in the console from the calculateWaitingTime function (in which the spawning happens)
What is a good way to fix this?
The problem is trying to dynamically change the values used within SKActions after the action has been created. For example when your WaitTime variable changes while running the spawnFlowerAction, the waitForNewFlower Action's wait time won't change dynamically because it doesn't reference WaitTime. Instead its wait value is whatever your variable WaitTime was when you declared let waitForNewFlower = SKAction.wait(forDuration: self.WaitTime) (Which I'm guessing was initially 0). Same concept goes with your other two spawn actions.
I usually use the dispatch Queue for things like these, but to use SKActions here's a function. Just call it once and input the number of times you want it to repeat.
func spawnRepeat(count: Int) {
//Put whatever code to spawn flower here
print("SPAWN FLOWER")
if count > 1 {
//Recalculate WaitTime
WaitTime = calculateWaitingTime()
let waitAction = SKAction.wait(forDuration: WaitTime)
run(waitAction, completion: { self.spawnRepeat(count: count - 1) })
}
}

Are Swift4 variables atomic?

I was wondering if Swift 4 variables are atomic or not. So I did the following test.
The following is my test code.
class Test {
var count = 0
let lock = NSLock()
func testA() {
count = 0
let queueA = DispatchQueue(label: "Q1")
let queueB = DispatchQueue(label: "Q2")
let queueC = DispatchQueue(label: "Q3")
queueA.async {
for _ in 1...1000 {
self.increase()
}
}
queueB.async {
for _ in 1...1000 {
self.increase()
}
}
queueC.async {
for _ in 1...1000 {
self.increase()
}
}
}
///The increase() method:
func increase() {
// lock.lock()
self.count += 1
print(count)
// lock.unlock()
}
}
The output is as following with lock.lock() and lock.unlock() commented.
3
3
3
4
5
...
2999
3000
The output is as following with lock.lock() and lock.unlock uncommented.
1
2
3
4
5
...
2999
3000
My Problem
If the count variable is nonatomic, the queueA, queueB and the queueC should asynchronous call the increase(), which is resulted in randomly access and print count.
So, in my mind, there is a moment, for example, queueA and queueB got count equal to like 15, and both of them increase count by 1 (count += 1), so the count should be 16 even though there are two increasements executed.
But the three queues above just randomly start to count at the first beginning, then everything goes right as supposed to.
To conclude, my question is why count is printed orderly?
Update:
The problem is solved, if you want to do the experiment as what I did, do the following changes.
1.Change the increase() to the below, you will get reasonable output.
func increase() {
lock.lock()
self.count += 1
array.append(self.count)
lock.unlock()
}
2.The output method:
#IBAction func tapped(_ sender: Any) {
let testObjc = Test()
testObj.testA()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3) {
print(self.testObj.array)
}
}
Output without NSLock:
Output with NSLock:
[1,2,3,...,2999,3000]
No, Swift properties are not atomic by default, and yes, it's likely you'll run into multi-threading issues, where multiple threads use an outdated value of that property, a property which just got updated.
But before we get to the chase, let's see what an atomic property is.
An atomic property is one that has an atomic setter - i.e. while the setter does it's job other threads that want to access (get or set) the property are blocked.
Now in your code we are not talking about an atomic property, as the += operation is actually split into at least three operations:
get the current value, store it in a CPU register
increment that CPU register
store the incremented value into the property
And even if the setter would be atomic, we can end up in situation where two threads "simultaneously" reach #1 and try to operate on the same value.
So the question here should be: is increase() an atomic operation?
Now back to the actual code, it's the print call that "rescues" you. An increment-and-store operation takes a very short amount of time, while printing takes much longer. This is why you seem do not run into race conditions, as the window where multiple threads can use an outdated value is quite small.
Try the following: uncomment the print call also, and print the count value after an amount time larger enough for all background threads to finish (2 seconds should be enough for 1000 iterations):
let t = Test()
t.testA()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
// you're likely to get different results each run
print(t.count)
}
RunLoop.current.run()
You'll see now that the locked version gives consistent results, while the non-locked one doesn't.