intercept all objective c method calls - ios

I wish to insert hooks whenever a method is called in my iOS app. So lets say there is a selector X, I wish to log "Method X starting" before the method executes, and then log "Method X ended" after the execution. I am aware of an approach where I can swizzle the implementation of sel X with the one which has the hook before and after the call to "itself", so that I can be notified when the method has executed. But, this will only work if i know the method in advance. I wish to insert hooks for all the methods that execute, even if I do not have access to the source code of the class executing it (for example a third party closed library executing an internal method). The intent behind this is logging the time taken for execution of each and every method in my app. I am aware that I cannot override objc message send method call to intercept methods. Does NSObject have some functions that are called before and after a method gets executed?

It sounds like what you actually want is to run your app in Instruments' "Time Profiler" tool. This will log all the method invocations for you and show you which ones are taking the greatest amount of time in your app.
To answer your original question, you don't actually have to know the methods ahead of time; you can just use class_copyMethodList() to get a list of methods and then iterate over them. I would discourage actually going this route, though, as Instruments is a better tool for this sort of thing.

Believe me you don't want this. As you think on a higher level that calling a function and logging the start and end to it is good, it won't do you any good for the following reasons:
1- Function will call many many lower level fuctions: addSubview itself will call many functions alone, and the function it calls will call many fuctions inside as well. You think you are about to call 1 function, but this log will be triggered +20 times in this case.
2- logging all functions is actually extra code in your case. Extra code means extra effort to the app. What you will do is basically impact the performance and battery usage dramatically.
3- Apple makes sure its core functions are seriously optimized and spends a lot of time on them to ensure they are at their best (in some xCode releases they are updated as well)
My advice is to log your functions, if you're trying to achieve a specific goal. but generally logging objective c is not recommended.
PS: In case you are trying to check the time for every function, there are tools that will show you which functions are taking what times.

Related

Why is runloop called when testing

I usually see RunLoop.current.run(until: Date()) called in integration tests.
For example in this article and in this open source project.
The explanation given in the article is
The RunLoop.current.run(until: Date()) statement makes sure the run loop associated with the current thread has ample time to let the drawing operations to complete
If that is true why wouldn't we give it more time, how do we know that Date() is enough?
I read a few articles about the run loop and it seems to me like the reason that line of code is added is to start the app. It seems like the appDelegate usually automatically triggers or starts the run loop, but since we are testing we need to trigger the run loop ourselves.
I might be missing some fundamental understand of threads or run loops but I hope that someone can give some insight.
If that is true why wouldn't we give it more time, how do we know that Date() is enough?
We know from experimentation, I suppose. A more “correct” way to do it would be:
Install a run loop observer that somehow detects when the views have been laid out and drawn.
Run the run loop indefinitely (until Date.distantFuture).
In the observer installed in step 1, call CFRunLoopStop(CFRunLoopGetMain()) when it detects that the views have been laid out and drawn.
However, that's a lot of extra work to do instead of just RunLoop.current.run(until: Date()), when the simpler method works and is unlikely to break.
I read a few articles about the run loop and it seems to me like the reason that line of code is added is to start the app. It seems like the appDelegate usually automatically triggers or starts the run loop, but since we are testing we need to trigger the run loop ourselves.
No, the app delegate does not start the run loop. The function UIApplicationMain sets up the app and starts the run loop. If you create a new Objective-C project, you will find that the main function in main.m calls UIApplicationMain. In a typical Swift project, the #UIApplicationMain attribute attached to the app delegate tells the Swift compiler to generate equivalent code (a main function that calls UIApplicationMain) in AppDelegate.o.
I might be missing some fundamental understand of threads or run loops but I hope that someone can give some insight.
An app spends most of its life in the run loop, which (simplified) has these phases:
Wait for an event. There are lots of event sources, including app startup, touches, timers, accelerometer, GPS, going to the background, returning to the foreground, and more.
Handle the event, often by calling code written by you.
If any views have the needsLayout property set, lay out the appropriate sections of the view hierarchy (which includes sending layoutSubviews messages).
If any views have the needsDisplay property set, draw those views (by sending drawRect: messages).
Go back to step 1.

Dealing with application processmessages

In our software we have issues with asynchronous execution of events. Sometimes one function will "break into" another one with all kinds of weird results.
I'm dealing here with user-input and timers that fire events.
The issue is that rather then executing the code tied to the events one by one, it's done at the first possible moment that Delphi gives a window for it: application.processmessages. This gives problems in that sometimes half of function A gets done, then function B "breaks in", gets done and after that , the last half of function A gets done. This can give "surprising" results.
Are there good ways to deal with this?
Things I tried:
--
Using a "busy-flag", this has some ups and downs, mostly that everything you do has to know of it.
Removing all application.processmessages where I can. This has pretty good results. But we're relying on some 3rd party components which I found out also fire application.processmessages.
Next I was thinking of trying building some kind of "command-queue" where I can receive my events and fire them in a fifo way.
Apart from rebuilding everything we have from the ground up, are there other/better ways to tackle these issues?
The best way is to eliminate the call to Application.ProcessMessages. Most of the time there is other ways to do what Application.ProcessMessages is supposed to do. You'll need to take a closer look why you need that call, and then find a better solution. For example, you don't need Application.ProcessMessages to update the UI. There is other ways to do that.
If a 3rd party component is calling Application.ProcessMessages then contact that vendor that they should replace this call with a better suited function. If this is not an option, you can try using workarounds like using that component in a thread (if possible). Or create an invisible modal window and execute the methods of the component inside the ShowModal function. That will at least avoid user input messages. (The "invisible modal window" is a Form with BorderStyle=bsNone, size=1×1 and 100% transparency).
Are there good ways to deal with this?
First eliminate all your use of ProcessMessages. As you discovered, it screws up timer event handlers when called from there. Used in other places, it is often subject to race conditions and may hide the real problem. Find out what that problem is and solve it.
But we're relying on some 3rd party components which I found out also fire application.processmessages.
Timer Event handlers are supposed to do only short time work. If you are calling ProcessMessages via a call to a 3rd party library inside a timer event handler, eliminate that call. There is no other cure, except rewriting the library or calling it in another way.
Apart from rebuilding everything we have from the ground up, are there other/better ways to tackle these issues?
Normally you can do background work in threads as well, providing the rules of not calling any VCL RTL methods directly are followed. Here it is not possible if the 3rd party component is calling ProcessMessages.
If you can't alter the 3rd party component, there is possibility to post a message to your form, and put the call in the method that handles this message. With a modern Delphi you could use DelayedAction by #MasonWheeler. But I really recommend you to take the "hard" way and fix the 3rd party lib instead.

Is there any easy way to adding NSLog or any logging statement in all methods?

I am about to complete the project and I want to add logging in it. I know there are some good loggers are available in market(CocoaLumberjack). But for that I need to add log statement into each and every method. As project is about to complete there are lots of methods. So, is there any way or work around ? Without adding log statement into all methods If I will add at any central place and it will work for all.
I am not sure if there is such Objective-C runtime function that is called before every method.
This method will be helpful in all cases like I am or any new dev is writing new method then he don’t need to remember to add log statement.
Edit:
This is just for a debugging purpose. And I will add a way to control the logs like turn off and print detail of certain level.
Don't do this. Seriously. Users don't appreciate their log files filling up because of chatty software, and you'll also annoy every other developer by obscuring messages that are actually important.
You should only use NSLog() this way as an absolute last resort during debugging. Even then, there are better approaches (e.g. you could use dtrace; if you get it to dump all objc_msgSend() invocations, you'll see almost all of your method calls, aside from those that pass through objc_msgSendStret() and the floating point ones if applicable to your platform).
If you really must make a chatty application, create your own log file, write your own logging function (ideally using asl), and it’s a good idea even then to have a set of flags that can be controlled e.g. from user defaults to enable different kinds of debug output.
How about a category of NSObject with this override?
-(BOOL)respondsToSelector:(SEL)aSelector {
printf("Excessive Log: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:(aSelector)];
}

How to cleanly encapsulate and execute in sequence a series of background tasks in iOS?

My app includes a back-end server, with many transactions which must be carried out in the background. Many of these transactions require many synchronous bits of code to run.
For example, do a query, use the result to do another query, create a new back-end object, then return a reference to the new object to a view controller object in the foreground so that the UI can be updated.
A more specific scenario would be to carry out a sequence of AJAX calls in order, similar to this question, but in iOS.
This sequence of tasks is really one unified piece of work. I did not find existing facilities in iOS that allowed me to cleanly code this sequence as a "unit of work". Likewise I did not see a way to provide a consistent context for the "unit of work" that would be available across the sequence of async tasks.
I recently had to do some JavaScript and had to learn to use the Promise concept that is common in JS. I realized that I could adapt this idea to iOS and objective-C. The results are here on Github. There is documentation, code and unit tests.
A Promise should be thought of as a promise to return a result object (id) or an error object (NSError) to a block at a future time. A Promise object is created to represent the asynchronous result. The asynchronous code delivers the result to the Promise and then the Promise schedules and runs a block to handle the result or error.
If you are familiar with Promises on JS, you will recognize the iOS version immediately. If not, check out the Readme and the Reference.
I've used most of the usual suspects, and I have to say that for me, Grand Central Dispatch is the way to go.
Apple obviously care enough about it to re-write a lot of their library code to use completion blocks.
IIRC, Apple have also said that GCD is the preferred implementation for multitasking.
I also remember that some of the previous options have been re-implemented using GCD under the hood, so you're not already attached to something else, Go GCD!
BTW, I used to find writing the block signatures a real pain, but if you just hit return when the placeholder is selected, it does all that for you. What could be sweeter than that.

Adobe Actionscript - multiple service request processing

Does anyone know of any good resources that fully explain how functions and results will fire in an Adobe AIR app where multiple things are happening at once?
As a simple test, I've created a single service that I just keep changing the url of, then issuing a send(). It seems that no matter how many send() calls I put in, all of these get executed before the 'result' eventListener function gets called for the first time.
Is this how it works? i.e. the current function gets fully executed, with the async returns queueing up to be processed after AIR has finished what it's currently doing.
Likewise, if the user does something while all this is going on, I presume their request goes to the back of the queue as well?
All that makes sense, but I'm just wondering if it's documented anywhere.
While I'm on one, is it recommended practice to reuse the same HTTPService in this way, or is it better to create one for each concurrent transaction? Just because it works, doesn't mean it's the right thing to do...
I'm not aware of any documentation that explains this, but I can confirm that code blocks get executed before async calls are made, or at least before their result is being processed. If it didn't work that way, you would for instance not always be able to attach a responder to a token of a service call, because the result might already have been processed.
var token:AsyncToken = myService.someMethod();
token.addResponder(new Responder(resultHandler, faultHandler));
Developers coming from other platforms find this strange as they would expect the assignment of the responder to be too late.
So while I don't have an official explanation about the technical details inside the Flash Player, I can assure that it works this way.
If the user does something while a call is pending, the new request will indeed just be added as a new asynchronous call. Note that we can't realy speak of a queue, as there is no guarantee that the response of the first call comes in before the response of the second call. This depends on how much time the actual requests take.
You can perfectly reuse an HTTPService instance.
PS: Based on this, we were able to build the Operation API in Spring ActionScript. It is basically an API that allows you to execute asynchronous processes in a uniform way, without having to worry about the details of the actual async process.
The following code executes an async process and attaches a handler to it. This is also something that puzzles many developers at first, for reasons similar to the asyncToken situation.
var operation:IOperation = doSomeOperation();
operation.addCompleteListener(aCompleteHandler);
operation.addErrorListener(anErrorHandler);

Resources