Crake
Crake

Reputation: 1679

How do I interrogate the current app's URL scheme programmatically?

My iOS app has 50+ targets, each with their own custom URL scheme. I need to detect if a request from a webview matches the scheme of the currently running app. In order to do this, I need to be able to interrogate the current app's URL scheme(s) from code.

Similar questions deal with attempting to interrogate other apps to discover their URL schemes, which seems like it is not possible. I need to find the scheme out for my own app, from within my app.

I would like to avoid having to set another plist value to the URL scheme and including that with the target.

Is there any way to get the URL scheme of the current app?

Upvotes: 9

Views: 7421

Answers (3)

Evgeny Karev
Evgeny Karev

Reputation: 613

Extension for Bundle swift 4 syntax

extension Bundle {

    static let externalURLSchemes: [String] = {
        guard let urlTypes = main.infoDictionary?["CFBundleURLTypes"] as? [[String: Any]] else {
            return []
        }

        var result: [String] = []
        for urlTypeDictionary in urlTypes {
            guard let urlSchemes = urlTypeDictionary["CFBundleURLSchemes"] as? [String] else { continue }
            guard let externalURLScheme = urlSchemes.first else { continue }
            result.append(externalURLScheme)
        }

        return result
    }()

}

Upvotes: 2

Naishta
Naishta

Reputation: 12383

In Swift 4 : Working version of getting the custom url scheme from Info.plist programmatically

func externalURLScheme() -> String? {
        guard let urlTypes = Bundle.main.infoDictionary?["CFBundleURLTypes"] as? [AnyObject],
            let urlTypeDictionary = urlTypes.first as? [String: AnyObject],
            let urlSchemes = urlTypeDictionary["CFBundleURLSchemes"] as? [AnyObject],
            let externalURLScheme = urlSchemes.first as? String else { return nil }

        return externalURLScheme
    }

(with the assumption that there is only 1 element in the urlTypes and urlSchemes array, hence taking the first element). Here is my plist entry of URL Scheme

enter image description here

Upvotes: 8

Crake
Crake

Reputation: 1679

This is the function I came up with to accomplish this.

- (BOOL)doesMatchURLScheme:(NSString *)scheme {
  if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"]) {
    NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
    for(NSDictionary *urlType in urlTypes)
    {
      if(urlType[@"CFBundleURLSchemes"])
      {
        NSArray *urlSchemes = urlType[@"CFBundleURLSchemes"];
        for(NSString *urlScheme in urlSchemes)
          if([urlScheme caseInsensitiveCompare:scheme] == NSOrderedSame)
            return YES;
      }

    }
  }
  return NO;
}

Upvotes: 12

Related Questions