How do I disable NSLog? - objective-c

I'd like to do the following in Xcode:
Find all NSLog commands without comments, and replace it with //NSLog...
In other words, I want to comment all NSLog calls. Is this possible? Is there an easy way to do this?

wait there is far more simple method. Just add the following lines when you dont need NSLOG to your constants file
#define NSLog //
and comment it when you need it.
EDIT: In latest Xcode, you get error on above statement. So I figured out the best way is
#define NSLog(...)

Update:
The answer bellow is actually much better. See here.
Initial answer:
There is a little hack that you could do. Search for all NSLog and replace them with //NSLog and than do another search for ////NSLog and replace them with //NSLog.

#define NSLog if(1) NSLog
if you dont want log set 1 as 0.

I have to do a separate answer because I cant comment yet, but one thing you really need to be careful about when you do a find and replace is something like this:
if(BOOL)
NSLog(#"blah blah");
[self doSomething];
If you comment out the nslog, the conditional gets associated with the method below it, correct me if I'm wrong

The answers you have are correct for your question. But. Your real question is how to turn of NSLogs in certain conditions. i.e. you want them to show for Debug builds, and not for Release builds. In which case try defining and using the DLog() macro as described on Cocoa Is My Girlfriend. If you're using Xcode4 it's even easier because the Debug and Release builds define and undefine DEBUG so you don't have to do that.
It's a lot easier than commenting and uncommenting lines of code.

#ifdef RELEASE
#define NSLog(...) do { } while (0)
#endif
is the best way i found so far.

#define NSLog(...)
add this line into your .pch file
if you want log than comment it

You can do this in a single find and replace operation. You can just do this simple Regular Expression replace. This handles both the commented(//) and non-commented lines. This also works even if the previous commented lines has more than two forward slashes(like ///)instead of rwo. You can refer this link. Do the following steps.
Select Edit > Find > Find and Replace in Workspace
Style => Regular Expression
Type (/)*(NSLog.*) in Find field.
Do the find operation.
Type //\2 in the Replace field.
Do the replace operation.
Enjoy the beauty of regular expressions ;-)

I would do this
#define EnableNSLog 1
#if EnableNSLog == 0
#define NSLog //
#elif EnableNSLog == 1
#warning Disable NSLog
#endif
This should generate a warning message to remind me to disable NSLog before final release.

right click on NSLog statement in xcode and select "find in project" as text.you would be prompted to a new window where you can follow the guidance given by Mihai Fratu.
TNQ

in the Menu bar : Edit > Find > Find and Replace in Workspace
then, display options to use regular expressions.
search/replace for "[^/]NSLog"

How to disable NSLog in Xcode for Production stage
Add #define NSLog in appName-Prefix.pch file in Supporting Files Folder of your project
and result file code look like...
// Prefix header for all source files of the 'NSLog' target in the 'NSLog' project
//
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
//Add this to disable NSLog
#define NSLog //

You can use following Preprocessor Directives, it will not go with release mode.
So you don't have to commenting NSLog().
#ifdef DEBUG
NSLog(#"YOUR MESSAGE HERE!");
#endif

try this also:
#define NSLog(#"YOUR MESSAGE HERE!") do { } while (0)

Add the following line to your .pch file
#define NSLog
for enable comment it

Related

Is there some no op operation in objective-c that we can use just to set breakpoint

The code shouldn't have any effect
It should be doable anywhere
It doesn't generate compiler warning
Basically sometimes I want to do NSAssert. However, rather than NSAssert, I sometimes want to do my if {} my self. That way I can just easily set or unset the break point
Currently this is what I do.
if (entityName==#"Business")
{
error=nil; //Some code for breakpoint. I want something that do nothing actually.
}
It's just happen that I have a variable named error that I will no longer use. But what would be a goodalternative
I also tried [nil donothing]; but that got compiler error.
Try this:
while (false);
There are other possibilities, like if (false) or even just a line with a lone semicolon ;, but in those cases execution stops at the next instruction, possibly because the compiler simply eliminates those empty bits of code. Using while has the advantage that execution will stop on that line (assuming you put a breakpoint there, of course).
You can give breakpoints conditions, hold down option and command and click the breakpoint, you should get a pop-up. In the 'condition' field yo can enter something like
[entityName isEqualToString:#"Business"]
(Note that you should compare strings with -isEqualToString: not ==, as the latter compares the pointers not the characters in the strings themselves.)
By using the condition in the breakpoint you shouldn't need the if statement at all, and also enable and disable the check without without recompiling. There is a lot more you can do with the breakpoint settings, like have it automatically log a message or run a debugger command etc.
In C, you can have a no-op instruction simply putting a semicolon alone in a line:
if (TRUE) {
; // Neutral operation
}
In Objective-C you could do the same, the thing is your program stops before the next line, as you can see here:
you don't compare 2 strings directly; try [NSString isEqualToString:]
you can use __asm int 3;
if ([entityName isEqualToString:#"Business"]) {
__asm int 3;
}
From CFInternal.h.
#if defined(__ppc__) || defined(__ppc64__)
#define HALT asm __volatile__("trap")
#elif defined(__i386__) || defined(__x86_64__)
#if defined(__GNUC__)
#define HALT asm __volatile__("int3")
#elif defined(_MSC_VER)
#define HALT __asm int 3;
#else
#error Compiler not supported
#endif
#endif
if ([entityName isEqualToString:#"Business"]) {
HALT;
}

Conditional NSLog, Without decreasing Performance

bool kDebuggingEnabled = NO;
...
for(i=0; i<length; i++){
...
if (kDebuggingEnabled) {
NSLog (#"Value of variable # %i",$resultingOptions);
}
}
whenever my app is live, my code checks the condition every time regarding NSLog.
Is there any better way to improve performance of my code?
You could use preprocessor macros to turn logging on and off. A good example is the DLog macro from Marcus Zarra on the Cocoa is My Girlfriend blog.
#ifdef DEBUG
#define DLog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
#define DLog(...) do { } while (0)
#endif
You would place the above in your prefix.pch file and then simply replace NSLog statements with DLog statements. You also need to make sure that DEBUG is set in your debug build configuration.
Using preprocessor macros like this means that the logging code does not get compiled into your release build so there is no performance hit for the log statements.
The blog post also contains some other useful macros for handling assertions.
You have 3 choices:
1) if you want to enable/disable your logs at build time. The preprocessor solutions are the best:
// define MY_ENABLE_LOGS in your build settings for the debug configuration only, for example
#ifdef MY_ENABLE_LOGS
#define MYLog(...) NSLog(__VA_ARGS__)
#else
#define MyLog(...) do { } while(0)
#endif
2) if you want to be able to enable/disable logs at runtime (e.g. based on some hidden preferences), your solution is likely the best. You can try to hint the compiler to optimize things a bit, though:
// tell the compiler it's unlikely that kDebuggingEnabled will be true
#define MYLog(...) do { if (__builtin_expect(kDebuggingEnabled, 0)) { NSLog(__VA_ARGS__); } } while(0)
3) last option is a little bit more complicated but can provide richer info than just logs and only depends on the kind of logging you expect to provide. The idea is to use custom probes with dtrace (which can also be used within Instruments). This only works in OS X (not in iOS). See http://www.macresearch.org/tuning-cocoa-applications-using-dtrace-custom-static-probes-and-instruments for example.
Note that you can mix 1) and 2) depending on your needs. 3) is meant to be almost zero cost when probes are not traced and can provide much richer info than a simple log string.
One caveat with these solutions: the arguments of the logs won't be evaluated when MY_ENABLE_LOGS is not defined which might change your application behavior.
Use a preprocessor macro to check if you're building for debug:
#if DEBUG
// do stuff
#end
If the preprocessor (the thing that runs before the compiler) evaluates DEBUG to be true it'll keep the code there for the compiler to compile, but if DEBUG doesn't exist or is false, it'll erase that piece of code.

cannot combine with previous 'type-name' declaration specifier

My iOS app was working and all of a sudden I'm seeing this error: "cannot combine with previous 'type-name' declaration specifier". Any ideas on what could be causing this error?
#import "SalesAPIManager.h"
#interface SalesDelegate : NSObject { // error points to this line
__unsafe_unretained id<SalesAPIManagerDelegate> delegate_;
}
#property (unsafe_unretained, nonatomic) id<SalesAPIManagerDelegate> delegate;
- (id)initWithDelegate:(id<SalesAPIManagerDelegate>)delegate;
#end
Likewise I had a typo in a random file in the project. It was just some plain text that was accidentally placed before a comment. My suggestion to fix/find it would be to put a ; just before the statement that is flagged. This then drew a warning to the errant text when I compiled.
It's one of the disadvantages of Xcode.
Xcode is one of the worst IDE's ever, Apple is trying to make it better every update.
But this issue raises when you add "Some word" in some places that the compiler of Xcode is not looking at it.
My case was like in image :
I forgot to delete the word RESideMenu in AppDelegate.h
and the strange thing that Xcode accepts the code until the Build and when it fires error it rays it in another and not related class.
I had this same problem. It turns out I had a typo in my main.m file. Once I cleared that up, this error went away.
I saw this error when there was some dead incomplete code in my file that I'd forgotten to take out. The compiler indicated the error at the start of a method at the return type, so I spent a lot of time looking at the method declaration and call. Turned out the incorrect typo was above the method. since there was no ";" the compiler could only tell that the void keyword was misplaced.
I get the same problem. And I finally fix it after cleaning some junk text at the bottom of my .h file. you may try.
I got it in a header file when in fact the error was in the .cpp. Turns out I had a method trying to return a bool in a sketchy way:
return (x == 1 && y == 2);
Which it turns out doesn't work, but Xcode told me in this very obscure way.
Not sure if this helps, but it's another example in a seeming desert of them.
I know this is very late, however, I just had this error come up in my cpp Xcode project (line 31) and it disappeared after I completed the string initialization directly above it (line 28). My code was as follows:
Cannot combine with previous 'type-name' declaration specifier
string //STRING NEEDING INITIALIZATION
void AMPM() {
if ((firstHourChar == 1) && (secondHourChar > 2)) {
afterAM = true;
}
}

how to get rid of warning related to : indexForInsertingObject:sortedUsingBlock:

I have the following line of code:
int insertIdx = (int)[self.itemsToDisplay indexForInsertingObject:item sortedUsingBlock:^(id a, id b) {
MWFeedItem *item1 = (MWFeedItem *) a;
MWFeedItem *item2 = (MWFeedItem *) b;
return [item1.date compare:item2.date];
}];
but XCode gives me the following warning on it:
NSMutableArray' may not respond to '-indexForInsertingObject:sortedUsingBlock:
how to get rid of this warning ? and could I know where excatly this method is defined in the SDK ?
thanks so much in advance ...
-indexForInsertingObject:sortedUsingBlock: is not part of the official, public SDK. Since it looks like you haven’t declared and implemented a category on NSMutableArray that contains that method, you could write one based on this blog post by Jayway Team. Having done that, it’s just a matter of importing the header file that declares the category.
to disable the warnings for one file add this:
#pragma GCC diagnostic ignored "-Wwarning-flag"
It should ignore all warnings. The problem is however you will not see any warnings in that file. even if they are legit.

What's a 'null defined macro'?

I'm learning objective-C and Cocoa. In the Apple tutorial I'm working through there's a side note that says:
IBOutlet is a null-defined macro, which the C preprocessor removes at compile time.
I'm curious - what's a null-defined macro?
#define IBOutlet
Whenever IBOutlet is used in program text, it will be replaced with nothing at all.
FYI, in this particular case, the reason the IBOutlet even exists is simply so that Interface Builder can parse the source file and glean bits of understanding from it. It's a clue (well, a bit stronger than a clue) that the variable preceded by IBOutlet should show up as an Outlet in Interface Builder when designing your UIs.
A null-defined macro is a macro which will be replaced by nothing (will be removed) by the preprocessor. It's role is to give a hint about something in code, such as:
#define IN
#define OUT
#define INOUT
int myFunction(IN char *name, INOUT char *address, OUT char *phone);
This declaration suggests that name is a input variable for the function, address is both input and output, phone is an output variable.
Also - if you're unsure how anything is defined - command double-click it and Xcode will open the definition in the original source file.
Oh and while I'm at it. Option double click will (attempt to) open up the documentation for the double clicked symbol.