I am trying to find a way for Cocoa Lumberjack to show me file and line number.
After looking through the docs and some Googling, I found no easy way to do this.
Is there any way to do this without adding custom formatter?
Well, like I said, there is no built-in way. So, I've implemented custom formatter:
#interface LineNumberLogFormatter : NSObject<DDLogFormatter>
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage;
#end
#implementation LineNumberLogFormatter
- (NSString *)formatLogMessage:(DDLogMessage *)logMessage
{
NSString *path = [NSString stringWithCString:logMessage->file encoding:NSASCIIStringEncoding];
NSString *fileName = [path lastPathComponent];
return [NSString stringWithFormat:#"%#:%d %#", fileName, logMessage->lineNumber, logMessage->logMsg];
}
#end
While a separate formatter class would work, it would make your logging code a bit more verbose. In my project I opted for adding some additional macros that make use of CocoaLumberjack like so:
// Prefix.pch file
// ...
#ifdef DEBUG
#define DLogError(fmt, ...) DDLogError((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogWarn(fmt, ...) DDLogWarn((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogInfo(fmt, ...) DDLogInfo((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogDebug(fmt, ...) DDLogDebug((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#define DLogVerbose(fmt, ...) DDLogVerbose((#"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define DLogError(fmt, ...)
#define DLogWarn(fmt, ...)
#define DLogInfo(fmt, ...)
#define DLogDebug(fmt, ...)
#define DLogVerbose(fmt, ...)
#endif
In your client code, you could then call:
DLogWarn(#"This is a warning");
As UrK suggested, there isn't any trivial way, but it's pretty simple if you define your own formatter (see doc)
Related
I'm developing an app that uses a barcode to pull data from an API.
For each call I need to generate a hash value as a signature. Which is a combination of my API ID and the barcode.
I've got an issue where my hashed value is the same each time, therefore my calls are failing.
The functions to create the hash are in objective-C and I have a bridge so I can call it in SwiftUI.
NSString+SHA1.m
#import "NSString+SHA1.h"
#import <CommonCrypto/CommonHMAC.h>
#implementation NSString (SHA1)
- (NSString *)hashedValue:(NSString *)key
{
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [self cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//Used to be [HMAC base64Encoding], but is now depreciated
return hash;
}
#end
As base64Encoding is depreciated, I tried to use base64EncodedStringWithOptions instead. This may be done incorrectly and could be the cause of why my hash value is the same each time.
This is how I call it in SwiftUI:
let hashedValue = scannedCode.barcode.hashedValue("(API ID)")
scannedCode is an observable object that stores the scanned barcode under "barcode" as a String.
In the bridging header:
#import "NSString+SHA1.h"
#import "NSString+SHA1.m"
NSString+SHA1.h
#import <Foundation/Foundation.h>
#interface NSString (SHA1)
- (NSString *)hashedValue:(NSString *)key;
#end
EDIT:
I fixed the problem of the hash value being the same, but the API still isn't accepting my signature. So it's to do with the calculation being wrong.
the code:
<UIKit/UIApplication.h> line 293-297
#if UIKIT_STRING_ENUMS
typedef NSString * UIApplicationLaunchOptionsKey NS_EXTENSIBLE_STRING_ENUM;
#else
typedef NSString * UIApplicationLaunchOptionsKey;
#endif
<UIKit/UIKitDefines.h>
#define UIKIT_STRING_ENUMS ((defined(SWIFT_SDK_OVERLAY_UIKIT_EPOCH) && SWIFT_SDK_OVERLAY_UIKIT_EPOCH >= 2))
What is #define UIKIT_STRING_ENUMS ?
UIKIT_STRING_ENUMS is a macro to control how Objective-C code is imported into Swift
I would like to know how could I identify if there is no element affected by an SQL statement (specifically a Delete). I have the next function associated to a button that erases the content of an UITableView, the parameter i give to it (nombre) it`s a UITextField.text element. Any further information would be given
#import "SD9ProxyBD.h"
#include <sqlite3.h>
#implementation SD9ProxyBD
-(NSMutableArray *)nombres{
sqlite3 *laBd;
sqlite3_stmt *consultaPreparada;
const char *consulta="Select nombre from informacion";
NSString *ruta=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:#"mibd"];
sqlite3_open([ruta UTF8String], &laBd);
sqlite3_prepare(laBd,consulta,-1,&consultaPreparada,NULL);
NSMutableArray *resultados=[[NSMutableArray alloc]init];
while (sqlite3_step(consultaPreparada)==SQLITE_ROW) {
[resultados addObject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(consultaPreparada,0)]];
}
sqlite3_close(laBd);
return resultados;
}
-(void)insertarNombre:(NSString *)nombre{
sqlite3 *laBd;
sqlite3_stmt *consultaPreparada;
const char *consulta="Insert into informacion(nombre) values(?)";
NSString *ruta=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:#"mibd"];
sqlite3_open([ruta UTF8String], &laBd);
sqlite3_prepare(laBd,consulta,-1,&consultaPreparada,NULL);
sqlite3_bind_text(consultaPreparada,1,[nombre UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_step(consultaPreparada);
sqlite3_finalize(consultaPreparada);
sqlite3_close(laBd);
}
-(void)eliminarNombre:(NSString *)nombre{
sqlite3 *laBd;
sqlite3_stmt *consultaPreparada;
const char *consulta="Delete from informacion where nombre=?";
NSString *ruta=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:#"mibd"];
sqlite3_open([ruta UTF8String], &laBd);
sqlite3_prepare(laBd,consulta,-1,&consultaPreparada,NULL);
sqlite3_bind_text(consultaPreparada,1,[nombre UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_step(consultaPreparada);
sqlite3_finalize(consultaPreparada);
sqlite3_close(laBd);
}
#end
And here is the code of the button:
- (IBAction)eliminar:(id)sender {
[self.texto resignFirstResponder];
[self.proxyBD eliminarNombre:self.texto.text];
[self.tabla reloadData];
}
Is there a way to use SQLite soundex() in iOS apps?
Please guide me to find a way...
Tried Homegrew but it works on terminal and I need to run soundex everytime in terminal. Also i dont know how to port to iOS APP.
Terminal work
You can the sqlite3_create_function to create the soundex SQL function:
#import "ViewController.h"
#import <sqlite3.h>
void soundex(sqlite3_context *context, int argc, sqlite3_value **argv);
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self test];
}
- (sqlite3 *)openDatabase
{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path = [docsPath stringByAppendingPathComponent:#"test.db"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path])
{
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"db"];
[fileManager copyItemAtPath:bundlePath toPath:path error:nil];
}
sqlite3 *db;
int rc;
if ((rc = sqlite3_open_v2([path UTF8String], &db, SQLITE_OPEN_READWRITE, NULL)) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_open_v2 failed: %d", __FUNCTION__, rc);
}
return db;
}
- (BOOL)createFunction:(sqlite3 *)db
{
int rc;
if ((rc = sqlite3_create_function(db, "soundex", 1, SQLITE_ANY, NULL, soundex, NULL, NULL)) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_create_function error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
return rc;
}
- (void)test
{
int rc;
sqlite3 *db = [self openDatabase];
[self createFunction:db];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, "SELECT name FROM todo WHERE soundex(name) = soundex('Mani')", -1, &statement, NULL) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_prepare_v2 error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
{
const unsigned char *name = sqlite3_column_text(statement, 0);
if (name)
NSLog(#"name=%s", name);
else
NSLog(#"name=NULL");
}
if (rc != SQLITE_DONE)
{
NSLog(#"%s: sqlite3_step error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
#end
void soundex(sqlite3_context *context, int argc, sqlite3_value **argv)
{
const char *str = (const char*)sqlite3_value_text(argv[0]);
const char *in = str;
static int code[] =
{ 0,1,2,3,0,1,2,0,0,2,2,4,5,5,0,1,2,6,2,3,0,1,0,2,0,2 };
/* a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z */
char ch;
int last;
int count;
char key[5];
/* Set up default key, complete with trailing '0's */
strcpy(key, "Z000");
/* Advance to the first letter. If none present,
return default key */
while (*in != '\0' && !isalpha(*in))
++in;
if (*in == '\0') {
sqlite3_result_text(context, key, 4, SQLITE_TRANSIENT);
return;
}
/* Pull out the first letter, uppercase it, and
set up for main loop */
key[0] = toupper(*in);
last = code[key[0] - 'A'];
++in;
/* Scan rest of string, stop at end of string or
when the key is full */
for (count = 1; count < 4 && *in != '\0'; ++in) {
/* If non-alpha, ignore the character altogether */
if (isalpha(*in)) {
ch = tolower(*in);
/* Fold together adjacent letters sharing the same code */
if (last != code[ch - 'a']) {
last = code[ch - 'a'];
/* Ignore code==0 letters except as separators */
if (last != 0)
key[count++] = '0' + last;
}
}
}
sqlite3_result_text(context, key, 4, SQLITE_TRANSIENT);
}
You need to include the sqlite.c/sqlite.h files in your project from the sqlite amalgamation itself vs. using the libsqlite dylib.
Be sure to set the SQLITE_SOUNDEX preprocessor flag as well to include this feature when you build.
1) download and unzip the sqlite amalgamation. Add the sqlite.h/sqlite.c files to your project.
2) add SQLITE_SOUNDEX=1 to your project's Preprocessor Macros, via the Build Settings screen in XCode.
3) remove libsqlite3XXX.dylib from your project's Link With Libraries list, via the Build Phases screen in Xcode.
Hello guys I have found this code that is used to create a different NSLog (without data and timestamps) that displays the class where the log was made and the line number.
I have read that is possible to disable the logging only for certain classes with NO_LOG but there was not explained how to use it exactly, I am quite new to obj-c and I appreciate an explanation on how to disable logging for certain classes and how to activate and deactivate the debugging. thanks
#define MAKESTRING(__VA_ARGS__) #__VA_ARGS__
#define TOSTRING(...) MAKESTRING(__VA_ARGS__)
static inline void PxReportv(BOOL doLog, char const *file, int line, NSString *prefix, NSString *fmt, va_list argList) {
if (doLog) {
NSString *fileNameWithExtension = [[NSString stringWithFormat:#"%s", file] lastPathComponent];
#ifdef NO_LOG
NSString *fileName = [fileNameWithExtension stringByDeletingPathExtension];
char *f = TOSTRING(NO_LOG);
NSArray *comps = [[[NSString alloc] initWithFormat:#"%s", f] componentsSeparatedByString:#","];
for (NSString *except in comps) {
if ([except isEqualToString:fileName]) {
return;
}
}
#endif
vprintf([[[NSString alloc] initWithFormat:[[NSString alloc] initWithFormat:#"%# <%# [%d]> %#\n", prefix, fileNameWithExtension, line, fmt] arguments:argList] cStringUsingEncoding:NSUTF8StringEncoding], NULL);
}
}
static inline void PxReport(BOOL doLog, char const *file, int line, NSString *prefix, NSString *fmt, ...) {
va_list ap;
va_start(ap, fmt);
PxReportv(doLog, file, line, prefix, fmt, ap);
va_end(ap);
}
#define PxError(...) PxReport(YES, __FILE__, __LINE__, #"[ERROR]", __VA_ARGS__)
#ifdef DEBUG
#define PxDebug(...) PxReport(YES, __FILE__, __LINE__, #"[DEBUG]", __VA_ARGS__)
#define NSLog(...) PxReport(YES, __FILE__, __LINE__, #"", __VA_ARGS__)
#else
#define PxDebug(...)
#define NSLog(...)
#endif
Add this:
#define NO_LOG 1
before #importing the file you've shown above.
BTW a better implementation would define PxDebug() and NSLog() to nothing if NO_LOG was defined...
that is quite a verbose solution, i made one that is a lot neater than that
#ifndef DebugLog_h
#define DebugLog_h
#if DEBUG
#define DLog(...) do{\
printf("[%s:%d]", __FUNCTION__, __LINE__);\
NSString *_S_ = [NSString stringWithFormat:__VA_ARGS__];\
printf(" %s\n",[_S_ cStringUsingEncoding:NSUTF8StringEncoding]);\
}while(0);
#else
#define DLog(...)
#endif
#endif
that will print the line number, class and function it came from
eg:
Dlog(#"hello %d", 123);
[-[SomeViewController viewWillAppear:]:91] hello 123
edit: if you add the file to your projectname-Prefix.pch file, then you can use it without having to include it everywhere
and it will automatically be taken out of release builds, because DEBUG is defined as a project definition automatically when its in debug mode