1

We can get the application state in iOS through UIApplication.shared.applicationState and it has to be done from main queue.

So, if we want to create a function that would return an application state or something similar to that, we need to assure two things:

  • UIApplication is being accessed from the main queue
  • Everything is synchronous inside the function

I came up with one approach. I don't know if it's correct or not.

TLDR: I need to know if the following approach is ok or if there is a better approach than this one to get the application state in iOS. Moreover, is it proper to use Thread.isMainThread to check whether the execution is being performed on the main queue?

func isInBackground() -> Bool {
        var isInBackground = true

        // If accessed from main queue, don't need to synchronously get this value through the main queue. Otherwise it would just lock the UI or maybe, crash.
        if Thread.isMainThread {
            return UIApplication.shared.applicationState == .background
        } else {
            DispatchQueue.main.sync {
                isInBackground = UIApplication.shared.applicationState == .background
            }
        }

        return isInBackground
}
Shubhashis
  • 10,411
  • 11
  • 33
  • 48

1 Answers1

1

You haven’t written the method as neatly as you might have, but your logic for ensuring that you talk to the application only on the main queue while returning the result on the same queue you were called on is exactly right. You’re probably concerned about your use of DispatchQueue.main.sync but the way you are using it is the only way one would ever use it — you need to get on and off the main queue but you mustn’t block the main queue if you’re already on it.

If there’s anything I’d question it’s why you need to push this logic down to this method. The implication is that this method can itself be called indiscriminately from different queues, which suggests a failure of logic or structure higher up the calling chain. Testing for what queue you’re on is arguably a bad smell and not, itself, thread-safe; you should always know what queue you’re on because each method should always be called on the same queue.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Actually, I had another confusion. I don't know if it's proper to use `Thread.isMainThread` to check whether it's being run on the main queue or not. – Shubhashis Oct 23 '19 at 11:33
  • Well, that is what my second paragraph criticizes. There is no thread safe way to behave differently depending what thread you’re on. That is why GCD provides no way to do it. You can arrange to crash if you’re on the wrong thread, with `dispatchPrecondition`, but that wouldn’t help you here. That is why I say you should not be in a situation like this in the first place. – matt Oct 23 '19 at 11:40
  • However, if the question is, is this sort of thing done?, then the answer is clearly yes, as shown by many answers on SO that demonstrate doing it, e.g. https://stackoverflow.com/a/5226271/341994. Perhaps I should have marked this as a duplicate. – matt Oct 23 '19 at 13:21