How to swizzle UIApplication in iOS? - ios

I need to Swizzle UIApplication class methods especially "application:handleOpenURL:". I have added a category class of UIApplication. I have exchanged my own method with the original method but, it never triggered. The Swizzle class called very first time of app launch but, the swizzle method never triggered. I have attached the code for your reference.
- (BOOL) xxx_application: (UIApplication *) application handleOpenURL: (NSURL *) url {
NSLog(#"\n\n Swizzle handle open url..");
[self xxx_application:application handleOpenURL:url];
NSLog(#"URL: %#", url);
return YES; }
Can anyone please save my day? I tried of using some private library like "RSSwizzle" but, no help.

You don't need to swizzle this method, and it doesn't exist on UIApplication anyway. It is a method that is part of UIApplication's delegate protocol, meaning that (typically) your "app delegate" class should simply implement the method to have it called.

Related

How to monitor http requests from WKWebView?

So, it is pretty clear question I think. This question is about monitoring ajax requests. I tried it but didn't work as I wanted.
How can I call a function in my native iOS Obj-C application every time a request is sent, received and the browsing link is changed in WKWebView?
Ok, I found a way.
You can create a new class (let's call it MyURLProtocol) which has NSURLProtocol as subclass. Then add this function to MyURLProtocol:
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
NSLog(#"URL = %#", request.URL.absoluteString);
return NO;
}
This function will be called each time your webview makes a request. And then you need to register this protocol with the loading system. In your Appdelegate.m file include your class and add/replace didFinishLaunchingWithOptions function with this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NSURLProtocol registerClass:[MyURLProtocol class]];
return YES;
}
All set. Now you can edit canInitWithRequest function and do what you want with the request.

How to handle link data detector UITextView / Link embed in webview iOS 10

In our application we embed our SAFETY link in textview/webview as attached in the image. Before iOS 10 when tap is received
- openURL: method will be fired and we handle redirection as below.
- (BOOL)openURL:(NSURL *)url
{
if ([url shouldHandleLocally])
{
return [self openURLApp:url isFromOtherApp:NO];
}
return [super openURL:url];
}
Now in iOS 10 neither of this method fired -canOpenURL: -openURL: and in documentation it is mentioned
(BOOL)openURL:(NSURL*)url NS_DEPRECATED_IOS(2_0, 10_0, "Please use openURL:options:completionHandler: instead")
NS_EXTENSION_UNAVAILABLE_IOS("");
Even below method is not fired.
- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion {
}
How to handle this case ? Any help will be greatly appreciated.
If your link lives in a UITextView then you should use the textView(_:shouldInteractWith:in:interaction:) function of UITextViewDelegate. Your delegate will be able to catch the interaction with a link in the UITextView, you can then call your logic to handle the URL internally. Return NO from the delegate method to prevent iOS from opening the URL in its browser when appropriate.

Will I ever need the UIApplication* application from the ApplicationDelegate functions?

When would the application parameter in any of the app delegates not be equal to the shared instance?
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
UIApplication* sharedapp = [UIApplication sharedApplication];
if(application == sharedapp){
//things are as I expect
}else{
//some other situation I can't think of
}
}
No, there wouldn't be any situation like that.
From Documentation:
Every app has exactly one instance of UIApplication. When an app is launched, the system calls the UIApplicationMain function; among its other tasks, this function creates a singleton UIApplication object. Thereafter you access the object by calling the sharedApplication class method.
The call to [UIApplication sharedApplication] will always return a pointer to your app's shared application object. That's what the method is for.
What is the variable sharedApp you are comparing against? Presumably that's an instance variable that you defined and set to contain a pointer to your application object with an identical call to [UIApplication sharedApplication]?

What's the difference between [UIApplication sharedApplication] and application argument of didFinishLaunchingWithOptions?

I'm now learning about background fetch functionality in iOS 7 and Xcode 5, and I've read a few tutorials explaining how to set setMinimumBackgroundFetchInterval within application: didFinishLaunchingWithOptions: method.
One type of sample code I've read is the following one:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval: UIApplicationBackgroundFetchMinimum];
return YES;
}
And the other is the following, which utilizes the application argument to set its background initialization:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[application setMinimumBackgroundFetchInterval: UIApplicationBackgroundFetchMinimum];
return YES;
However, I don't get what makes one different from the other in the two codes above. The shareApplication class method returns UIApplication *, which is exactly the same as the type of the application argument.
And if there are NOT any differences between the two, what's the point of using the former? As far as I read, there are more samples taking the first approach, but I always feel the simpler is better (again, if there is NO difference - I think some differences exists, as mentioned above).
There are no diferences, using the method parameter is useful when you don't know which class sent that message (for example, imagine that you have several UITableView, all of them with the same delegate, you want to know which one called the delegate).
In this case, there's only one UIAplication per App, and that's the one that is in your [UIApplication sharedApplication] and the one that calls the delegate.
Summarising, is just the same object and there's no diference, just style.
Extending the example, imagine that you have a variable like this:
#property (nonatomic, strong) UITableView *myTable;
Yo do:
self.myTable.delegate = self;
When the delegate is called, theres are equivalents:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//self.myTable = tableView;
}
In this case, there is no difference.
It's probably a matter of style/preference as to which option you use.
I use [UIApplication sharedApplication].
There is no difference UIApplication is a singleton class and [UIApplication sharedApplication] is a way to access that shared variable of singleton class If you are calling the method from UIApplication class itself then using application is enough to access the method.

runtime added application:openURL not fires

For some reason I develop static library for facebook connection.
For proper process authorizated URL appDelegate should have
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
method.
So when I code it in appDelegate.mm file all works well, method invokes and facebook session become authorized.
But I have to add this method to delegate in runtime, so I use follow code:
{
NSString* methodDescription;
methodDescription = #"B#:####";
UIApplication* app = [UIApplication sharedApplication];
bool res = class_addMethod([app.delegate class], #selector(application:openURL:sourceApplication:annotation:), (IMP)applicationIMP, [methodDescription UTF8String]);
NSLog(#"Result of add method is %d", res);
}
//here is implementation of new method:
bool applicationIMP(id self, SEL _cmd, UIApplication *application, NSURL *url, NSString *sourceApplication, id annotation)
{
NSLog(#"Log from applicationIMP injected method");
return [[LibSocial sharedInstance] FacebookHandleOpenURL:url];
}
this code successfully adds method (I see this method when calls class_copyMethodList):
2013-02-04 23:02:00.704 LibSocialTest[38167:19a03] Mathod[0] is application:openURL:sourceApplication:annotation:
But Facebook SDK doesn't fire this method after authentication, and I got FBSessionState FBSessionStateClosedLoginFailed.
Why this method didn't fired?
Update:
Even if I replace normally implemented method with custom implementation at runtime, all works well and Facebook SDK fires new method implementation. But if I didn't code normally this method, but add it at runtime, it isn't fires.
Update2
If I add method to appDelegate class before instantiating UIApplication (in main.m file), then injected method works (even there are no default implementation of method in appDelegate.mm file), but if I inject method after UIApplication was created (so instance of appDelegate class was created too), then injection of method doesn't affect on already instantiated instances of class.

Resources