如何在 iOS 中管理被调用应用程序内的 openUrl 方法?
How to manage openUrl method inside called application in iOS?
我想这是重复的,但我想不通。
我必须使用 openUrl
方法从我的 iOS 应用调用其他应用。完成工作后,其他应用程序必须使用相同的方法 return 到我的应用程序。我想出了如何调用其他应用程序并打开我的应用程序。我的问题是如何拦截 return 到我的应用程序。我需要检查查询字符串中的值。
我发现方法 handleOpenURL
拦截了 return 并且我可以处理我的查询字符串。
我被卡住了 - 如何在我的 ViewController 中使用该信息?我在 viewDidLoad
中设置了断点,但没有命中。我必须使用哪种方法?
编辑:
我的代码是(在AppDelegate
内):
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"url recieved: %@", url);
NSLog(@"query string: %@", [url query]);
NSLog(@"host: %@", [url host]);
NSLog(@"url path: %@", [url path]);
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
return YES;
}
- (NSDictionary *)parseQueryString:(NSString *)query {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:6];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for (NSString *pair in pairs) {
NSArray *elements = [pair componentsSeparatedByString:@"="];
NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dict setObject:val forKey:key];
}
return dict;
}
效果很好。
我的 ViewController (VC):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setNeedsStatusBarAppearanceUpdate];
// Instantiate App singleton
singApp = [PESsingApplication sharedInstance];
@try {
// Localize resources using currently saved setting for language
[self setLocalizedResources];
// Init visual buttons
[self baseInit];
// Add code for keyboard management
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardHide:)
name:UIKeyboardWillHideNotification
object:nil];
CGRect screenRect = [[UIScreen mainScreen] bounds];
_screenHeight = screenRect.size.height;
_screenWidth = screenRect.size.width;
}
@catch (NSException *exception) {
[self throwUnknownException:exception];
}
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
我的url:
URL 标识符:xx.mydomain.MyUrlScheme
URL 场景:MyUrlScheme
我的 VC
中有断点(在上面显示的每个方法中)。
我使用以下字符串调用其他应用程序:@"otherApp://openApp?param1=value1&callbackUrl=MyUrlScheme";
他们使用 callbackUrl
参数从 otherApp 呼叫我。
需要自己定制URL,请往下看
How to implement Custom URL Scheme
定义应用程序的自定义 URL 方案全部在 Info.plist 文件中完成。单击文件中的最后一行,然后单击右侧的“+”号以添加新行。 Select URL 新项目的类型。添加后,单击 "URL Types" 旁边的灰色箭头以显示 "Item 0"。将您的 URL 标识符设置为唯一的字符串 - 类似于 com.yourcompany.yourappname.
设置 URL 标识符后,select 该行并再次单击“+”号,并为 URL 方案添加一个新项目。然后单击 "URL Schemes" 旁边的灰色箭头以显示 "Item 0"。将项目 0 的值设置为您的 URL 方案名称。
处理自定义 URL 呼叫
为了让您的应用程序在收到自定义 URL 调用时做出响应,您必须在应用程序委托 class:
中实现 application:handleOpenURL 方法
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// your code
}
解析自定义 URL
URL有几个部分:
方案://host/path?查询
URL 的部分可以通过传递给 application:handleOpenURL 方法的 NSURL 对象来检索。如果你有一个相当简单的 URL 命名方案并且想要允许访问特定的 pages/keys,你可以只使用主机名:
[url 主机的自定义 URL 值:
myapp://page1 page1
myapp://page2 page2
myapp://otherPage otherPage
要将数据传递到您的应用程序,您需要使用查询字符串。这是从 url:
解析查询字符串的简单方法
- (NSDictionary *)parseQueryString:(NSString *)query {
NSMutableDictionary *dict = [[[NSMutableDictionary alloc] initWithCapacity:6] autorelease];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for (NSString *pair in pairs) {
NSArray *elements = [pair componentsSeparatedByString:@"="];
NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dict setObject:val forKey:key];
}
return dict;
}
测试自定义 URL
您可以在模拟器中轻松测试您的 URL 方案。只需在您的其中一个视图中添加一个测试按钮,并按如下方式为其实现 IBAction 方法:
- (IBAction)getTest:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"myappscheme://test_page/one?token=12345&domain=foo.com"]];
}
然后在您的应用委托中,实现 application:handleOpenURL 方法:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"url recieved: %@", url);
NSLog(@"query string: %@", [url query]);
NSLog(@"host: %@", [url host]);
NSLog(@"url path: %@", [url path]);
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
return YES;
}
最后,如果您正在寻找可以在任何地方接收数据的方法,您可以使用这两种方案。
您可以简单地使用 Local notification or NSUserDefault
NSUserDefault
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSUserDefaults *userDefaults=[[NSUserDefaults alloc] init];
[userDefaults synchronize];
NSString *status = [defaults stringForKey:@"any status"];
}
本地通知
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:VAL, @"value", nil];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
如果您的 viewDidLoad
没有被完美调用,请尝试使用 viewWillAppear
或 viewDidAppear
方法。
示例目的:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
// add dictionary to standardUserDefaults for saving purpose, like
[[NSUserDefaults standardUserDefaults] setObject:dict forKey:@"DicKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
// add code for navigation/present view controller
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main"
bundle: nil];
YourViewController *yourController = (YourViewController *)[mainStoryboard
instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
self.window.rootViewController = yourController;
return YES;
}
用于检索
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSMutableDictionary *mutableRetrievedDictionary = [[[NSUserDefaults standardUserDefaults] objectForKey:@"DicKey"] mutableCopy];
// here parse the dictionary and do your work here, when your works is over
// remove the key of standardUserDefaults
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"DicKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
将来自其他应用的状态存储在 NSUserdefaults
中,当您的应用 ViewController 启动时,将状态从 NSUserdefaults
中提取到 NSString 中并将其提升为警报。
在appdelegate
中调用handleopenURL
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSUserDefaults *defaults=[[NSUserDefaults alloc] init];
[defaults synchronize];
NSString *status = [defaults stringForKey:@"status string from other app"];
}
我想这是重复的,但我想不通。
我必须使用 openUrl
方法从我的 iOS 应用调用其他应用。完成工作后,其他应用程序必须使用相同的方法 return 到我的应用程序。我想出了如何调用其他应用程序并打开我的应用程序。我的问题是如何拦截 return 到我的应用程序。我需要检查查询字符串中的值。
我发现方法 handleOpenURL
拦截了 return 并且我可以处理我的查询字符串。
我被卡住了 - 如何在我的 ViewController 中使用该信息?我在 viewDidLoad
中设置了断点,但没有命中。我必须使用哪种方法?
编辑:
我的代码是(在AppDelegate
内):
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"url recieved: %@", url);
NSLog(@"query string: %@", [url query]);
NSLog(@"host: %@", [url host]);
NSLog(@"url path: %@", [url path]);
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
return YES;
}
- (NSDictionary *)parseQueryString:(NSString *)query {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:6];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for (NSString *pair in pairs) {
NSArray *elements = [pair componentsSeparatedByString:@"="];
NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dict setObject:val forKey:key];
}
return dict;
}
效果很好。
我的 ViewController (VC):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setNeedsStatusBarAppearanceUpdate];
// Instantiate App singleton
singApp = [PESsingApplication sharedInstance];
@try {
// Localize resources using currently saved setting for language
[self setLocalizedResources];
// Init visual buttons
[self baseInit];
// Add code for keyboard management
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardHide:)
name:UIKeyboardWillHideNotification
object:nil];
CGRect screenRect = [[UIScreen mainScreen] bounds];
_screenHeight = screenRect.size.height;
_screenWidth = screenRect.size.width;
}
@catch (NSException *exception) {
[self throwUnknownException:exception];
}
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
我的url:
URL 标识符:xx.mydomain.MyUrlScheme
URL 场景:MyUrlScheme
我的 VC
中有断点(在上面显示的每个方法中)。
我使用以下字符串调用其他应用程序:@"otherApp://openApp?param1=value1&callbackUrl=MyUrlScheme";
他们使用 callbackUrl
参数从 otherApp 呼叫我。
需要自己定制URL,请往下看
How to implement Custom URL Scheme
定义应用程序的自定义 URL 方案全部在 Info.plist 文件中完成。单击文件中的最后一行,然后单击右侧的“+”号以添加新行。 Select URL 新项目的类型。添加后,单击 "URL Types" 旁边的灰色箭头以显示 "Item 0"。将您的 URL 标识符设置为唯一的字符串 - 类似于 com.yourcompany.yourappname.
设置 URL 标识符后,select 该行并再次单击“+”号,并为 URL 方案添加一个新项目。然后单击 "URL Schemes" 旁边的灰色箭头以显示 "Item 0"。将项目 0 的值设置为您的 URL 方案名称。
处理自定义 URL 呼叫
为了让您的应用程序在收到自定义 URL 调用时做出响应,您必须在应用程序委托 class:
中实现 application:handleOpenURL 方法- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// your code
}
解析自定义 URL
URL有几个部分:
方案://host/path?查询
URL 的部分可以通过传递给 application:handleOpenURL 方法的 NSURL 对象来检索。如果你有一个相当简单的 URL 命名方案并且想要允许访问特定的 pages/keys,你可以只使用主机名:
[url 主机的自定义 URL 值:
myapp://page1 page1
myapp://page2 page2
myapp://otherPage otherPage
要将数据传递到您的应用程序,您需要使用查询字符串。这是从 url:
解析查询字符串的简单方法- (NSDictionary *)parseQueryString:(NSString *)query {
NSMutableDictionary *dict = [[[NSMutableDictionary alloc] initWithCapacity:6] autorelease];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for (NSString *pair in pairs) {
NSArray *elements = [pair componentsSeparatedByString:@"="];
NSString *key = [[elements objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *val = [[elements objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[dict setObject:val forKey:key];
}
return dict;
}
测试自定义 URL
您可以在模拟器中轻松测试您的 URL 方案。只需在您的其中一个视图中添加一个测试按钮,并按如下方式为其实现 IBAction 方法:
- (IBAction)getTest:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"myappscheme://test_page/one?token=12345&domain=foo.com"]];
}
然后在您的应用委托中,实现 application:handleOpenURL 方法:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSLog(@"url recieved: %@", url);
NSLog(@"query string: %@", [url query]);
NSLog(@"host: %@", [url host]);
NSLog(@"url path: %@", [url path]);
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
return YES;
}
最后,如果您正在寻找可以在任何地方接收数据的方法,您可以使用这两种方案。 您可以简单地使用 Local notification or NSUserDefault
NSUserDefault
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSUserDefaults *userDefaults=[[NSUserDefaults alloc] init];
[userDefaults synchronize];
NSString *status = [defaults stringForKey:@"any status"];
}
本地通知
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
UILocalNotification *localNotif = [[UILocalNotification alloc] init];
if (localNotif == nil)
return;
localNotif.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:VAL, @"value", nil];
[[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}
如果您的 viewDidLoad
没有被完美调用,请尝试使用 viewWillAppear
或 viewDidAppear
方法。
示例目的:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
NSDictionary *dict = [self parseQueryString:[url query]];
NSLog(@"query dict: %@", dict);
// add dictionary to standardUserDefaults for saving purpose, like
[[NSUserDefaults standardUserDefaults] setObject:dict forKey:@"DicKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
// add code for navigation/present view controller
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main"
bundle: nil];
YourViewController *yourController = (YourViewController *)[mainStoryboard
instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
self.window.rootViewController = yourController;
return YES;
}
用于检索
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSMutableDictionary *mutableRetrievedDictionary = [[[NSUserDefaults standardUserDefaults] objectForKey:@"DicKey"] mutableCopy];
// here parse the dictionary and do your work here, when your works is over
// remove the key of standardUserDefaults
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"DicKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
将来自其他应用的状态存储在 NSUserdefaults
中,当您的应用 ViewController 启动时,将状态从 NSUserdefaults
中提取到 NSString 中并将其提升为警报。
在appdelegate
handleopenURL
- (BOOL)application:(UIApplication *)application handleopenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSUserDefaults *defaults=[[NSUserDefaults alloc] init];
[defaults synchronize];
NSString *status = [defaults stringForKey:@"status string from other app"];
}