To add delays in my tests I implemented this:
func execute(after: TimeInterval, testBlock: () -> Void) {
let result = XCTWaiter.wait(for: [expectation(description: "Delayed Test")], timeout: after)
if result == XCTWaiter.Result.timedOut {
testBlock()
} else {
XCTFail("Delay interrupted.")
}
}
Then I wrote a test:
func testExecute() {
var i = 1
DispatchQueue.main.asyncAfter(deadline: .now() + 0.40) {
i = 2
}
execute(after: 0.20) {
XCTAssert(i == 1)
}
execute(after: 0.15) {
XCTAssert(i == 1) // Fails once every three or four runs.
}
execute(after: 0.06) { // Never fails.
XCTAssert(i == 2)
}
}
Why does this second XCTAssert() fail regularly?
This is the only thing running on my simulator. You'd expect some jitter, but shouldn't that stay with 1 or 2 times the system clock period of 1/60s?
It turns out that delays may take up to considerably longer (up to 200ms in this 2011 experiment: http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/).
Must take sufficient margins when using this execute(after:testBlock:) function.
Related
I've this method :
func stepThree() {
operation = "prDatas"
let entries = self.data.componentsSeparatedByString("|***|")
total = entries.count
for entry in entries {
++current
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
self.registerDB(entry)
})
}
status.setProgress(Float(current/total), animated: true)
finishAll()
}
I want to perform registerDB function and update my progressBar when complete.
I tested several way but never succeed
EDIT 1
Implementing #Russell proposition, work perfectly, but calculating value inside dispatch_async block always result to 0
Is there an issue about operations and multithread ?
method :
func stepThree() {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
var current = 0
var total = 0
self.operation = "prDatas"
let entries = self.data.componentsSeparatedByString("|***|")
total = entries.count
for entry in entries {
++current
self.registerDB(entry)
dispatch_async(dispatch_get_main_queue(), {
print("value of 'current' is :" + String(current))
print("value of 'total' is :" + String(total))
print("Result is : " + String(Float(current/total)))
self.updateV(Float(current/total))
})
}
})
}
Console output :
value of 'current' is :71
value of 'total' is :1328
Result is : 0.0
Your code will update the status bar immediately - so the job will not have finished.
You need to move the update so that it actually follows the registerDB function, and then you have to make the call on the main thread. Here's an example - using dummy functions instead of your function calls, so that I can ensure it works as expected
func stepThree()
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let total = 5 // test data for demo
for entry in 0...total
{
// dummy function - just pause
sleep(1)
//self.registerDB(entry)
// make UI update on main queue
dispatch_async(dispatch_get_main_queue(),
{
self.setProgress(Float(entry)/Float(total))
})
}
})
}
func setProgress(progress : Float)
{
progressView.progress = progress
lblProgress.text = String(format: "%0.2f", progress)
}
I'm still getting started with ReactiveCocoa and functional reactive programming concepts, so maybe this is a dumb question.
ReactiveCocoa seem naturally designed to react to streams of live data, touch events or accelerometer sensor input etc.
Is it possible to apply finite impulse response filters in ReactiveCocoa in an easy, reactive fashion? Or if not, what would be the least-ugly hacky way of doing this? How would one go about implementing something like a simple moving average?
Ideally looking for an Swift 2 + RA4 solution but also interested in if this is possible at all in Objective C and RA2/RA3.
What you actually need is a some sort of period buffer, which will keep a period of values buffered and only start sending out when the buffer has reached capacity (the code below is heavenly inspired on takeLast operator)
extension SignalType {
func periodBuffer(period:Int) -> Signal<[Value], Error> {
return Signal { observer in
var buffer: [Value] = []
buffer.reserveCapacity(period)
return self.observe { event in
switch event {
case let .Next(value):
// To avoid exceeding the reserved capacity of the buffer, we remove then add.
// Remove elements until we have room to add one more.
while (buffer.count + 1) > period {
buffer.removeAtIndex(0)
}
buffer.append(value)
if buffer.count == period {
observer.sendNext(buffer)
}
case let .Failed(error):
observer.sendFailed(error)
case .Completed:
observer.sendCompleted()
case .Interrupted:
observer.sendInterrupted()
}
}
}
}
}
based on that you can map it to any algorithm you want
let pipe = Signal<Int,NoError>.pipe()
pipe.0
.periodBuffer(3)
.map { Double($0.reduce(0, combine: +))/Double($0.count) } // simple moving average
.observeNext { print($0) }
pipe.1.sendNext(10) // does nothing
pipe.1.sendNext(11) // does nothing
pipe.1.sendNext(15) // prints 12
pipe.1.sendNext(7) // prints 11
pipe.1.sendNext(9) // prints 10.3333
pipe.1.sendNext(6) // prints 7.3333
Probably the scan signal operator is what you're looking for. Inspired by Andy Jacobs' answer, I came up with something like this (a simple moving average implementation):
let (signal, observer) = Signal<Int,NoError>.pipe()
let maxSamples = 3
let movingAverage = signal.scan( [Int]() ) { (previousSamples, nextValue) in
let samples : [Int] = previousSamples.count < maxSamples ? previousSamples : Array(previousSamples.dropFirst())
return samples + [nextValue]
}
.filter { $0.count >= maxSamples }
.map { $0.average }
movingAverage.observeNext { (next) -> () in
print("Next: \(next)")
}
observer.sendNext(1)
observer.sendNext(2)
observer.sendNext(3)
observer.sendNext(4)
observer.sendNext(42)
Note: I had to move average method into a protocol extension, otherwise the compiler would complain that the expression was too complex. I used a nice solution from this answer:
extension Array where Element: IntegerType {
var total: Element {
guard !isEmpty else { return 0 }
return reduce(0){$0 + $1}
}
var average: Double {
guard let total = total as? Int where !isEmpty else { return 0 }
return Double(total)/Double(count)
}
}
I have a sequence of asynchronous methods defined like so:
func step1(input: Step1InputData, completion: (Step1OutputData -> Void)) { /* do something */ }
func step2(input: Step1OutputData, completion: (Step2OutputData -> Void)) { /* do something */ }
// etc...
As you can see, the output of step1 is the input of step2. These types all implement the StepData protocol:
protocol StepData {}
class Step1InputData : StepData { }
class Step1OutputData : StepData { }
class Step2OutputData : StepData { }
Finally, I have this custom operator:
infix operator => { associativity left }
func => <P:StepData, Q:StepData, R:StepData> (left:((P, Q -> Void) -> Void), right:((Q, R -> Void) -> Void)) -> ((P, R -> Void) -> Void) {
return { (x, completion) in
left(x, { y in
right(y, completion)
})
}
}
... which means I can write the following:
let combinedStep = step1 => step2
Which is great because it's super readable, and crucially it enforces type safety between the steps.
The problem is that I want to be able to persist the progress of a combinedStep. For example, step1 could be an image upload and step2 could be a local storage write. If step2 fails, the next time I try, I want to pick up where I left off, rather than re-uploading the image. Of course, there could be any number of steps chained together.
I could come up with a system that has an array of steps and manages the passing of data between steps and would be able to persist the progress, however, I can't think of a way to do this while still keeping the compile-time type safety.
Can someone with more experience of functional programming point me in the right direction?
I would suggest you look into frameworks like PromiseKit, BrightFutures, and ReactiveCocoa.
Those framework are in the same problem and solution space as you, asynchronous operations that need to be composed, and they all provide multiple ways to handle errors and retries.
If you like any of those you could adopt them in place of your custom implementation, and leverage the support of a big community of developers. Or you could just find inspiration from their code to bring back in your.
Enjoy
I think you need to make your operator right associative and pass an enum in the completion handler to allow for failure.
enum StepResult<Output> {
case Success(Output)
case Failure((StepResult<Output>->Void)->Void)
static func toFailHandlerWithInput<Input>(input: Input, processor: (Input,(StepResult<Output>)->Void)->Void) -> StepResult<Output> {
let handler : ((StepResult<Output>->Void)->Void) = { completion in
processor(input) { pout in
completion(pout)
}
}
return .Failure(handler)
}
}
infix operator => { associativity right }
func =><Input,Intermediate,Output>(left: (Input,(StepResult<Intermediate>)->Void)->Void, right: (Intermediate,(StepResult<Output>)->Void)->Void) -> (Input,(StepResult<Output>)->Void)->Void {
var mergedOp : ((Input,(StepResult<Output>)->Void)->Void)!
mergedOp = { input,completion in
left(input) { intermediate in
switch intermediate {
case .Success(let output):
right(output, completion)
case .Failure:
let failure = StepResult.toFailHandlerWithInput(input, processor: mergedOp)
completion(failure)
}
}
}
return mergedOp
}
var counter1 = 0
func step1(input: Int, completion: (StepResult<Double>)->Void) {
print("performing step 1...")
counter1 += 1
if ( counter1 > 1 ) {
print("Step 1 will succeed...")
let result = 2.0 * Double(input + counter1)
completion(.Success(result))
} else {
print("Step 1 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step1))
}
}
var counter2 = 0
func step2(input: Double, completion: (StepResult<Double>)->Void) {
print("performing Step 2...")
counter2 += 1
if ( counter2 > 2 ) {
print("Step 2 will succeed...")
let result = 3 * input + Double(counter2)
completion(.Success(result))
} else {
print("Step 2 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step2))
}
}
var counter3 = 0
func step3(input: Double, completion: (StepResult<Double>)->Void) {
print("performing Step 3...")
counter3 += 1
if ( counter3 > 1 ) {
print("Step 3 will succeed...")
let result = 4 * input + Double(counter3)
completion(.Success(result))
} else {
print("Step 3 fails...")
completion(StepResult.toFailHandlerWithInput(input, processor: step3))
}
}
func comboHandler(result: StepResult<Double>) {
switch result {
case .Success(let output):
print("output: \(output)")
case .Failure(let failHandler):
failHandler(comboHandler) // call again until success
}
}
let combinedSteps = step1 => step2 => step3
combinedSteps(5) { result in
comboHandler(result)
}
The answer to the specific question I asked here, in case it is useful to anyone else turned out to be to take a similar approach to Memoization. Strictly speaking, it is caching, rather than memoization, but the concept of wrapping the step function in another function that takes a cache key parameter is the same.
I have situation where-in i have to search IP address of **router ** and I know only it's range is from range 163.289.2.0 to 163.289.2.255.
I know this is not good way to search.
for i in 1... 255 {
var str = "163.289.2." + "i"
var tempIP = Ping.getIPAddress(str)
if(tempIP == true)
{
break;
}
}
Now my problem is my custom class Ping.getIPAddress() takes 3 seconds to get the result for a given IP value. So for 255 searches it takes approx 765 seconds (12.75 minutes). I have restriction that search should complete in max 2 minutes. So is there anyway i can achieve this in iPhone using swift.
I must use only this custom function Ping.getIPAddress() which gives true if given IP address exists else false.
Please provide me example or reference or approach to solve this issue .
Using NSOperationQueue with MaxConcurrentOperationCount set to 10 will be good ?
Synchronous approach
If we perform each call to Ping.getIPAddress(str) only after the previous one has completed of course we need to wait for (3 seconds * 256) = 768 seconds.
Asynchronous approach
On the other hand we can perform several concurrent calls to Ping.getIPAddress(str).
The fake Ping class
This is a class I created to test your function.
class Ping {
class func getIPAddress(str:String) -> Bool {
sleep(3)
return str == "163.289.2.255"
}
}
As you see the class does wait for 3 seconds (to simulate your scenario) and then returns true only if the passed ip is 163.289.2.255. This allows me to replicated the worst case scenario.
Solution
This is the class I prepared
class QuantumComputer {
func search(completion:(existingIP:String?) -> ()) {
var resultFound = false
var numProcessed = 0
let serialQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)
for i in 0...255 {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) {
var ip = "163.289.2." + "\(i)"
let foundThisOne = Ping.getIPAddress(ip)
dispatch_async(serialQueue) {
if !resultFound {
resultFound = foundThisOne
numProcessed++
if resultFound {
completion(existingIP:ip)
} else if numProcessed == 256 {
completion(existingIP: nil)
}
}
}
}
}
}
}
The class performs 256 asynchronous calls to Ping.getIPAddress(...).
The results from the 256 async closures is processed by this code:
dispatch_async(serialQueue) {
if !resultFound {
resultFound = foundThisOne
numProcessed++
if resultFound {
completion(existingIP:ip)
} else if numProcessed == 256 {
completion(existingIP: nil)
}
}
}
The previous block of code (from line #2 to #9) is executed in my queue serialQueue. Here the 256 distinct closures run synchronously.
this is crucial to ensure a consistent access to the variables resultFound and numProcessed;
on the other hand this is not a problem by a performance point of view since this code is pretty fast (just a bunch of arithmetic operations)
Test
And this is how I call it from a standard ViewController.
class ViewController: UIViewController {
var computer = QuantumComputer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
debugPrintln(NSDate())
computer.search { (existingIP) -> () in
debugPrintln("existingIP: \(existingIP)")
debugPrintln(NSDate())
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Conclusions
Finally this is the output when I test it on my iOS simulator. Please remind that this is the worst case scenario (since the last checked number is a valid IP).
2015-09-04 20:56:17 +0000
"existingIP: Optional(\"163.289.2.255\")"
2015-09-04 20:56:29 +0000
It's only 12 seconds!
Hope this helps.
So I have a function with a completion block that handles animation and a function calling that function. During the function call the completion block is seemingly skipped over because no print lines are printed. I have tried putting the code to be executed into the main queue but it has not yielded any results. Here is how I'm calling the function:
runAnimations(past.count, currentIteration: 0, animationsArray: past, completion: {
finished in
var randomr = self.randomInRange(0,hi: 3)
println("sell")
past.append(randomr)
for i in past123{
if(past.count >= 10){
}
else{
// have tried with and without dispatch_async.. neither print little did I know
dispatch_async(dispatch_get_main_queue()) {
println("little did I know")
self.incrementGame(past)
}
}
}
})
I know it is not an issue with the past.count if statement because the sell print line is not executed either. A breakpoint at the function call simply shows it skipping over however I am aware this is due to it being in an async thread.
Here is the code for runAnimations function:
func runAnimations(numberToIterate:Int, currentIteration:Int, animationsArray : [Int], completion: ((Bool) -> Void)?) {
UIView.animateWithDuration(1, animations: {
if(animationsArray[currentIteration] == 0){
self.label.text="circle!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 1){
self.label.text="square!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 2){
self.label.text="triangle!"
//self.label.alpha = 0.0
}
else if(animationsArray[currentIteration] == 3){
self.label.text="star!"
//self.label.alpha = 0.0
}
}, completion: {
finished in
println("BRO")
if(currentIteration+1>=numberToIterate){
self.label.alpha = 1.0
println("ook")
}
else{
println("okies")
self.runAnimations(numberToIterate, currentIteration: currentIteration+1, animationsArray: animationsArray, completion: { finished in
})
//self.runAnimations(numberToIterate, currentIteration: currentIteration+1, animationsArray: animationsArray)
}
})
The prints in runAnimation execute properly.
You actually have to call the completion block, which you haven't done by doing
completion(finished)
The completion block you defined can be seen as a separate method, which you need to call. In your case you have left your block as an optional so you must do optional checking as per the standard (completion != nil, etc)
This is a very "swift" guide on a completion block in swift, which is now called a closure. Take a look: here