I am doing a lot of setup inside my app delegate (mainly for CoreData) inside of applicationDidFinishLaunchingWithOptions. And was curious how i would go about testing code inside the appDelegate? Thanks
Step one: Stop using your regular application delegate during testing. This avoids the "it will be called at launch" problem, and will likely also speed up your tests. See https://qualitycoding.org/ios-app-delegate-testing/
Step two: Now that your regular application delegate isn't invoked when tests are launched, directly call its methods from tests.
Move the functionality into smaller functions or other classes that you can test.
If you keep things in the App Delegate class, you can access them the normal way since the unit tests are linked to the app and the app is actually run. But you cannot call applicationDidFinishLaunchingWithOptions and expect it to work. It will be called by iOS at the start, like normal.
Related
I am writing an iOS app that registers for call events (not-in-call, dialing, disconnected etc).
I have code that registers for the call event, but I'm not sure where is the correct location to put it (in the Model? In the Controller?).
All samples place the code in the app delegate, but that seems awkward. After all, the app delegate is not part of MVC.
Thanks!
After all, the app delegate is not part of MVC.
I could argue, but I have a feeling you worry too much about the "correct design". If you want to change the place of these event handlers, I'd put them somewhere in the controller (certainly not model, because they are not data providers...)
But after all, why are they "awkward" in the app delegate? That's exactly why the singleton application object has a delegate: system-wide events shall notify the app (and its delegate), respectively, and not some internal part of the application. That's mixing things up.
Since these events control parts of your application the best answer would be: in a controller.
This Apple style to put lots of stuff in the delegate is indeed bad coding practice.
Suppose an application runs fine. But now app is in a phase of adding functionality to it. Assume programmer added functionality to one button which is visible after applying many gesture on iPhone.
(for example, tap one of the tabs then, tap one of the tableview cells visible thereafter, then few more taps & say on Navigation bar one button is visible to which programmer added functionality ).
So while testing functionality of that button, programmer has to tap the iPhone many times to goto that specific button.
If that added functionality is critical & needs to be tested many times then it would be tedious process of just reaching that button which may lead to some frustration.
So is there any tool available that will help user in skipping this chain of tappings on iPhone.
Or is there any other way to test such an app.
You can use Instruments with UIAutomation, which lets you script UI actions, log messages and take screenshots. The test scripts are written using Javascript (search for UIAElement to find the API reference).
But the best resource to get you started is the WWDC 2010 session "Automating User Interface Testing with Instruments".
You should also read the Accessibility Programming Guide since UI Automation leverages on that.
Don't neglect the preprocessor constants as well. Something like:
#if TARGET_IPHONE_SIMULATOR
// Some code to automatically skip the view controllers leading to this
#else
// Production code
#endif
Otherwise I would investigate the UIAutomation classes for automating input to an iOS application. Furthermore, you should be Unit Testing the code behind your buttons. Writing a unit tests that pushes a button will always work. It's really rather pointless to unit test the framework code.
I migrate recently from C programming to iphone development with Xcode. It seems the IDE hides a lot of trivial things and I'm curious about what's going on under the hood.
I find a file named main.m in my project. Inside this function, UIApplicationMain(argc, argv, nil, nil); is invoked. My question is what tasks will the UIApplicationMain completes? Can I step into this function tracking its execution?
Any hints will be appreciated.
Thanks and best regards.
iOS Cocoa Touch apps use an event driven paradigm, instead of being strictly sequential procedural code.
UIApplicationMain() tells the OS and Objective C runtime to set things up (plist'ed defaults, main nib, run loop, etc.) and then have the main run loop start dispatching to methods within your app. Put breakpoints at the beginning of all your (init/load/event handling) methods to see what the OS starts calling first.
The OS does a whole bunch of things you can't step into. You have to wait until it's good and ready to call methods within your app.
UIApplicationMain is the entry point for the Cocoa app. It sets up the app's primary application class and its delegate, and starts running the event loop. It doesn't return.
From the documentation:
This function instantiates the application object from the principal
class and and instantiates the delegate (if any) from the given class
and sets the delegate for the application. It also sets up the main
event loop, including the application’s run loop, and begins
processing events. If the application’s Info.plist file specifies a
main nib file to be loaded, by including the NSMainNibFile key and a
valid nib file name for the value, this function loads that nib file.
You don't really want to step into the guts of that specific function, because there's just a whole stew of binary instructions to look at that won't be enlightening. But the way to think of it, is that it's the "container" function for your whole app. Once it does its setup work, it starts event processing in an run loop, and will call out into your code when appropriate. It will be at the bottom of the callstack for all your app's code on the main thread.
Check out the great diagrams on this page for more about an app's lifecycle, which should give you some hints about where to put breakpoints in your own code, and how they will be called:
http://www.codeproject.com/KB/iPhone/ApplicationLifeCycle.aspx
I have an timer in viewDidLoad, but I want to pass variable seconds assigned by slider, so what should I do for this for such implementation?
I think I have to restart app, so is there any other solution, or how can I restart my app?
a) Keep your timer as an instance variable in your appdelegate or somewhere else, and update its interval whenever the slider moves.
b) From the user's perspective you wouldn't want to restart the app for simple things such as these.
c) You can't restart an iPhone app or in any way play around with its lifecycle.
EDIT:
If you are planning to have an instance of the timer available across the app, there are twp ways you can do that.
put is as an instance variable in the appdelegate class, the one which xcode would have created for you, with the projectnameAppDelegate. You will then be able to access it using
[UIApplication sharedApplication].delegate
from which you can get the instance of the NSTimer
Or you can implement a common Singleton class, and put the timer in it. This is a much more accepted approach described here and scroll down to the bottom of the page.
For more info, search on ways to create a global object(although creating a global object is not a good idea), and follow the instructions.
I would really like to see every method, delegate, notification, etc. which is called / sent while I run my app in the iPhone Simulator. I thought the right place for this would be in the debugger, but I can't find the right setting.
My target is to see all that is happening in the background while I, for example, add a row to a UITableView or push the 'back'-button from my UINavigationController.
This would be a big help to figure out what delegate to use when something in the app is happening or when the user is pushing a button, changing a view, etc.
Is it possible to get this information?
You can log out everything that is happening when your application is running using DTrace, a framework that lets you probe the inner workings of anything running on a modern Mac. We don't yet have DTrace on iOS, but it will work while you're running within the Simulator.
I describe the fundamentals of DTrace in this article for MacResearch, then provide an example of a custom instrument you can build in Instruments using DTrace near the end of this article. That instrument logs out all methods called on all objects (even internal system ones) from the moment your application starts until it hits the end of -applicationDidFinishLaunching:.
To simplify this, you can simply create a custom instrument using the Instrument | Build New Instrument menu item in instruments. Set up one of the probe descriptors to look like the following:
only ignore the isInApplicationStart and timestamp logging options. A simple probe responding to any Objective-C method in any class will log all of those messages to the Instruments console, which sounds like what you want for your debugging.
Assuming you're sure you want absolutely everything...
Breakpoint objc_msgSend and objc_msgSend_stret. Almost all method calls use those two functions (mumble mumble IMP-cacheing).
Okay, now your app drops into the debugger all the time. So click the auto-continue box.
But now you don't see very much happening, so edit the breakpoints and add the command "bt" to get a backtrace.
Drown in debug spam.
This won't catch other C functions, of course.
If you just want to catch notifications, you can do something like this (much less spammy):
+(void)load
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleEveryNotification:) name:nil object:nil];
}
+(void)handleEveryNotification:(NSNotification*)notification
{
CFShow(notification);
}
Of course, notifications are done with normal method calls, so the first method will also show them (albeit in a big pile of spam).
Delegates are not called or sent; they are just normal Obj-C method calls (strictly "message-sends", but that doesn't have the same ring to it).
If you put a breakpoint into your app, you can watch the call stack change while you step through the code. That's probably as close as you're going to come to what you have in mind.