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!
Related
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]));
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 have a C++ function which I call from Objective C.I need to pass variables by reference to the C++ function.But I get the following error in xcode - "Expected ';', ',' or ')' before '&' token in foo.h"
Function declaration in "foo.h"
#ifdef __cplusplus
extern "C"
{
#endif
NSString * LLtoUTM(double Lat,double Long,double &UTMNorthing, double &UTMEasting);
#ifdef __cplusplus
}
#endif
Function call in test_viewcontroller.m
double UTM_x;
double UTM_y;
UTMzone = [[NSString alloc] init];
UTMzone = (NSString *) LLtoUTM(latitude,longitude,UTM_y,UTM_x);
Can anyone tell me what is wrong?
Change the file to be test_viewcontroller.mm.
You told it to compile as an Objective-C file, which doesn't understand references. '.mm' means Objective-C++, which can mix the Obj-C and C++ together like what you're attempting to do.
You simply cannot do this in plain Objective-C — because references don't exist in C. They're a C++ feature. So you have to use Objective-C++, which basically means changing your Objective-C files' extensions to ".mm".
I have imported the pdf.h file in my view controller class and tried calling
NSString *outPutString = convertPDF(pathToPdfFile);
but while building it gives me linker error:
_convertPDF" refrenced from: -[ScriptViewController searchBarSearchButtonClicked:] in ScriptViewController.o Symbol(s) not found
I have also included libz.dylib in my project.
What am I doing wrong?
Is there any step to be followed before building the project which includes c code?
Also one more question:
Will this search algorithm work on any PDF(simple and formatted pdfs).
What if you change the name of the .m file that calls pdf.h to xxxx.mm ? It's a c++ file.
I tested it and found out it works only with simple ascii pdfs.
Your must use the definition in the pdf.h
#if __cplusplus
extern "C" {
#endif
NSString* convertPDF(NSString * pathToFile);
#if __cplusplus
}
#endif
also in the implementation file *pdf.m*m use:
#if __cplusplus
extern "C" {
#endif
NSString* convertPDF(NSString * pathToFile);
#if __cplusplus
} //Extern C
#endif
Suppose I have the following macro:
#define xxx(x) printf("%s\n",x);
Now in certain files I want to use an "enhanced" version of this macro without changing its name. The new version explores the functionality of the original version and does some more work.
#define xxx(x) do { xxx(x); yyy(x); } while(0)
This of course gives me redefition warning but why I get 'xxx' was not declared in this scope? How should I define it properly?
EDIT: according to this http://gcc.gnu.org/onlinedocs/gcc-3.3.6/cpp/Self_002dReferential-Macros.html it should be possible
Not possible. Macros can use other macros but they are using the definition available at expand time, not definition time. And macros in C and C++ can't be recursive, so the xxx in your new macro isn't expanded and is considered as a function.
Self-referential macros do not work at all:
http://gcc.gnu.org/onlinedocs/cpp/Self_002dReferential-Macros.html#Self_002dReferential-Macros
If you're working on C++ you can obtain the same results with template functions and namespaces:
template <typename T> void xxx( x ) {
printf( "%s\n", x );
}
namespace my_namespace {
template <typename T> void xxx( T x ) {
::xxx(x);
::yyy(x);
}
}
You won't be able to reuse the old definition of the macro, but you can undefine it and make the new definition. Hopefully it isn't too complicated to copy and paste.
#ifdef xxx
#undef xxx
#endif
#define xxx(x) printf("%s\n",x);
My recommendation is defining an xxx2 macro.
#define xxx2(x) do { xxx(x); yyy(x); } while(0);
If we know type of 'x' parameter in the 'xxx' macro, we can redefine macro by using it in a function and then define the 'xxx' macro as this function
Original definition for the 'xxx' macro:
#define xxx(x) printf("xxx %s\n",x);
In a certain file make enhanced version of the 'xxx' macro:
/* before redefining the "xxx" macro use it in function
* that will have enhanced version for "xxx"
*/
static inline void __body_xxx(const char *x)
{
xxx(x);
printf("enhanced version\n");
}
#undef xxx
#define xxx(x) __body_xxx(x)
From: https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.html
#define X 1
#pragma push_macro("X")
#undef X
#define X -1
#pragma pop_macro("X")
int x [X];
It is not exactly what you're asking for but it can help.
You can #undef a macro prior to giving it a new definition.
Example:
#ifdef xxx
#undef xxx
#endif
#define xxx(x) whatever
I never heard of (or seen) a recursive macro though. I don't think it is possible.
This answer doesn't answer your question exactly, but I feel like it does a good job at working the way you would intend to use your method (if it was possible).
The idea is for all of your file-specific macros that do actual work to have a unique name (for example LOG_GENERIC and LOG_SPECIFIC), and having the common token (in your case xxx) simply point to the currently appropriate macro.
Plus, using non-standard but widely available #pragma push_macro and #pragma pop_macro we can both modify the common xxx token and restore it to the previous version.
For example, imagine two header files, generic.hpp and specific.hpp, common token here being LOG:
// generic.hpp
#pragma once
#include <cstdio>
#define LOG_GENERIC(x) printf("INFO: " x "\n")
#define LOG LOG_GENERIC
void generic_fn(){LOG("generic");} // prints "INFO: generic\n"
// specific.hpp
#pragma once
#include "generic.hpp"
#define LOG_SPECIFIC(x) do {printf("<SPECIFIC> "); LOG_GENERIC(x);} while (0)
#pragma push_macro("LOG")
#undef LOG
#define LOG LOG_SPECIFIC
void specific_fn(){LOG("specific");} // prints "<SPECIFIC> INFO: specific\n"
#undef LOG
#pragma pop_macro("LOG")
By doing things this way we get the benefits of:
an easy mechanism to modify LOG in a restorable way via #pragma push_macro and #pragma pop_macro
being able to refer to certain LOG_* macros explicitly (LOG_SPECIFIC can use LOG_GENERIC)
we can't refer to LOG inside of LOG_SPECIFIC definition, we have to go through LOG_GENERIC
this is different to your question, but personally I am of the opinion that this is the better design, otherwise you gain the ability to allow macros above the LOG_SPECIFIC definition to affect it, just sounds like the wrong thing to do every time
Link to a github repository with the example above