How to pass parameter values to the custom NSLOG - ios

I'm developing one logger class for my application.NSLog will be printed only in debug mode. I have customized the NSLog where Name of the source file,Source code line number,Name of the class and method where NSLog() was called is printed.
That is , my current NSLOG looks like
(ClassName MethodName) (SourceFileName:LineNumber) NSLog output
Now, I want to log, parameter values of the methodname. How to get those parameter values in NSLog???
I want the output as
(ClassName MethodName) (SourceFileName:LineNumber) (Parameter Values) NSLog output

Something like this should work
#define InstanceLog(fmt, ...) NSLog(#"(%#.%#)(%s:%d) " fmt, NSStringFromClass(self.class), NSStringFromSelector(_cmd), __FILE__, __LINE__, ##__VA_ARGS__)
You may use it as NSLog within Objective-C methods
InstanceLog(#"simple string");
InstanceLog(#"%# %#", #"hello", #"world");

There isn't a way to automatically introspect the values passed to a method. Even in DEBUG builds (where the optimizer is out of the way), any attempts to write code to introspect said iVars is going to be incredibly complex (you'll have to dive into the symbol tables, extract offsets, etc, and then try and find the arguments that were likely destroyed in the attempt to grab them).
So, no, no way to really automate that.
In general, though, any such logging mechanism would generate such an atrociously huge amount of output that you are far better off creating (potentially debugging only) logging that is both configurable and highly tuned to your application.
You can pass args like this (thanks to #hoha for the simpler version).
#import <Foundation/Foundation.h>
#define FooLog(fmt, ...) NSLog(#"(%s): %#", __PRETTY_FUNCTION__, ## __VA_ARGS__)
#interface Bob:NSObject
#end
#implementation Bob
- (void)yourUncle
{
FooLog(#"%#", self);
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSString *w = #"World";
FooLog(#"Hello, %#!", w);
[[Bob new] yourUncle];
}
}
Output:
2013-09-02 10:51:49.447 Untitled[60967:507] (int main(int, char **)): Hello, World!
2013-09-02 10:51:49.453 Untitled[60967:507] (-[Bob yourUncle]): <Bob: 0x7fde8840a490>

for handle custom logging you can use or refer following link.
You can customise Lumberjack as per you needs.
Lumberjack error logging for ios
Lumberjack error logging tutorial

Related

Is there a way to see every time NSLog is called and the content of the NSLog?

Ideally I'd like to setup a selector to see every time NSLog is called in my app, and to get the output of that NSLog. NSLog might be called by an SDK I'm using and I'd like to be able to see the output of those logs from within my app. Is that possible?
What you want is a Symbolic breakpoint.
Navigate to the Breakpoints tab in Xcode and use the + button in the bottom left corner to add one.
When the breakpoint is added, it should automatically come up with a window that allows you to enter the conditions on which you want it to pause execution. You can use NSLog as the symbol.
As for calling a custom function of your own, you can attempt to do that by adding an action in that breakpoint and utilise the debugger's ability to call into your own code by passing in the arguments that are available to the debugger e.g. $arg1.
So I dont think it is possible to simply replace every instance of NSLog with something else... but you could do something like this:
#define NSLog MyLog
void MyLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
void MyLog(NSString *format, ...)
{
va_list list;
va_start(list,format);
NSLogv(format,list);
va_end(list);
va_start(list,format);
vfprintf(stderr,[format UTF8String], list);
va_end(list);
}
int main(int argc, const char * argv[]) {
NSLog(#"hello %s\n","world");
return 0;
}
My example uses 2 va_lists to log with an NSLog like NSLogv and vfprintf to log to an open FILE * stream (stderr in this case)... you could also probably more simply format an NSString (as vfprintf can't print NS objects)...
I tried a little bit to try to re-assign NSLog with dlsym which would be process wide, rather than just when the macro is expanded... I couldn't get it to work but I am not a dynamic linker expert.

Define custom NSAssert that includes line, class and general formatting

As the title reads, how could I define a custom NSAssert which would include the line, class, and formatting as per my NSLog below:
#define NSLog(__FORMAT__, ...) NSLog((#"%#: " __FORMAT__), NSStringFromClass([self class]), ##__VA_ARGS__)
The problem is that NSAssert has a BOOL value first before the rest of the arguments are taken under account. I can't seem to find a solution without taking out the arguments and separating them.
Is there a better way to solve this?
Long story short, I'm looking for something like this:
#define DebugAssert(__VA_ARGS__[0], #"%#: %#", NSStringFromClass([self class]), __VA_ARGS__[1])
The NSAssert macro is defined like this:
#define NSAssert(condition, desc, ...) /* the implementation */
So, the condition is already a separate parameter from the format string and the variable argument list. There should be no problem doing something similar to what you did for NSLog:
#define MyAssert(condition, desc, ...) \
NSAssert(condition, (#"%#: " desc), NSStringFromClass([self class]), ##__VA_ARGS__)

Strange Clang behaviour in Xcode 8.3

Recently i noticed strange behaviour with Objective C memory management in Xcode.
Here is the code:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *firstString = [[NSString alloc] initWithString: #"Hello"];
NSString *secondString = firstString;
[firstString release];
NSLog(#"%#", secondString);
}
return 0;
}
I think, that secondString points to nil after releasing firstString and NSLog should produce error.
But this code does not produce any errors and successfully prints "Hello" string.
I manually compiled and run code with such command and does not noticed any errors too:
% clang -framework Foundation -fno-objc-arc main.m && ./a.out
I tried to compile this code with online objective-c compiler (GCC) (http://rextester.com/l/objectivec_online_compiler) and error was occurred.
What am i doing wrong?
ARC support is turned off in Xcode.
Thanks in advance.
If you perform a static analysis (shift+command+B in Xcode, or "Analyze" on Xcode's "Product" menu), it will warn you that you're trying to reference an object after it is released:
The issue is that in manual reference counting code, your references to deallocated objects are not set to nil automatically. So you can end up with dangling pointers to an object that was previously deallocated unless you manually nil those pointers.
The static analyzer is remarkably good at identifying these sorts of issues, amongst others. I would advise making sure you have a clean bill of health from the static analyzer before moving on.
The second line of defense in situations like this is to enable the zombies runtime debugging option. This will report any attempts to interact with objects after they've been deallocated. Zombies can be enabled in the "Diagnostics" section when you edit your Xcode target's scheme.
Unfortunately, you are using NSString, which doesn't follow the typical memory management rules (it can keep its own references to strings, so they're not always deallocated when you'd otherwise expect them to be).
Consider an example similar to yours, except with a custom class:
#import <Foundation/Foundation.h>
#interface MyObject: NSObject
#end
#implementation MyObject
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
MyObject *firstObject = [[MyObject alloc] init];
MyObject *secondObject = firstObject;
[firstObject release];
NSLog(#"%#", secondObject);
}
return 0;
}
If you run this with zombies on, you'll get a corresponding error message indicating that you're trying to interact with a deallocated instance:
2017-05-27 08:19:18.154033-0700 MyApp[36888:7215135] *** -[MyObject isProxy]: message sent to deallocated instance 0x100303620
But you may not get this warning from NSString. Bottom line, one should avoid drawing any broader memory management conclusions from NSString behavior. Instead, rely upon Xcode's static analyzer and zombies. (Note, remember to turn off zombies when you're done debugging your app.)

Objective-c-Keyboard input

I believe ive looked at every article related to keyboard input, but still cant get it to work. ALl i want is a output, using NSLog everytime i hit a key, in the app or not. Im currently using xcode 5. Ive tried many snippets of code such as
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event)
NSLog(#"%#",event.characters);
and im not sure where to put his code. Do i put it in the main function like this
#import <Foundation/Foundation.h>
#import <appkit/NSEvent.h>
int main(int argc, char * argV[]) {
#autoreleasepool{
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event)
NSLog(#"%#",event.characters);
}
}
Clearly im new to objective-C, and i dont plan on continuing with it unless i can get keyboard input to work. Ive tried tutorials, snippets from keyloggers, and the mac dev forums. Thanks.
Your code is pretty close but you're getting hung up on block syntax. Blocks are very powerful and useful, but the syntax is truly awful and I still struggle with it 2 years after starting to work with them. Blocks are much less readable than C function pointers, and that's saying a lot.
It should look like this:
int main(int argc, char * argV[])
{
#autoreleasepool
{
[NSEvent addGlobalMonitorForEventsMatchingMask: NSKeyDownMask
handler: ^(NSEvent *event)
{
NSLog(#"%#",event.characters);
}
];
}
}
I put all the opening and closing braces on separate lines for clarity. A block needs to be enclosed in braces, and you were missing braces, as well as the closing bracket on your call to addGlobalMonitorForEventsMatchingMask:handler:
BTW, it's very unusual to change the main() function on a Mac or iOS program. Usually you leave that alone, and then set up an application object, set up a delegate, and put your custom code in the app delegate.
You should start of using the normal Cocoa design patterns for applications, and not try to toss them.
If you want to work with main() in C style you should think about creating a command line tool intend of an interactive application. You're going to set yourself up for failure if you don't follow the standard patterns. There's just too many ways to get things wrong.
Your main is missing the housekeeping needed to create a working iOS or Mac application

NSLog giving error when trying to print a single unformatted integer

Hi this is third day of mine using Objective-C today I was writing few simple programs and i ecncountered the following warning
main.m:19:5: warning: passing argument 1 of 'NSLog' makes pointer from integer without a cast [enabled by default]
NSLog(res);
which finally resulted in the Segmentation fault.. Here is my program..
#import <Foundation/Foundation.h>
#interface SomeClass: NSObject
{
int x;
}
#property int x;
#end
#implementation SomeClass
#synthesize x;
#end
int main(){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
SomeClass * obj = [[SomeClass alloc]init];
obj.x =20;
int res = obj.x;
NSLog(res); //error
/* But the error was not seen when I replaced the above statement with
NSLog(#"The value is : %d",res);
*/
[pool drain];
return 0;
}
The error message that I got was :
Compiling the source code....
$gcc `gnustep-config --objc-flags` -L/usr/GNUstep/System/Library/Libraries -lgnustep-base main.m -o demo -lm -pthread -lgmpxx -lreadline 2>&1
main.m: In function 'main':
main.m:19:5: warning: passing argument 1 of 'NSLog' makes pointer from integer without a cast [enabled by default]
NSLog(res);
^
In file included from /usr/GNUstep/System/Library/Headers/Foundation/NSObject.h:30:0,
from /usr/GNUstep/System/Library/Headers/Foundation/FoundationErrors.h:29,
from /usr/GNUstep/System/Library/Headers/Foundation/Foundation.h:33,
from main.m:1:
/usr/GNUstep/System/Library/Headers/Foundation/NSObjCRuntime.h:146:16: note: expected 'struct NSString *' but argument is of type 'int'
GS_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
^
Executing the program....
$demo
Segmentation fault (core dumped)
Please help by making me understand why NSLog behaves like this ? Where did I go wrong?
Thank you...
You can't use the NSLog like this, You need to specify the control string and use like:
NSLog(#"%d",res);
The format should be specified for NSLog(), please check the NSLog and NSLogv reference for more information
NSLog
Logs an error message to the Apple System Log facility.
void NSLog ( NSString *format, ... );
Discussion
Simply calls NSLogv, passing it a variable number of arguments.
Availability
NSLogv
Logs an error message to the Apple System Log facility.
void NSLogv ( NSString *format, va_list args );
Discussion
Logs an error message to the Apple System Log facility (see man 3
asl). If the STDERR_FILENO file descriptor has been redirected away
from the default or is going to a tty, it will also be written there.
If you want to direct output elsewhere, you need to use a custom
logging facility.
The message consists of a timestamp and the process ID prefixed to the
string you pass in. You compose this string with a format string,
format, and one or more arguments to be inserted into the string. The
format specification allowed by these functions is that which is
understood by NSString’s formatting capabilities (which is not
necessarily the set of format escapes and flags understood by printf).
The supported format specifiers are described in “String Format
Specifiers”. A final hard return is added to the error message if one
is not present in the format.
In general, you should use the NSLog function instead of calling this
function directly. If you do use this function directly, you must have
prepared the variable argument list in the args argument by calling
the standard C macro va_start. Upon completion, you must similarly
call the standard C macro va_end for this list.
Output from NSLogv is serialized, in that only one thread in a process
can be doing the writing/logging described above at a time. All
attempts at writing/logging a message complete before the next thread
can begin its attempts.
The effects of NSLogv are not serialized with subsystems other than
those discussed above (such as the standard I/O package) and do not
produce side effects on those subsystems (such as causing buffered
output to be flushed, which may be undesirable). Availability
You cant declare the NSLog like that see the tutorial for NSLog its may be useful for you.
Objective-C has a number of built-in data types:
int – integer constant
float – real numbers with fractional component
double – double precision floating point number
char – a single character
short – short integer (2 bytes)
long – double short
long long – double long
BOOL – boolean
The utility function NSLog() can be used to print to the debug console in Xcode. NSLog() uses the NSString formatting services. The easiest way to create a NSString is to use the #”" notation. Inside a format string a % is a placeholder for a value. The character after the % determines the value expected, be it an int or a float and so on. If we declare an integer “int i = 5″ and want to print the value of i with NSLog() we can do it with NSLog(#”The value of i is %d”, i);
You can use %d to print the value of an int, %f for a float and double, %c for a char. For a full listing of all format specifiers supported by NSString formatting methods read through the documentation.
For More Reference Click Here
keep learning..:)
The 1st argument to NSLog is an NSString that should be a string with 0 or more format specifiers.
Use:
NSLog(#"res = %d", res);
or just:
NSLog(#"%d", res);
Have a look at the reference docs for NSLog for details.
You should specify the compiler that what kind of data type you want to print in Log,
NSLog(#"%d",res);
You should not never use NSLog(variable) directly. Instead, use NSLog(#"%d", variable) for integers or NSLog(#"%#", object) for objects.

Resources