iPhone RestKit how to enable RKLogDebug? - iphone

I'm trying to debug RestKit object mapping and noticed that there are calls to RKLogDebug throughout the code, but it appears that that macro is undefined somewhere. How can I enable it?

You want to add something like this:
RKLogConfigureByName("RestKit", RKLogLevelWarning);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
to your code. See RKLog.h for the various levels. It is pretty trick.
N.B. this supports a wildcard at the end so, e.g.,
RKLogConfigureByName("*", RKLogLevelTrace); // set all logs to trace,
RKLogConfigureByName("RestKit*", RKLogLevelWarning); // set all RestKit logs to warning (leaving the app-specific log untouched).
– Thanks Kevin!
For Swift user use this syntex:
RKlcl_configure_by_name("RestKit/Network", RKlcl_vTrace.rawValue)
RKlcl_configure_by_na`enter code here`me("RestKit/ObjectMapping", RKlcl_vOff.rawValue)
– Thanks Darshit!

As described in first answer you can configure your app to specific component by calling RKLogConfigureByName.
You can also configure RestKit for specific component using Environment Variables in Xcode scheme. This is useful especially when you have your app building continuously for different environments.
Here's detailed explanation of RestKit logging http://restkit-tutorials.com/logging-in-restkit-debug-tips/

Related

Sentry Raven inside Firefox Addon SDK

I am making a Firefox Extension and I want to log the errors/messages/exceptions produced by the extension code using Sentry.
I tried the JavsScript Raven client but I guess its not really made to live inside the "Content" context.
The error I get is: message = "debug" is read-only, but my actual question is, how do I go about integrating Sentry in a Firefox Addon?
PS: No, this wont go into general distribution, my api keys are safe.
What I did was just to omit calling .install() and just use the error/message reporting.
There will be no automatic catching and source code but it works for my purposes.

Handling errors/exceptions & logging them in iPhone applications

I wanted to know do we need to log the exceptions/errors in a common file in file system when an iPhone application runs for debugging purpose later point in time? Or this is handled by IOS automatically through device logs?
I now using NSLog statements we can print on consol but is there something similar to log4j in Java where you put all debugging statements including errors/exceptions in a single file which you can analyze later point in time.
What is the best way to handle such scenarios.
Some excellent info is found in this previous post on SO:
Logging to a file on the iPhone
Another good tip for logging in general is using the DLog macro:
http://iphoneincubator.com/blog/debugging/the-evolution-of-a-replacement-for-nslog

Logging iphone feature usage

Are there any frameworks/services for logging user usage of an iphone application?
Say you want to log events like 'creating a contact' or something similiar, to know how people are actually using your app.
I have used and really like Pinch Media. (Recently renamed to flurry)
http://www.flurry.com
It gives you a bunch of analytics without you having to do anything special.
You can also add hooks to your code to see how often a particular section of code is run and get analytics on that area as well.
Yes, Flurry Analytics does this. You can even pass parameters to your events so you can break down which options are most popular, etc.
What you could do is simply log these messages perhaps as a Log custom class, and whenever you need to add anything to the log, you would simply add a new Log item to the AppDelegate or wherever you need to store the list of Logs. Then you can save them to the file system.
For achieving the logging the feature usage in flurry the url below can be helpful.
http://wiki.flurry.com/index.php?title=Analytics_-_Best_Practices

How to check if not available methods are used if deployment target < base sdk?

I would like to know how you check that your code do not call not available methods when the deployment target is inferior to base SDK ?
It is possible to run the application on a device with the SDK equal to deployment target, but I search a way more 'automatic'. Any idea ?
Regards,
Quentin
The easiest way to do this is to use the __IPHONE_OS_VERSION_MAX_ALLOWED preprocessor define.
You do this by adding
__IPHONE_OS_VERSION_MAX_ALLOWED=__IPHONE_4_2
or something similar to your "Preprocessor Macros" option in Build Settings of your target. You can look up versions available in <Availability.h>.
Unfortunately if you add this define it will cause mismatch errors with your precompiled header. So, to fix that you need to turn off the "Precompile Prefix Header" option in your build settings as well.
Once you do this you'll get a bunch of errors for classes that don't exist on your targeted SDK (for instance NSOrderedSet doesn't exist in iOS 4.2). If you're trying to go back pre-iOS 4 you'll probably get so many errors that the compiler bails--I don't know of a workaround for this. In any case, ignore the errors about missing classes in the UIKit headers, and go to the bottom of the error list; there you should find an error for each time you use a method or class that isn't included in the SDK pointed to by __IPHONE_OS_VERSION_MAX_ALLOWED. Make sure each of these methods is enclosed in an
if( [targetObject respondsToSelector:#selector(thePossiblyMissingSelector:)]
and you should be safe. Classes that may be missing should be tested as well
if ([NSOrderedSet class] != nil)
These settings aren't something you want to accidentally forget to flip back however. To make this an automatic option for testing, do the following:
Create a new build configuration called something like "Old SDK Testing".
Define __IPHONE_OS_VERSION_MAX_ALLOWED and the precompiled head option only for this configuration (hit the disclosure arrow beside each line in Build Settings to access per configuration settings).
Duplicate your current Scheme and set its name to something like "Old SDK Check".
Set the Build Configuration of the Run item in this new scheme to the build configuration you created in step 1.
Select the new Scheme and build.
Notes:
I make no guarantee that this will catch any/all of your issues.
Anything outside of UIKit will not be caught by this check.
This is not a substitute for testing your code on the versions of iOS you
plan to support.
use NSClassFromString();
Class cls = NSClassFromString(#"YourClass");
if (cls == nil)
is this you are looking for?
best way to do that which i found: compile code with old SDK :) link which can help
I think this question is releated with next
I belive that someday Apple allow to compile project for old SDK by simple defining #define __IPHONE_OS_VERSION_MAX_ALLOWED __IPHONE_3_0
upd: I found solution here
4.3 5.0 and 5.1 SDK just fail to compile after trying to redefine this macro
Are you looking for something like
- (BOOL)respondsToSelector:(SEL)aSelector
If you have an instance of a class, you can use the following to see if it understands the method you want to call:
if ([mipmapBrowserView respondsToSelector:#selector(setBackgroundColor:)]) {
// set the background layer since IKImageView supports it
}
Here, mipmapBrowserView is an instance of IKImageView, which was first introduced in Mac OS X 10.5. The setBackgroundColor: method of IKImageView was only added in 10.6, however, so I need to check before I call it. This allows me to build against the 10.6 SDK, and take advantage of the new features, yet still support OS X 10.5 as well. While this example involves OS X rather than iOS, the same method (pun intended?) works in iOS as well.
Note that things are slightly different when you are subclassing a class, and you want to know whether the superclass responds to a certain selector:
"You cannot test whether an object inherits a method from its superclass by sending respondsToSelector: to the object using the super keyword. This method will still be testing the object as a whole, not just the superclass’s implementation. Therefore, sending respondsToSelector: to super is equivalent to sending it to self. Instead, you must invoke the NSObject class method instancesRespondToSelector: directly on the object’s superclass...."

Is it true that one should not use NSLog() on production code?

I was told this a few times in this very site, but I wanted to make sure this is really the case.
I was expecting to be able to sprinkle NSLog function calls throughout my code, and that Xcode/gcc would automatically strip those calls out when building my Release/Distribution builds.
Should I avoid using this? If so, what alternatives are most common between experienced Objective-C programmers?
Preprocessor macros are indeed great for debugging. There's nothing wrong with NSLog(), but it's simple to define your own logging function with better functionality. Here's the one I use, it includes the file name and line number to make it easier to track down log statements.
#define DEBUG_MODE
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( #"<%p %#:(%d)> %#", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
I found it easier to put this entire statement in the prefix header rather than its own file. You could, if you wanted, build a more complicated logging system by having DebugLog interact with normal Objective-C objects. For instance, you could have a logging class that writes to its own log file (or database), and includes a 'priority' argument you could set at runtime, so debug messages are not shown in your release version, but error messages are (if you did this you could make DebugLog(), WarningLog(), and so on).
Oh, and keep in mind #define DEBUG_MODE can be re-used in different places in your application. For example, in my application I use it to disable license key checks and only allow the application to run if it's before a certain date. This lets me distribute a time limited, fully functional beta copy with minimal effort on my part.
Put this 3 lines at the end of -prefix.pch file:
#ifndef DEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
You don't need to define anything into your project, because DEBUG is defined in your build setting by default when you create your project.
NSLog calls can be left in production code, but should only be there for truly exceptional cases, or information that it is desired that will be logged to the system log.
Applications which litter the system log are annoying, and come across as unprofessional.
I can't comment on Marc Charbonneau's answer, so I'll post this as an answer.
Further to adding the macro to your pre-compiled header, you can use the Target build configurations to control the defining (or lack of defining) the DEBUG_MODE.
If you select "Debug" active configuration, DEBUG_MODE will be defined, and the macro expands to the full NSLog definition.
Selecting the "Release" active configuration will not define DEBUG_MODE and your NSLogging is omitted from the release build.
Steps:
Target > Get Info
Build tab
Search for "PreProcessor Macros" (or GCC_PREPROCESSOR_DEFINITIONS)
Select Configuration: Debug
Edit Definition at this Level
Add DEBUG_MODE=1
Select Configuration: Release
confirm DEBUG_MODE is not set in GCC_PREPROCESSOR_DEFINITIONS
if you omit the '=' character in the definition, you will get an error from the preprocessor
Also, paste this comment (shown below) above the macro definition to remind you where the DEBUG_MACRO define comes from ;)
// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
// = Debug: DEBUG_MODE=1
EDIT: The method posted by Marc Charbonneau, and brought to my attention by sho, is far better than this one.
I have deleted the portion of my answer which suggested using an empty function to disable logging when debug mode is disabled. The portion that deals with setting an automatic preprocessor macro is still relevant, so it remains. I have also edited the name of the preprocessor macro so that it fits better with Marc Charbonneau's answer.
To achieve the automatic (and expected) behaviour in Xcode:
In the project settings, go to the "Build" tab, and select the "Debug" configuration. Find the "Preprocessor Macros" section, and add a macro named DEBUG_MODE.
...
EDIT: See Marc Charbonneau's answer for the proper way to enable and disable logging with the DEBUG_MODE macro.
I agree with Matthew. There's nothing wrong with NSLog in production code. In fact, it can be useful to the user. That said, if the only reason you're using NSLog is to help debug, then, yes, that should be removed before you release.
Furthermore, since you've tagged this as an iPhone question, NSLog takes resources, which is something the iPhone has precious little of. If you're NSLogging anything on the iPhone, that takes away processor time from your app. Use it wisely.
The simple truth is that NSLog is just plain slow.
But why? To answer that question, let's find out what NSLog does, and then how it does it.
What does NSLog do exactly?
NSLog does 2 things:
It writes log messages to the Apple System Logging (asl) facility. This allows log messages to show up in Console.app.
It also checks to see if the application's stderr stream is going to a terminal (such as when the application is being run via Xcode). If so it writes the log message to stderr (so that it shows up in the Xcode console).
Writing to STDERR doesn't sound difficult. That can be accomplished with fprintf and the stderr file descriptor reference. But what about asl?
The best documentation I've found about ASL is a 10 part blog post from Peter Hosey: link
Without going into too much detail, the highlight (as it concerns performance) is this:
To send a log message to the ASL facility, you basically open a client connection to the ASL daemon and send the message. BUT - each thread must use a separate client connection. So, to be thread safe, every time NSLog is called it opens a new asl client connection, sends the message, and then closes the connection.
Resources could be found here & here.
As noted in other answers you can use a #define to alter whether NSLog is used or not at compile time.
However a more flexible way is to use a logging library like Cocoa Lumberjack thatallows you to change whether something is logged at runtime as well.
In your code replace NSLog by DDLogVerbose or DDLogError etc, add a #import for the macro definitions etc and setup the loggers, often in the applicationDidFinishLaunching method.
To have the same effect as NSLog the configuration code is
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
From a security point of view, it depends on what is being logged. If NSLog (or other loggers) is writing sensitive information, then you should remove the logger in production code.
From an auditing point of view, the auditor does not want to look at each use of NSLog to ensure its not logging sensitive information. He/she will simply tell you to remove the logger.
I work with both groups. We audit code, write the coding guides, etc. Our guide requires that logging is disabled in production code. So the internal teams know not to try it ;)
We will also reject an external app that logs in production because we don't want to accept the risk associated with accidentally leaking sensitive information. We don't care what the developer tells us. Its simply not worth our time to investigate.
And remember, we define 'sensitive', and not the developer ;)
I also perceive an app which performs lots of logging as an app ready to implode. There's a reason so much logging is performed/needed, and its usually not stability. Its right up there with 'watchdog' threads that restart hung services.
If you have never been through a Security Architecture (SecArch) review, these are the sorts of things we look at.
You shouldn't be needlessly verbose with printf or NSLog in release code. Try only doing a printf or NSLog if the app has something bad happen to it, I.E. an unrecoverable error.
Keep in mind that NSLogs can slow down the UI / main thread. It is best to remove them from release builds unless absolutely necessary.
I would highly recommend using TestFlight for logging (free). Their method will override NSLog (using a macro) and allow you to turn on/off logging to their server, Apple System log and STDERR log, for all your existing calls to NSLog. The nice thing about this is you can still review your log messages for apps deployed to testers and apps deployed in the App Store, without the logs appearing on the user's system log. The best of both worlds.