Before doing a openUrl:
to launch an app that should callback my app (like an app that acts according to the x-callback-url specification), how can I programmatically check that my application callback is working, before calling the other app?
Asked
Active
Viewed 4,226 times
7

Filip Radelic
- 26,607
- 8
- 71
- 97

João Portela
- 6,338
- 7
- 38
- 51
3 Answers
12
This is my current solution:
- (BOOL) respondsToUrl:url
{
BOOL schemeIsInPlist = NO; // find out if the sceme is in the plist file.
NSBundle* mainBundle = [NSBundle mainBundle];
NSArray* cfBundleURLTypes = [mainBundle objectForInfoDictionaryKey:@"CFBundleURLTypes"];
if ([cfBundleURLTypes isKindOfClass:[NSArray class]] && [cfBundleURLTypes lastObject]) {
NSDictionary* cfBundleURLTypes0 = [cfBundleURLTypes objectAtIndex:0];
if ([cfBundleURLTypes0 isKindOfClass:[NSDictionary class]]) {
NSArray* cfBundleURLSchemes = [cfBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"];
if ([cfBundleURLSchemes isKindOfClass:[NSArray class]]) {
for (NSString* scheme in cfBundleURLSchemes) {
if ([scheme isKindOfClass:[NSString class]] && [url hasPrefix:scheme]) {
schemeIsInPlist = YES;
break;
}
}
}
}
}
BOOL canOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]];
return schemeIsInPlist && canOpenUrl;
}
The limitation is that we are checking that this app registered for the scheme and some application responds to that url.
AFAIK this does not guarantee that your application is the actual responder for that scheme (in the case where another app also registered for that scheme).
From what I tried, it seems that iOS opens the first installed app for each unique url scheme.

João Portela
- 6,338
- 7
- 38
- 51
-
Ah, now I understand a bit better. There is no way to know for certain prior to opening an URL what will happen when you open that URL. There is no LaunchServices interface on iOS to query. – Rob Napier Aug 30 '11 at 14:01
-
I decided to accept my answer since it seems that this is the best method available (although it is not 100% reliable). – João Portela Sep 06 '11 at 09:28
0
A simpler solution:
+ (BOOL)isBundleURL:(NSURL *)url
{
NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
NSArray *urlSchemes = [urlTypes.firstObject objectForKey:@"CFBundleURLSchemes"];
return [urlSchemes containsObject:url.scheme];
}
+ (BOOL)respondsToURL:(NSURL *)url
{
return [self isBundleURL:url] && [[UIApplication sharedApplication] canOpenURL:url];
}

Tyler Sheaffer
- 1,953
- 1
- 16
- 16
-1
Here is how I solved it in Swift:
var plistPath = NSBundle.mainBundle().pathForResource("Info", ofType: "plist")
var urlStuff = NSMutableDictionary(contentsOfFile: plistPath!)
var urlType = NSDictionary(objectsAndKeys: "com.appprefix.AppName", "CFBundleURLName", NSArray(object: "fb123456789"), "CFBundleURLSchemes")
urlStuff?.setObject(NSArray(object: urlType), forKey: "CFBundleURLTypes")
urlStuff?.writeToFile(plistPath!, atomically: true)

Esqarrouth
- 38,543
- 21
- 161
- 168
-
This can never work on a real iOS device since an app's bundle (and its Info.plist) is read-only. – HangarRash May 30 '23 at 17:40