I have a big project and there are many NSLog() calls. When something happens some NSLog() works, and I don't know which NSLog get called. How can I find a place where is NSLog() get called in class file?
My NSLog is like this: NSLog(#"%#", someArray);
and here's the log:
2013-04-23 20:43:38.257 myProj[2101:707] {
id = 1;
version = 1;
}
What does myProj[2101:707] mean here? Does it give me any information about NSLog function's location in class?
You could try searching the project for the output.
For instance if the output is
This is my output with values 3.1415 and 1.2345.
press cmdshiftF and search for "This is my output with values"
You can also insert placeholders in the search term:
Convert all of your NSLog usage to DLog and then the log statements will print:
The file name
The method name
The line number
Of every line that is output to the log. In this way you can immediately see where all logging is being done. DLog is a much better logging mechanism to use than NSLog and you should start using it in all your projects.
Define DLog in you pch file as:
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif
You can use the function class_getName to get the class name of the object your log statement is placed and include the class name in NSLog().
Like this:
#import <objc/runtime.h>
…
NSLog("%# Some Log Statement", class_getName([self class]));
Related
I have allocated and initialized a class file which is not in the project workspace (don't have a file to import).Normally it would throw an error like Use of undeclared identifier classname.Here i want to skip this error make the build success.Is there any pragma to skip these kind of error's.
Wrap the code around #ifdef and #endif macros and do not define the macro name that is used.
Example
- (void)myMethod
{
// ....
#ifdef MYMACRO
// Here you need not #import ABC.h
ABC *abc = [[ABC alloc] init];
[abc someMethod]
#endif
// .....
}
Do not #define MYMACRO anywhere so that this code block is ignored by the compiler.
Hope that helps!
Is there any particular flag which can be set to not display NSLog output in either debug or release?
Thanks.
One option might be to use a macro as a replacement for NSLog (if its easy for you to change things at this point). I like the prefix header file these guys use:
http://www.cimgf.com/2010/05/02/my-current-prefix-pch-file/
Basically their logging function is:
#ifdef DEBUG
#define DLog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
#define DLog(...) do { } while (0)
#endif
So if you are not in a DEBUG build, the logging macro becomes a no-op.
Generally, people write their own macro -- something like DebugLog -- for logs to be "compiled out":
#undef DebugLog
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( #"%#", [NSString stringWithFormat:(s), ##__VA_ARGS] )
#else
#define DebugLog( s, ... )
#endif
In Xcode, you can define macros for particular build configurations. For example, here I have DEBUG defined for Debug builds, and nothing for release builds.
Then to use this in the code, wrap your NSLog(...) statements in (or however you choose to use the macro, update:darren's method is quite good with this technique):
#ifdef DEBUG
NSLog(...);
#endif
Use the same mechanism for release configuration only logic.
You can use this ability if you have various number of build configurations, and you can define more than one macro if you want to enable/disable different levels of functionality for different build configurations.
Default flag with a new Xcode project is DEBUG for Debug and none for Release. So you will hide NSLog in Release this way:
#ifndef DEBUG
# define NSLog(...)
# define NSLogv(...)
#endif
Or if you want pretty custom logs as well (not using #ifdef here because no simple #elifdef):
#if DEBUG
# define NSLog(format, ...) NSLog((#"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__)
# define NSLogv(format, ...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [[NSString alloc] initWithFormat:format arguments:__VA_ARGS__])
#elif ADHOC
// default logs
#else// Release
# define NSLog(...)
# define NSLogv(...)
#endif
And if you want to override those macros and still log something sometimes, you can use:
(NSLog)(#"This log is always visible!");
Now, how to hide those as well? It would require you to #define NSLog NoLog and define NoLog as an extern function with an empty implementation like void NoLog(NSString *format, ...) {}. But it could be cleaner to avoid using (NSLog) altogether and instead use a function with a LogLevel enum:
typedef NS_ENUM(NSUInteger, LogLevel) {
LogLevelRelease,
LogLevelAdHoc,
LogLevelDeveloper,
};
void CustomLog(LogLevel level, NSString *format, ...) {
#if !DEBUG
if (LogLevel == LogLevelDeveloper)
return;
#if !ADHOC
if (LogLevel == LogLevelAdHoc)
return;
#endif
#endif
va_list ap;
va_start (ap, format);
NSLogv(format, ap);
va_end (ap);
}
The drawback of this CustomLog is that arguments get always evaluated, even in Release. So an optimal solution is multiple macros:
#define NSLog(format, ...) NSLog((#"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__)
#if DEBUG
# define DebugLog(...) NSLog(__VA_ARGS__)
# define AdHocLog(...) NSLog(__VA_ARGS__)
# define ReleaseLog(...) NSLog(__VA_ARGS__)
#elif ADHOC
# define DebugLog(...)
# define AdHocLog(...) NSLog(__VA_ARGS__)
# define ReleaseLog(...) NSLog(__VA_ARGS__)
#else// Release
# define NSLogv(...)
# define DebugLog(...)
# define AdHocLog(...)
# define ReleaseLog(...) NSLog(__VA_ARGS__)
#endif
check for Debug mode using this macro
#ifdef DEBUG
//NSLog(#"XYZ");
#endif
Above NSLog will not get printed in Release mode
You can define a macro in the precompiled header (.pch) to disable NSLog:
#ifdef RELEASE
# define NSLog(...)
#endif
This disables NSLog in release builds.
Adding this b/c none of the answers seem to address warnings you may have (depending on project settings) with some of these approaches.
This is the only way I could find to suppress NSLog without getting any warnings. Otherwise I get a ton with the settings we use (warn on unused variables).
#undef NSLog
#define NSLog(fmt, ...) if (0) { printf("%s", [[NSString stringWithFormat:fmt, ##__VA_ARGS__] UTF8String]); }
Then all you need to do is put that in whatever pch file you use for your release builds or wherever you want to suppress the logs.
Credit to #Hot Licks for the example of how to make the variable "used".
I want to unit test my Core Data app (stress test with many records). Everything is set up for unit and application testing and working fine.
I would like to create many core data objects and then see if my graphing view controller still works. How would I do that?
If I create a test method in my MyAppApplicationTest.m test class the test will just terminate the app after the test and I have no way to interact with the graphing view controller.
Am I stuck with having to create the many records in my AppDelegate and delete that code later? Or is there a way to use the unit testing framework?
Thanks for your help.
There are several options for UI testing. However, in this case, I would suggest building a huge database, and keeping it around for various testing. You can optionally use it by setting a value on the command line, in the environment, or just in user defaults.
Come sample code to check user defaults, then environment for a setting...
static NSString * findOption(NSString *name) {
NSString *result = nil;
NSDictionary *options = [NSUserDefaults standardUserDefaults];
if ((result = [options objectForKey:name]) != nil) return result;
options = [[NSProcessInfo processInfo] environment];
if ((result = [options objectForKey:name]) != nil) return result;
return nil;
}
Note, if you just want to check command line parameters, instead of all domains of user defaults, you can use this...
NSDictionary *options = [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSArgumentDomain];
Then, in your code that creates your persistent store, you can just see if the option is set...
if ((value = findOption(#"MundiLargeData")) && value.boolValue) {
// Create the persistent store with the pre-generated big database
// If creation failed, can continue with normal database as failsafe
}
Also, note that if you use SenTest for testing, it uses a command line parameter:
NSString *value = findOption(#"SenTest");
if (value) {
NSLog(#"Using SenTest: %#", value);
}
You can leave the code in, or #ifdef it out. It's pretty safe to just leave in there.
EDIT
Apologies -- I was going to add this immediately, but got called away...
Sorry about that. I never meant to imply that you ship your testing code. You certainly do not want to do that. I thought you were just looking for a way to load the big database when you were running the application so you could do manual UI testing on the device without having to compile a different version.
If you want to do something like that, then you have lots of options. You can write your tests as a category on the class that you want to test, and just exclude that file from release builds. If you give your tests a consistent naming scheme, like prefix with "test" or "runtimeTest" then you could have a method like this...
- (void)runAllMethodsThatBeginWith:(NSString*)prefix {
Class aClass = [self class];
Method *methods;
unsigned methodCount;
if ((methods = class_copyMethodList(aClass, &methodCount)))
{
// For this example, we only want methods that take no arguments and return void
char const *desiredEncoding = method_getTypeEncoding(class_getClassMethod([NSObject class], #selector(load)));
for (unsigned i = 0; i < methodCount; ++i) {
SEL selector = method_getName(methods[i]);
NSString *name = NSStringFromSelector(selector);
char const * typeEncoding = method_getTypeEncoding(methods[i]);
NSLog(#"%#: %s %s", name, typeEncoding, desiredEncoding);
NSRange range = [name rangeOfString:prefix];
if (range.location == 0 && range.length == prefix.length && strcmp(desiredEncoding, typeEncoding) == 0) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:selector];
#pragma clang diagnostic pop
}
}
// Don't forget to free the allocated methods array
free(methods);
}
}
It will find al the methods in your class that start with some name and return void and take no arguments. You can do other argument handling, but you will then have to deal with ARC related issues (since the compiler does not know for sure what to do -- it will at least give you a warning). Anyway, that's just to get you started... you could add type encoding as a parameter, and make it more generic...
Now, in your runtime code, you can just call...
[self runAllMethodsThatBeginWith:#"runtimeTest"];
It will run all methods that look like...
- (void)runtimeTestFoo {
}
If there are none, then it will just silently do nothing.
You can either exclude entire files with these implementations from the release build, or just exclude them with a macro ifdef.
Now none of your tests are compiled into the release, but they are for other stuff, and you can just call your tests anytime you want. If you know a specific test, then you can, of course, just use respondsToSelector: and conditionally run that specific test method.
EDIT
Hmmm. I thought you were looking for some way to dynamically decide what to do. If that's all you want, then just provide a subclass of the AppDelegate that creates the database...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Create your mondo database
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
Now, you have several options. In main.o, you tell it which app delegate class to use. You could use an option (#ifdef DEBUG), or an environment variable, or some other means to tell it which app delegate class to use...
#import "AppDelegate.h"
#define APP_DELEGATE AppDelegate
#ifdef USE_MY_SPECIAL_RUNTIME_TEST_DELEGATE
#import "RuntimeTestDelegate.h"
#undef APP_DELEGATE
#define APP_DELEGATE RuntimeTestDelegate
#endif
int main(int argc, char *argv[])
{
#autoreleasepool
{
return UIApplicationMain(argc, argv, nil, NSStringFromClass([APP_DELEGATE class]));
}
}
Or, it could just call NSClassFromString(#"MyTestingAppDelegate") to see if it is linked in to call it...
Or, if you want complete separation, simply create another target. Have the app delegate subclass in there, and use it in the main.m for that target. Link against all the other files.
Now you have a completely separate executable, that is identical to the "production" except it has a special app delegate that builds the database before launching the app.
Testing is hard. You have to know exactly what you want and do not want. There is no right answer that encompasses all situations.
There are MANY other options to this as well, like providing a config file in the resource bundle, including extra stuff in the app plist, providing a "guru" mode to the app where you can send it special commands during execution (like having it open a socket and reading special commands and sending back responses -- that way you can script scenarios for whatever you want, run them on your mac and remotely control the app -- there are tools for this as well).
Hopefully, one of these methods will fit what you are looking for.
ForwardInvocation does exist, but it is slow and has the annoying problem of compiler warnings. So that got me to thinking -- is there a way to use macroes to quickly implement a bunch of getter methods that get the property in question from another object?
For example, if I have a Car object, it might want to implement the following:
Car.h:
#class SparkPlug;
#class Engine;
. . .
-(int) nPistons;
-(float) horsepower;
-(SparkPlug*) sparkPlug;
Car.m:
. . .
-(int) nPistons {
return self.engine.nPistons;
}
-(float) horsepower {
return self.engine.horsepower;
}
-(SparkPlug*) sparkPlug {
return self.engine.sparkPlug;
}
Question -- would it be possible to set up some macroes so that by making one change somewhere, I could add another such method to both the header and implementation files?
e.g. MagicForwardingMacro (nPistons, int, engine);
Ideally, in such a way that the macroes would be reusable if I later wanted to later use a similar strategy to get the firstName, lastName, placeOfBirth, and dateOfBirth properties of a Person from his or her birthCertificate.
The easiest way is probably to add the methods dynamically:
Add the properties to a category so the compiler doesn't complain too much.
Clone a suitable IMP in +[NSObject resolveInstanceMethod:]. You'll need to poke the Objective-C runtime.
Elaborating on the second step:
For each type, add a method like
-(int)getEngineInt {
return (int()(id,SEL))(objc_msgSend)(engine, _cmd);
}
Note that for structs you need objc_msgSend_stret and for floats/doubles you might need objc_msgSend_fpret (I think you only need it on i386; not sure about AMD64). The easy hack to support both the simulator and device is something like (I forget the macro name GCC uses...)
#if __i386
#define objc_msgSend_fpret objc_msgSend
#endif
Now to implement +resolveInstanceMethod:, you need to know the class you're forwarding to ahead of time. Let's say it's Engine.
+(BOOL)instancesRespondToSelector:(SEL)name
{
return [Engine instancesRespondToSelector:name];
}
+(BOOL)resolveInstanceMethod:(SEL)name
{
// Do we want to super-call first or last? Who knows...
if ([super resolveInstanceMethod:name]) { return YES; }
// Find the return type, which determines the "template" IMP we call.
const char * returntype = [Engine instanceMethodSignatureForSelector:name].methodReturnType;
if (!returnType) { return NO; }
// Get the selector corresponding to the "template" by comparing return types...
SEL template = NULL;
if (0 == strcmp(returntype,#encode(int))
{
sel = #selector(getEngineInt);
}
else if (0 == strcmp(Returntype,#encode(float))
{
...
}
if (!sel) { return NO; }
Method m = class_getInstanceMethod(self,template);
return class_addMethod(self, name, method_getImplementation(m), method_getTypeEncoding(m));
}
Alternatively, there's a slightly undocumented method -forwardingTargetForSelector: which may be fast enough for your needs.
EDIT: Alternatively, you can loop over the properties/methods dynamically. There doesn't appear to be an obvious way to introspect categories, but you can define them in a protocol, do something like #interface Engine:NSObject<Engine> ... #interface Car(DynamicEngine)<Engine> and use objc_getProtocol("Engine") and then protocol_copyMethodDescriptionList()/protocol_copyPropertyList() to get the methods, and then add the getters. I'm not sure if properties are added to the "method description list". Also note that the "copy" functions do not copy methods/properties from superclasses, which (in this case) is what you want.
Sadly, I don't think Objective-C 2.0 properties will work for you because I don't think you can specify any kind of forwarding in the property declaration.
You can't have one macro that will insert text in two different places. However, you can use two macros like so:
//This could also take the third argument and discard it, if you like
#define FORWARDI(type, prop) - (type)prop;
#define FORWARDM(type, prop, owner) - (type)prop { return owner.prop; }
//In the header...
FORWARDI(float, nPistons)
//In the implementation...
FORWARDM(float, nPistons, self.engine)
If you don't mind the methods not showing up in the header file (for example, if you will only use these methods inside the class's implementation itself), you can just as well use the implementation file macro by itself.
This is agnostic to the type of the owner, but it should work with any expression.
I'm getting close to what I want. Some nagging details remain:
ForwardingInclude.h:
// no include guard; we want to be able to include this multiple times
#undef forward
#ifdef IMPLEMENTATION
#define forward(a, b, c) -(a) b { return [[self c] b]; }
#else
#define forward(a, b, c) -(a) b;
#endif
CarForwarding.h:
// again, no include guard
#include ForwardingInclude.h
forward(int, nPistons, engine)
forward(SparkPlug* sparkPlug, engine)
Car.h:
#interface Car: SomeSuperclass {
// some ivars
}
. . .
#include CarForwarding.h
Car.m:
. . .
#implementation Car
#define IMPLEMENTATION
#include CarForwarding.h
The nagging details:
1) I don't like that #define IMPLEMENTATION line. I want CarForwarding.h to somehow automatically detect whether or not it is currently being included inside an implementation.
2) It would be waaaaaay cool if I could have the stuff defined in the forwarding file somehow also appear in human-readable form in the header. Or better yet -- write the "forward" definitions directly into the Car.h file somehow, so I don't need the CarForwarding.h file at all.
This is for practise. I try to build something similar to NSLog. Currently I have this:
#define LogThis(info) \
[[MyLogger sharedLogger] logThis:info];\
- (void)logThis:(NSString*)info {
fprintf(stderr, [[NSString stringWithFormat:#" %#\n", info] cString]);
}
Currently all I can do is pass a simple #"string" to it, but no formats and arguments like I could with NSLog. The main advantage here is that I get rid of all this overhead which NSLog produces. For learning purpose I'd like to know how I can get multiple arguments to make something similar to NSLog, so that I could call:
LogThis(#"method foo received input value %d", inputValue)
Is this possible?
Here’s how you define variadic macros in gcc’s cpp:
#define LogThis(format, ...) \
do { printf(format, ## __VA_ARGS__); } while(0)
There is a way, you define the last argument with a trailing '...'. To access the last arguments defined, prepend the argument name with ##. I have a similar Log macro that looks like:
#define LOGGER(format, args...) \
LogManager::log()->addEntry(format, ##args)
where the addEntry function takes in a printf-like format. An example call looks like
LOGGER("This is a debug string with %d arguments %s", 2, "hooray");