I have a view controller that keeps reloading over and over again. I would like to be able to see which methods are being called so that I can see the one that keeps firing the reload. I know I can see what was called if an error occurs and the app crashes. However, in this case there is no crash. Is there a way to monitor all of the methods being called throughout the app?
If you are new to XCode and Objective C and looking for something lightweight and you do not have a large code/ many methods, I would put:
NSLog(#"%s",__PRETTY_FUNCTION__);
in every method.
Use Instruments. Start your code in a profiling mode and select the CPU time instrument. As the app runs, Instruments will gather information about every call stack at regular intervals, which will allow you to see what calls what. (Use the "Invert Call Tree" option to see callers of a given function.)
I use this macro:
#define DEBUG 1
#if DEBUG
# define NLog(fmt, ...) printf("%s\n", [[NSString stringWithFormat:#"%s:%d %#", __PRETTY_FUNCTION__, __LINE__, [NSString stringWithFormat:fmt, ##__VA_ARGS__]] UTF8String])
#else
# define NLog(...)
#endif
Then I include my Macros.h in my Application_Prefix.pch file, so that it's available everywhere. Before I ship, I set DEBUG to 0 so that all NLogs disappear.
So now, instead of using NSLog, I use NLog. The output looks something like this:
-[ApplicationDelegate applicationDidBecomeActive:]:86 applicationDidBecomeActive called!
This solution was based on these earlier posts:
How to print out the method name and line number and conditionally disable NSLog?
Do I need to disable NSLog before release Application?
You can just place the NLog calls in several places, to see which functions are called right before your view controller reloads. If you need to know the exact function that triggered the reload, your best bet would be to place a breakpoint and examine the call stack, as others have mentioned.
Related
I made my project in storyboard in, due to issue with the custom UITableViewCell I have made a new project, copied all of the data to my new classes and copied my buttons, images etc from the storyboard views to new project's nib/xib files.
Now When I click on any button my app crashes without any error and it opens delegate file and highlights this line of code
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ThisOrThatAppDelegate class]));
I have already made connections for the required actions from IB to controller. Also I have tried Command+Shift+K for clean code. But the problem is still there.
You have to find out first what the problem is:
use the Debug build config and are using lldb or gdb
make sure you have a breakpoint on all exceptions
make sure you have the "Breakpoints" button top left enabled.
run the app
You should break into the debugger. You need to get to a point where the debugger catches the exception.
Then edit your question and tell us what exception you get. I'm going to guess you'll be getting a objc_msgSend() error, which means that some object is trying to message a non-existent or dealloced object. If that turns out to be true, then you can enable "Zombies" (which lets all objects stay around) and see if one of those gets messaged.
If nothing seems to help, then what you need to do is start adding NSLog messages to track your app as it comes up (or use breakpoints, your choice). This takes a long time so you might work backwards - see if your appDelegate application:didFinishLaunchingWithOptions: gets called, and also if you get to the end of it.
Unforunately this type of problem can be take a lot of time to track down. Some object has probably queued a message up for another object on the main queue, so when you get the crash you don't get to see who did what when.
Also, with objc_msgSend problems, when the debugger stops you cannot easily see what object was messaged - but if you turn off the debugger and let the app actually crash, you can find the crash report in the Console app and get more info from that.
I am working on a large (>30k lines) event-driven app. I have a sequence of inputs that produces a bug. What I want to do is to break as soon as the final input enters my code.
Is there a general way to do that?
I understand that for any specific sequence of inputs, I can find out where that last input is going to enter my code, then set a breakpoint there. What I would like to do is take out the step of "find out where that last input enters my code." In other words, I am running the app in the simulator, and I want to set a flag somewhere that says "break the next time you are going to enter non-system Objective C code." Then I send the event that causes the problem.
I understand what you are asking, but have you tried using an Exception Breakpoint? This will basically act like an auto-inserted breakpoint on the piece of code that throws the exception. If that doesn't work for you, try a symbolic breakpoint
If you want to intercept UI events, you can try subclassing UIWindow and overriding its sendEvent: method, then setting this class as the class of the UIWindow object in your main XIB file. sendEvent: will be called each time the user generates a touch event. Unfortunately, at this point you cannot yet know which UI object will finally consume the event (read: which event handler code will be ultimately called) since that depends on the actual state of the responder chain. But anyway, you can use this method to inject events into the system.
My app crashes, but generates no exception in the console and no crash log on the device. No memory warnings are received. Is there any way I can narrow down the cause without having to comment out code?
Stepping through the code should help you nail down where the app is crashing, this will stop the program execution before it hits any "bad" code (providing you put the breakpoint - where the code will stop in the right place). You can add a break point by clicking on the appropriate line number to the left of the code editing pane and can access the break points organiser through the View->Navigators->Show Breakpoint Navigators menu.
You may have some inkling of the method or class that's currently being executed in which case you should put a break point on the first line of that method, if the class is a UIViewController then putting the break point on the first line of it's -(void)viewDidLoad method may help. You could, at a push, put your breakpoint on the first line of -(void)applicationDidFinishLaunching in the application delegate. However this will require a lot of stepping into instructions rather than just stepping over instructions.
https://developer.apple.com/library/mac/#documentation/ToolsLanguages/Conceptual/Xcode4UserGuide/Debugging/Debugging.html
Apple also suggest turning on the static analyser and then inferring problems in your code from it's output.
The reason for the crash was that I was logging a really large array with NSLog - did not know that could crash an app!
I am loading the custom cell on tableView and i return 50 rows in the tableView.
number of some rows are display in the tableview but when scroll the tableview my customcell is not display and I have the error
"EXC_BAD_ACCESS"
and also display following message on the console
"void SendDelegateMessage(NSInvocation*): delegate (webViewDidLayout:) failed to return after waiting 10 seconds. main run loop mode: UITrackingRunLoopMode"
I think you get this error due to your method of making custom cells. When you made the class file for the custom cell in the .m file you released the IBOutlets. Try removing that portion from your code than try.
I had the same problem in an app, and I solved that problem this way. Maybe this solution will work for you too.
The best way to detect zombies is:
in the Groups and Files section,
expand the Executables section
and right click on your app name and
choose Get Info
select the Arguments tab on the top and then add a new entry in the Variables to be set in the environment section. Name the new variable to NSZombieEnabled and set its value to YES.
After this you will have information in console on which released objects you make calls.
This typically means that you have asked the program to look at a memory area that you don't have access to, which usually means you have run off the end of an array, or something.
If you are running in debug mode, the stack trace will probably give you more clues. Open up the debug console.
You should also use NSZombieEnabled, it usually helps. It shows you which deallocated object was accessed. Be sure to disable it after you use it because using this, no memory is ever released.
I have a problem with a function running before the previous one has had time to finish. According to the logs they both run but it is almost as if the function called from the AppDelegate is put onto a separate thread.
-(IBAction) checkLocation {
[AppDelegate locateMe];
[self checkForChangeAndReloadTable];
}
The locateMe function can be called from several views which would do different things with the information. It finds the user's location and saves it to user defaults. checkForChangeAndReloadTable checks the defaults and, if the location has changed, reloads the table with new, more relevant information. It seems the change happens after it checks so this does work if the checkLocation function is called twice by the user.
Is this expected? Any ideas how to get around it?
Without seeing any source code to the locateMe or checkForChangeAndReloadTable methods, it's impossible to say, but several CoreLocation methods run asynchronously, which is probably your problem.
you can use notifications to handle asynchronous events. The basic idea is to set a notification that calls checkForChangeAndReloadTable when locateme completes