1

I'm trying to develop a widget (today extension) which pass to main app a bunch of data.

I add this in info.plist

<key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>TodayWidget</string>
            </array>
            <key>CFBundleURLName</key>
            <string>xxx.xxx.xxx</string>
        </dict>
    </array>

and I call (successfully) the application from widget with this code

    let url = URL(string:"TodayWidget://?key=value")
    self.extensionContext?.open(url!, completionHandler: nil)

How I can access to these values?

I also saw this but xcode warns me that code is deprecated

Pass data between two Apps by url scheme in swift?

Thanks!

Community
  • 1
  • 1
Gianluca
  • 143
  • 1
  • 10

2 Answers2

1

first your scheme usage is wrong... CFBundleURLSchemes is to refer to your application from outside, not intended specifically for your extension. a better usage would be:

let url = URL(string:"yourAppName://TodayWidget?key=value")
let url = URL(string:"yourAppName://action?param1=value1&param2=value2")

then you can identify the source or action ... here's code to get a dictionary from your params (url is from application:openURL)

adapt the validations to your needs.

if (!url) return NO;
if ([url.absoluteString rangeOfString:@"://"].location == NSNotFound) return NO;
if ([url.absoluteString rangeOfString:@"?"].location == NSNotFound) return NO;

NSMutableDictionary* queryString = [NSMutableDictionary dictionaryWithCapacity:1];

__block NSMutableDictionary* paramDict = [[NSMutableDictionary alloc]init];
[paramDict setValue:[url scheme] forKey:@"protocol"];
[paramDict setValue:[url absoluteString] forKey:@"url"];
[paramDict setValue:[[url.absoluteString componentsSeparatedByString:@"://"][1] componentsSeparatedByString:@"?"].firstObject forKey:@"path"];
[paramDict setValue:queryString forKey:@"parameters"];

NSString* urlString = [url.absoluteString stringByRemovingPercentEncoding];
NSString* paramString = [urlString componentsSeparatedByString:@"?"][1];
NSArray* params = [paramString componentsSeparatedByString:@"&"];

for (NSString* param in params) 
{
    NSArray* paramArray = [param componentsSeparatedByString:@"="];
    if (paramArray.count != 2) {
        NSLog(@"Malformated url:%@", urlString);
        continue;
    }

    NSString* key = paramArray[0];
    NSString* value = paramArray[1];

    if (!key.length | !value.length) {
        NSLog(@"Malformated key %@ value %@ in url:%@", key, value, urlString);
        continue;
    }
    [queryString setValue:value forKey:key];
}
NSLog(@"%@", [paramDict toJSONString]);
altagir
  • 640
  • 8
  • 18
1

Try this:

 let url = URL(string:"TodayWidget://value")
 self.extensionContext?.open(url!, completionHandler: nil)

To access value in Containing App:

In AppDelegate, write this method:

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool
{
    if url.scheme == "NearbyRestaurantsTodayExtension"
    {
        if let value = url.host
        {
            //TODO: Write your code here
        }
    }
    return true
}
PGDev
  • 23,751
  • 6
  • 34
  • 88