Short summary of the simplified situation:
We have two applications, lets call them appA and appB. In appA, we have a button that allows you to either open the app store to download appB if appB is not installed, or open appB if it is installed. Every time appA is opened / resumed, it checks if appB is installed by performing a [[UIApplication sharedApplication] canOpenURL: <<appB's URL scheme>>], if the result is true, appA's button says "Open AppB", otherwise it says "Get AppB".
When appA's button is tapped, it does the canOpenURL check again, and either opens the App Store to appB, or opens appB via a deep link. Pretty simple stuff. Literally, the code is:
if ( [[UIApplication sharedApplication] canOpenURL:appBDeepLink] ) {
[[UIApplication sharedApplication] openURL: appBDeepLink];
} else {
[[UIApplication sharedApplication] openURL: appBAppStoreLink];
}
This all works as expected, however, if you change appB's installation state and go back to appA, the call to openURL freezes for 5-10 seconds on the next time it is tapped, before finally opening the URL.
For example, here are 2 scenarios to cause the freeze:
Scenario 1: Installing appB
1. User does not have appB installed
2. User opens appA
3. User taps "Get AppB"
4. User is brought to App Store and installs appB
5. User re-opens appA (brings it to foreground, it was never closed)
6. appA sees that appB is now installed, and changes it's button to "Open AppB"
7. User taps "Open AppB"
8. App freezes for 5-10 seconds
9. appA opens appB
Scenario 2: Uninstalling appB
1. User has appB installed
2. User opens appA
3. User taps "Open AppB"
4. appB is opened
5. User closes appB
6. User uninstalls appB
7. User re-opens appA (brings it to foreground, it was never closed)
6. appA sees that appB is now uninstalled, and changes it's button to "Get AppB"
7. User taps "Get AppB"
8. App freezes for 5-10 seconds
9. appA opens App Store
It almost seems like a given UIApplication instance doesn't update it's internal list of what apps can be opened via openURL until either the application is terminated / re-opened, or openURL is called again, and calling openURL causes the freeze as it re-configures it's internal list of what apps can be opened (I'm entirely speculating here, I don't know how this works under the hood). Regardless, the freeze is there, and I've tried numerous ways to get around it without any success, including:
- using GCD to dispatch to the main thread
- using GCD to dispatch to a background thread
- performing the openURL call after a short 0.1 second delay
- using NSThread's detachNewThreadSelector:toTarget:withObject to perform the call on a different thread
Nothing seems to work, the delay is always there until I close appB and re-open it. Searching online, there are some Stackoverflow posts that note this behavior starting in iOS 7, but their solutions (which are the solutions I've tried above) seem to be geared towards the overall delay of calling openURL from places you shouldn't be (in application:didFinishLaunching, for example), and I haven't been able to find anything specifcally about opening a URL after an app has been installed / uninstalled.
Has anyone else ran into this? Is there any solution?
Thanks,
- Adam