0

I am trying to create a date scheduler to observe some event. But it does not work. I've looked through

protocol DateScheduler

and it is said that action will take place at currentDate in some methods protocol DateScheduler. I am trying doing this after 10 sec. Below is an example of my custom schedular.

class SomeDateScheduler : DateScheduler {
var currentDate: Date
init() {
    self.currentDate = Date(timeIntervalSinceNow: 10)
}

func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? {
    print(#function)
    print(date)
    return nil
}

func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? {
    print(#function)
    print(date)
    print(interval)
    print(leeway)
    return nil
}

func schedule(_ action: @escaping () -> Void) -> Disposable? {
    print(#function)
    return nil
}

}

and then I create bind to observe event

private func testSchedular() {
    let schedular = SomeDateScheduler()

    reactive.makeBindingTarget { appDeleg, value in
        print("SUCCESS")
        print(value)
        } <~ signalSchedular.observe(on: schedular)

    DispatchQueue.main.async { [observerSchedular] in
        observerSchedular.send(value: "Hello World")
        observerSchedular.sendCompleted()
    }
}

I am doing it into AppDelegate. ObserverSchedular and signalSchedular are global properties. Please, explain to me how to invoke all methods DateScheduler.

Zouhair Sassi
  • 1,403
  • 1
  • 13
  • 30
Taras
  • 1,485
  • 1
  • 16
  • 31

1 Answers1

0

I have already understood where I made mistake. To fix it I done next:

  1. Created custom observe(on: Schedular). So it looked like this (add these function in extension to Signal):
func customObserve(on scheduler: DateScheduler, interval: Int, leeway: Int) -> Signal<Value, Error> {
    return customFlatMapEvent(Signal.Event.observe(on: scheduler, interval: DispatchTimeInterval.seconds(interval), leeway: DispatchTimeInterval.seconds(leeway)))
}


func customFlatMapEvent<U, E>(_ transform: @escaping Event.CustomTransformation<U, E>) -> Signal<U, E> {
    return Signal<U, E> { output, lifetime in
        let input = transform(output.send, lifetime)
        lifetime += self.observe(input)
    }
}

also add this

extension Signal.Event {
    typealias CustomTransformation<U, E: Swift.Error> = (@escaping Signal<U, E>.Observer.Action, Lifetime) -> Signal<Value, Error>.Observer.Action
    
    static func observe(on scheduler: DateScheduler, interval: DispatchTimeInterval, leeway: DispatchTimeInterval) -> CustomTransformation<Value, Error> {
        return { action, lifetime in
            lifetime.observeEnded {
                scheduler.schedule {
                    action(.interrupted)
                }
            }

            return { event in
                scheduler.schedule(after: scheduler.currentDate, interval: interval, leeway: leeway) {
                    if !lifetime.hasEnded {
                        action(event)
                    }
                }
            }
        }
    }
}
  1. Created bind for observation in didFinishLaunchingWithOptions

    reactive.makeBindingTarget { appDeleg, value in
        print("SUCCESS")
        print(value)
        } <~ signalSchedular.customObserve(on: schedular, interval: 10, leeway: 1)
    
  2. And simulate async code


DispatchQueue.main.async { [observerSchedular] in
       observerSchedular.send(value: "Hello World")
       observerSchedular.sendCompleted()
}

  1. Defined global properties
private let (signalSchedular, observerSchedular) = Signal<String, Never>.pipe(),
let schedular = SomeDateScheduler()
  1. Changed custom date schedular
class SomeDateScheduler : DateScheduler {
    var currentDate: Date
    init() {
        self.currentDate = Date()
    }
    
    func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? {
        action()
        return nil
    }
    
    func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? {
        if case .seconds(let sec) = interval {
            let time = DispatchTime.now() + DispatchTimeInterval.seconds(sec)
            let queue = DispatchQueue(label: "sads", qos: .utility, attributes: .concurrent)
            queue.asyncAfter(deadline: time) { [weak self] in
                _ = self?.schedule(after: date) {
                    action()
                }
            }


            DispatchQueue.main.asyncAfter(deadline: time) { [weak self] in
                _ = self?.schedule(after: date) {
                    action()
                }
            }
        }
        return nil
    }
    
    func schedule(_ action: @escaping () -> Void) -> Disposable? {
        action()
        return nil
    }
}
Taras
  • 1,485
  • 1
  • 16
  • 31