1

How can I programmatically catch the case when completion does not execute?

I can not modify exists method, because this is a simple replacer for a Firebase observe.

func exists(completion: (_ a: Int) -> ()) {
   //async call with a completion handler where I get the `a` value
    if a % 2 == 0 {
        completion(a)
    }
    ..............//other cases
}

func check() {
    exists { a in
        print(a)
    }
}

I thought of some flag, but how do I know that exists ended?

Laura Calinoiu
  • 704
  • 1
  • 8
  • 24
  • @MartinR, you are right, the `arc4random` is not async - I've replaced with a comment there. In `exists` method there is async code, and the completion handler is called on just a case. – Laura Calinoiu Aug 14 '17 at 07:47
  • can you please provide some documentation link for usages of exists, if thats a firebase function, you can not modify that and hence it would great if you can provide link to what it does. Basically I want to find something which also accepts failure callback along with completion – JTeam Aug 14 '17 at 08:35
  • @JTeam, I will close this question, since my example is not good and people understood something else. But you are very close, this is my original question https://stackoverflow.com/questions/45668411/observers-completion-handler-not-called-how-to-check-in-code – Laura Calinoiu Aug 16 '17 at 08:51

2 Answers2

2

There's many ways of doing what you're trying to do, you could set flags (booleans), you could use optionals in the completion closure, you can use two closures...

I'm posting a way which I find the nicest, but it's purely subjective.

You could change the completion closure argument to be a Result enum for example.

enum Result {
    case .success(Int)
    case .failure
}

Then in the completion closure, you would replace the argument with this enum.

func exists(completion: (_ result: Result) -> ()) {
    let a = arc4random()
    if a % 2 == 0 {
        completion(.success(a))
    } else {
        //other cases
        completion(.failure)
    }
}

func check() {
    exists { result in
        switch result {
        case .succeess(let number):
            print(number)
        case .failure:
            print("Finished without number")
        }
    }
}
Dominik Hadl
  • 3,609
  • 3
  • 24
  • 58
  • I can not modify the `exists` function, which has some async in it. – Laura Calinoiu Aug 14 '17 at 07:45
  • `exists` is a placeholder for `observe` from Firebase – Laura Calinoiu Aug 14 '17 at 07:51
  • Ah, so you want to modify an existing function from Firebase? I am surprised, however, that the completion is not called in those other cases. Let me read up on the documentation. – Dominik Hadl Aug 14 '17 at 08:11
  • I don't want to modify it. I just want to know when completion handler does not execute. – Laura Calinoiu Aug 14 '17 at 08:13
  • https://stackoverflow.com/questions/45668411/observers-completion-handler-not-called-how-to-check-in-code – Laura Calinoiu Aug 14 '17 at 08:14
  • and this, https://stackoverflow.com/questions/36383368/remove-a-user-through-dashboard-but-the-user-is-still-logged-in – Laura Calinoiu Aug 14 '17 at 08:15
  • I am trying something with semaphores. If I have a timeout, I can logout. What do you think? – Laura Calinoiu Aug 14 '17 at 08:15
  • I think you are misunderstanding how does the `observe` function works - it's supposed to notify you whenever a value changes, it *doesn't really finish* executing, until you manually unsubscribe. Also, as a side note - it's not necessary to post multiple SO questions regarding the same topic :) – Dominik Hadl Aug 14 '17 at 08:22
  • Ok. It doesn't finish executing, you are right. But what I can do if a completion handler does not get executed? How can I know this? – Laura Calinoiu Aug 14 '17 at 08:27
  • Good question, if you are certain that the issue is within Firebase - ie. that the closure is not getting executed then I would file a bug report, otherwise let's move this discussion to the other question (where we can discuss the actual Firebase code) you've create as it is more Firebase related (I suggest you either close/delete or mark this question as answered). – Dominik Hadl Aug 14 '17 at 08:38
  • here is my Firebase question. https://stackoverflow.com/questions/45668411/observers-completion-handler-not-called-how-to-check-in-code/45709324#45709324 I ended up with a bug report on Firebase, and I've posted what the guys responded. Maybe will help someone. I'll close this question since the sample that I'm showing is not clear. – Laura Calinoiu Aug 16 '17 at 09:09
0

Best way to achieve what you want is to use DisptachGroup.

func exists(completion: (_ a: Int) -> ()) {
    completion(1)
}

let group = DispatchGroup()
group.enter()
exists { (a) in
    group.leave()
}
group.notify(queue: .main) { 
    print("Did finish 'exists' function!")
}
Ramis
  • 13,985
  • 7
  • 81
  • 100