ios: dynamically loading functions on app delegate - ios

Is it possible in IOS to dynamically load/create a function on a class at runtime?
I'm specifically thinking for example of adding a class the the app delegate at runtime, but I'm not sure it is even possible in the language?
For instance, this is used for push notifications, but could it be added dynamically by a Push framework behind the scenes at runtime?
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
....
}
As an alternative, could it simply be defined in the framework, outside the app delegate file, but still a part of the app delegate logic?

Both are options.
Dynamically adding methods, is via a C function called class_addMethod. You can even change an existing method (and still use the original!), it's called method swizzling. You can read the Apple documentation, or google for other examples. Note that you will need something in the program to at least touch your library to get it loaded (if you put the swizzling in your class's +initialize method), and it's probably easiest overall to just have the user initialize your library with something along the lines of [MYLibrary applicationLaunchedWithDelegate:self launchOptions:launchOptions].
If you know the class you need to add the method to, you can use a category.

you can put your self as app delegate and bypass all received delegates to old one for backward compatibility.here is a pseudo code.
1)by default we have this wiring:
ios -> appdelegate.m
now you need to put your self in the middle like :
ios -> framework -> appdelegate.m
2)so you can do it by set old delegate to another variable like:
(in your framework delegate)
self.oldDelegate = [UIApplication sharedApplication].delegate;
and set yourself as application delegate:
[[UIApplication sharedApplication] setDelagate:self];
3)for backward compatibility you need to bypass all delegates to oldDeleagete
4)warning:this is pseudo code to give you the idea but remember you need to take care of multi threading of your app may be there is another framework like you and both are changing app delegates but will get wrong oldDelegate and your wiring will not work .so pay more attention to these kind of stuffs.look at this

Related

ios - swizzling of firebase cloud messing

I am working with an app using Firebase Cloud Messaging for Push Notification. After reading its documentation, I have a little confuse about "Swizzling disabled", I tried to find some tutorials which are talking about it, but unfortunately there is no any tutorials. Could you please help me to describe what exactly "swizzling" mean? and what is case we need to use it?
Thank you so much.
Ryan
Method swizzling means that you change the implementation of a given function at runtime.
It is often used when you don't have access to the code of the function or if you don't want to modify the code of a library and when inheritance doesn't apply.
Basically what Firebase does: you don't have access to the Push Notifications API/functions except for the delegates that Apple exposes. By swizzling such a function, you can add some logic to what it is currently doing. (You can still call the "previous" function like you would do with super or completely replace its original purpose).
This is how Firebase asks you to activate PUSH Notifications. It makes it easier for you to add it in your code and give Firebase a lot of flexibility as with one line in your AppDelegate they can run whatever they want.
NB: A simple example: you don't have access to the print function, you can just use it. Instead of wrapping the print function in a custom function and replacing its usage everywhere; you could swizzle print with one of your custom function to extend or replace its original functionality. As it is applied at runtime, you wouldn't have to change anything in your project and all print calls would be "redirected" to your new custom function.

iOS - Correct way to "listen" for a delegate method from within a class

I've just implemented the CLLocationManager in my AppDelegate, which is currently printing the location whenever it's updated.
What I'm trying to do now is trigger a method in one of my view controllers whenever that location is updated.
I've done something similar before using protocol, but I'm not sure if that's possible with the AppDelegate.
I'm working in Swift, but an Objective-C response would also be helpful as I'm looking for the logic behind how to achieve this.
You can post notifications to NSNotificationCenter from your application delegate (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/) and subscribe to in in your controller (do not forget to unsubscribe in dealloc). Just make sure you do not update any GUI when application is in background (you can check state directly in controller).

Where is the correct place to make HTTP requests in iOS?

I have an app that fetches data from a server using NSURLSessionDataTask. As of right now I am starting my HTTP GET Request in the init method of the UIViewController that displays the data. Is this the best/smartest place to kick off an HTTP request? If not, where should I do it?
I'm asking this question because when I exit my app and it goes into the background (and is not killed) and then re-open my application, the HTTP request is not fired off (because it is in the UIViewControllers init method) and the data being displayed is not up to date with what's on the server. I've tried putting it in viewDidLoad but this method is not called upon entering the foreground, neither is viewWillAppear nor viewDidAppear.
Should I be doing all of my HTTP requests in one of the UIApplications life cycle methods in my appDelegate?
In short, where is the best place to make HTTP requests in iOS?
Thank you, I can post code or explain more if needed.
first off, this is a huge question and probably impossible to answer fully here, but hopefully I can point you in the right direction so you can learn how to fish. :)
To stick to the Model-View-Controller paradigm, you will want to create a separate object for making your HTTP requests. An HTTP request would be considered part of your model. The benefit of this is being able to use your model in other iOS apps you create, for example.
As for where to put all of this stuff and what's the best design.... One thing that strikes me in your question is you want the data being displayed in your app to be up to date with what is on the server. On a high level, a really good way to do this is to use iOS's ability to multitask and perform functions for you when you app is in the background. You would need to register with the OS as an app that performs fetches to a server in the background.
According to Apple's documentation, "In Xcode 5 and later, you declare the background modes your app supports from the Capabilities tab of your project settings. Enabling the Background Modes option adds the UIBackgroundModes key to your app’s Info.plist file." From there you would need to research the UIApplicationDelegate's protocol methods – application:performFetchWithCompletionHandler: and -application:handleEventsForBackgroundURLSession:completionHandler:.
Also, you will need to look into NSURLSession a little more. If you want to use background fetching, NSURLSessionDataTask is not supported. You will need to use NSURLSessionDownloadTask, save the response to a file and process it however you need to. Also, as the app delegate method name above implies, you will need to read the NSURLSessionConfiguration Class Reference, specifically about backgroundSessionConfiguration.
The really cool thing about all of this is, after you have implemented it, your app UI will be up to date for the user – even if your app was killed by the user or by the OS. Pretty nifty.
Good luck and hope this all helps. I hope I didn't miss any other big pieces here.
I think it a personal preference. So I personally do it on the model objects. Lets say I have a Car object and a ShowroomViewController. I always declare a class method to Car object to call service to get all the cars.
#interaface Car
+(void)fetchCarsWithCompletionHandler:(void (^)(NSArray* cars, NSError *error ))handler;
-(void)getDetailsWithCompletionHandler:(void (^)(Car* car, NSError *error ))handler;
#end
Then call the class method on viewWillAppear(If I need to update the cars very often) or viewDidload(If I need to call the service once).
The other trick I mostly do is define a flag in the view controller like
#interface ShowroomViewController
#property(assign)BOOL needsModelUpdate;
#end
and I update the modal conditionally.
#implementation ShowroomViewController
-(void)viewWillAppear:(BOOL)animated{
if(self.needsModelUpdate){
[self fetchModel]
}
}
-(void)fetchModel{
__block __weak ShowroomViewController *weakRef=self;
[Car fetchCarsWithCompletionHandler:^(NSArray *cars, NSError *error) {
[weakRef setCars:cars];
[weakRef.tableView reloadData];
}];
}
#end
The reason I define this flag is I can change it somewhere else lets say applicationDidEnterBackground: method the change the flag. Or you can use KVO but I always find it overkill .
Do it however you want.
Personally, I create a class specifically for all communication with the server. Actually, my App has around 20 classes for different parts of the communication process. But yours is probably less complicated.
Add an instance of the class as an object in an xib file or else create an instance of it inside the app delegate's init method.
Use didEnterForeground to tell the other class that it needs to do it's stuff, but still use the init method to create an instance of the class.

Tracking/Instrumenting events/methods fired

I am trying to print out (e.g., NSLog) the information about events that fired on iPhone application. For example user executes a scenario and I want to track all the methods called and events clicked by the user.
Is there anyway to do that using a category extension and method swizzling features of objective-C to inject some code to log and print the information needed? Right now, I defined a category for UIWindow, UIApplication and UIView. I am not sure where is the best place to track tho, e.g., [UIWindow sendEvent:]? Should I observe objc_msgSend()?
I basically want to instrument a project and inject code with category extension in order to not change the source code as much as possible.

How to prevent iOS app launching whilest defining protocol handling

I have successfully implemented urlHandling of a self-defined protocol.
I need to prevent the app from launching when other apps try to call this url for security issues. The protocol is only needed for a callback from executed JavaScript-code, so only calls within the app are allowed.
To use the response of UIWebView:stringByEvaluatingJavascriptFromString is not an option because the JS code has to work on multiple platforms.
I thought of intercepting the call itself within my app (which would work by using UIWebViewDelegate:shouldStartLoadWithRequest) but I could not figure out if that is possible with WP8. (In Android this would work with WebViewClient:shouldOverideUrlLoading)
How about implementing the UIApplicationDelegate protocol method:
application:openURL:sourceApplication:annotation:
and checking sourceApplication?
As far as I know, there is no standard API on iOS to have something like a "white-list" for which apps are allowed to call your custom URL scheme and open your app this way. When using this URL schemes, you can only have the whole cake, not just a small piece.
Suggestion A:
You could set a boolean variable in your app delegate to store if openURL was initiated from your app or another, in your view controller check if this variable is set to NO and exchange the rootViewController of your apps' window with a blank screen or an info screen telling the user that the app was not opened from a trusted source or whatever.
Suggestion B:
If you really don't want your app to open, you could make it crash in application:openURL:sourceApplication:annotation:.
Just check if the sourceApplication is a trusted source and if not use something like NSAssert(YES == NO, #"Bad bad boy") to make it crash.
B would only be a hack and I would not consider it best practice. Try suggestion A, it is a much more user-friendly way and you should be able to achieve your goal.
finally I've found a solution that works for me. ;) It's a different approach, though.
First: you might want to check out WebViewJavascriptBridge, thats a Bridge for communication in both directions implementing callbacks and everyhting you might need. But that is working with iframes... I wanted to use ajax.
I'm not implementing a protocol that my app is going to listen to. What I do now is implement a NSURLProtocol, which will allways return NO for canInitWithRequest. I am using a unique path (like /!anythingUnique) to identify my JS-Calls. With that set up I can call ajax and do stuff in the Obj-C code.
implement NSURLProtocol.
register NSURLProtocol via [NSURLProtocol registerClass:[SFJURLProtocol class]];.
you will need to set a baseURL... do that by loading any page or or via webView:loadHTMLSString. Do that when you initialize the controller.
fire Requests from JavaScript
catch them in your canInitWithRequestfunction. You might want to do stuff in the Controller for the sake of clean code, so think of a callback mechanism or something. ;)
???
Profit!
I hope this helps.

Resources