In my app, I have implemented a private method in my AppDelegate
to override the default openURL:
method in order to open links inside my app within UIWebView
. But now I need the default functionalities in place too.
Here's what I did:
@implementation UIApplication (Private)
- (BOOL)customOpenURL:(NSURL*)url
{
AppDelegate *MyWatcher = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (MyWatcher.currentViewController) {
[MyWatcher.currentViewController handleURL:url];
return YES;
}
return NO;
}
@end
- (void)applicationDidBecomeActive:(UIApplication *)application {
Method customOpenUrl = class_getInstanceMethod([UIApplication class], @selector(customOpenURL:));
Method openUrl = class_getInstanceMethod([UIApplication class], @selector(openURL:));
method_exchangeImplementations(openUrl, customOpenUrl);
}
I also implemented handleURL:
in my class where the custom open URL handling was needed. However, this is hindering my other class in which I just want to do a simple open of an iTunes link in iTunes. So what I don't know how to achieve is how to use the original openURL:
in place of customOpenURL:
.
You can just subclass UIApplication
and override openURL:
directly. Be sure to change the principle class in your Info.plist
to use your UIApplication
subclass.
Example:
@interface ECApplication : UIApplication
@end
@implementation ECApplication
- (BOOL)openURL:(NSURL*)url
{
AppDelegate *MyWatcher = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if (MyWatcher.currentViewController) {
[MyWatcher.currentViewController handleURL:url];
return YES;
}
return NO;
}
@end
Then, in your Info.plist
file, look for the Principle Class key, and change the value to ECApplication
(or whatever you name your subclass).
You can set the original implementation to some other method and then just call it:
@implementation UIApplication (Private)
- (BOOL)originalOpenURL:(NSURL*)url
{
return NO;
}
- (BOOL)customOpenURL:(NSURL*)url
{
if (/* some condition */)
{
// your code
}
else
{
return [self originalOpenURL: url];
}
}
@end
- (void)applicationDidBecomeActive:(UIApplication *)application {
Method customOpenUrl = class_getInstanceMethod([UIApplication class], @selector(customOpenURL:));
Method openUrl = class_getInstanceMethod([UIApplication class], @selector(openURL:));
Method originalOpenUrl = class_getInstanceMethod([UIApplication class], @selector(originalOpenURL:));
method_exchangeImplementations(openUrl, originalOpenUrl);
method_exchangeImplementations(openUrl, customOpenUrl);
}
Note: This is just a solution giving direct answer to your question. The clearer approach to this problem is the one suggested by @edc1591. You can access original openURL:
with [super openURL:url]
.
The approach pointed out by Krizz works on the first app launch only, if you happen to open an URL that redirects you to another App (i.e.: Facebook app), it messes with the implementations when your app is resumed. Adding a flag to make sure the method_exchangeImplementations is called only on the first app launch seems to work.