perhaps I'm blind but I cant figure out what I am doing wrong.
after the 2 runs (there are only 2 values in the database) I get 2 different values like it should be. Then I write it into the NSMutableArray.
But there is only the 2nd value twice. Shouldnt it add to the end of the array? What do I do wrong?
- (NSMutableArray *)getItemsFromDatabaseWithName:(NSString *)databaseName fromTable:(NSString *)tableName andConstraint:(NSString *)constraint
{
NSString *absolutePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:databaseName];
NSLog(#"%#", absolutePath);
//Datenbank öffnen --- "**" bedeuten "&" verwenden
sqlite3_open([absolutePath UTF8String], &_database);
//check if there is a constraint and if not take 2nd statement
if (![constraint isEqualToString:#""])
{
_statement = [NSString stringWithFormat:#"select * from %# where %#",tableName, constraint];
}
else
{
_statement = [NSString stringWithFormat:#"select * from %#",tableName];
}
const char *charStatement = [_statement cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *results;
//new array to return values
_mutableItemArray = [NSMutableArray new];
//new ItemModel
ItemModel *tmpItem = [ItemModel new];
if (sqlite3_prepare_v2(_database, charStatement, -1, &results, NULL)== SQLITE_OK)
{
while (sqlite3_step(results) == SQLITE_ROW)
{
_charItemName = (char *)sqlite3_column_text(results, 1);
[tmpItem setItemName:[NSString stringWithUTF8String:_charItemName]];
_charItemDescription = (char *)sqlite3_column_text(results, 2);
[tmpItem setItemDescription:[NSString stringWithUTF8String:_charItemDescription]];
_charItemYear = (char *)sqlite3_column_text(results, 3);
[tmpItem setItemYear:[_dateFormat dateFromString:[NSString stringWithUTF8String:_charItemYear]]];
_charItemRecommendedBy = (char *)sqlite3_column_text(results, 4);
[tmpItem setItemRecommendedBy:[NSString stringWithUTF8String:_charItemRecommendedBy]];
_charItemImage = (char *)sqlite3_column_text(results, 5);
[tmpItem setItemImage:[NSString stringWithUTF8String:_charItemImage]];
[_mutableItemArray addObject:tmpItem];
#warning here I get the 2 items correct
NSLog(#"ItemName: %#",[tmpItem getItemName]);
NSLog(#"ItemName: %#",[tmpItem getItemDescription]);
}
}
sqlite3_close(_database);
#warning here I get 2 times the same item ???
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:0]);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:1]);
return _mutableItemArray;
}
You just create one object tmpItem.
This will be added to the array and in the next run of the while loop you're not creating a new tmpItem but modifying the old one and add it to the array.
Therefore you will end up with an Array containing two pointers to the same object tmpItem (with the latest state).
Solution: create your tmpItem within the while loop.
If you go through your code you will see inside the while loop you are setting the same object (tmpItem) again and again,that is why your array has last updated values of the same object.
Now see below code you will notice in the while loop, we are creating new object and storing it in an NSArray.
- (NSMutableArray *)getItemsFromDatabaseWithName:(NSString *)databaseName fromTable:(NSString *)tableName andConstraint:(NSString *)constraint
{
NSString *absolutePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:databaseName];
NSLog(#"%#", absolutePath);
//Datenbank öffnen --- "**" bedeuten "&" verwenden
sqlite3_open([absolutePath UTF8String], &_database);
//check if there is a constraint and if not take 2nd statement
if (![constraint isEqualToString:#""])
{
_statement = [NSString stringWithFormat:#"select * from %# where %#",tableName, constraint];
}
else
{
_statement = [NSString stringWithFormat:#"select * from %#",tableName];
}
const char *charStatement = [_statement cStringUsingEncoding:NSUTF8StringEncoding];
sqlite3_stmt *results;
//new array to return values
_mutableItemArray = [NSMutableArray new];
//new ItemModel
if (sqlite3_prepare_v2(_database, charStatement, -1, &results, NULL)== SQLITE_OK)
{
while (sqlite3_step(results) == SQLITE_ROW)
{
ItemModel *tmpItem = [ItemModel new];
_charItemName = (char *)sqlite3_column_text(results, 1);
[tmpItem setItemName:[NSString stringWithUTF8String:_charItemName]];
_charItemDescription = (char *)sqlite3_column_text(results, 2);
[tmpItem setItemDescription:[NSString stringWithUTF8String:_charItemDescription]];
_charItemYear = (char *)sqlite3_column_text(results, 3);
[tmpItem setItemYear:[_dateFormat dateFromString:[NSString stringWithUTF8String:_charItemYear]]];
_charItemRecommendedBy = (char *)sqlite3_column_text(results, 4);
[tmpItem setItemRecommendedBy:[NSString stringWithUTF8String:_charItemRecommendedBy]];
_charItemImage = (char *)sqlite3_column_text(results, 5);
[tmpItem setItemImage:[NSString stringWithUTF8String:_charItemImage]];
[_mutableItemArray addObject:tmpItem];
NSLog(#"ItemName: %#",[tmpItem getItemName]);
NSLog(#"ItemName: %#",[tmpItem getItemDescription]);
}
}
sqlite3_close(_database);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:0]);
NSLog(#"ItemName: %#",[_mutableItemArray objectAtIndex:1]);
return _mutableItemArray;
}
I coulnd not find a solution.
I store data into a local SQLITE DB. Everything works except for accented words.
As in the figure.
However, if I try to store accented word by using SqliteManager (Firefox plugin) everything works. In conclusion: when I store accented word by using my app, strange chars appear.
I use the following code to write data (same for read). Basically, all strings are UTF8 encoded.
-(NSInteger)writeData:(NSDictionary* )data table:(NSString* )table
{
sqlite3_stmt *sqlStatement;
NSMutableArray *columns = [[NSMutableArray alloc] init];
NSMutableArray *values = [[NSMutableArray alloc] init];
NSMutableDictionary *temp = [[NSMutableDictionary alloc] initWithDictionary:data];
#try {
assert([data count] != 0);
if ([[data allKeys] count] == 0) return 1;
[temp removeObjectForKey:#"id"];
[columns addObjectsFromArray:[temp allKeys]];
NSString *cols = [columns componentsJoinedByString:#","];
NSMutableString *colNames = [[NSMutableString alloc] initWithString:
[NSString stringWithFormat:#"INSERT INTO %s (",[table UTF8String]]];
[colNames appendString:cols];
[colNames appendString:#")"];
// VALUES FOR INSERT
[values addObjectsFromArray:[temp allValues] ];
NSMutableString *s = [[NSMutableString alloc] init];
for(int i = 0; i < [values count]; i++)
{
[s setString:[NSString stringWithFormat:#"%#",[values objectAtIndex:i]]];
const char* currentValue = [s UTF8String];
[values setObject:[NSString stringWithFormat:#"\"%s\"",currentValue] atIndexedSubscript:i];
}
NSString *vals = [values componentsJoinedByString:#","];
NSMutableString *valNames = [[NSMutableString alloc] initWithString:#" VALUES ("];
[valNames appendString:vals];
[valNames appendString:#")"];
[colNames appendString:valNames];
const char *sql = [colNames UTF8String];
#ifdef DEBUG
NSLog(#"avvDB writeDATA insert string %#",colNames);
#endif
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement write %s",sqlite3_errmsg(db));
return 0;
}
if (sqlite3_exec(db, sql, NULL, NULL, NULL) == SQLITE_OK)
{
// NSLog(#"Last id %llu %s",sqlite3_last_insert_rowid(db),sqlite3_errmsg(db));
}
}// end try
#catch(NSException* e)
{
NSLog(#"Eccezione in write %#",[e reason]);
}
#finally {
sqlite3_reset(sqlStatement);
sqlite3_finalize(sqlStatement);
sqlStatement = nil;
return sqlite3_last_insert_rowid(db);
}
}
The %s operator does not support unicode characters. As the String Format Specifiers of the String Programming Guide says, it is "Null-terminated array of 8-bit unsigned characters."
Frankly, for other reasons, you shouldn't be using stringWithFormat anyway (what if one of the strings had a quotation mark in it ... your SQL statement would fail; you're even exposed to SQL injection attacks). You should be using a ? placeholder instead (with no quotation marks), and then call sqlite3_bind_text for each of the parameters you want to bind to the respective question mark (note, sqlite3_bind_xxx functions use a 1-based index, unlike sqlite3_column_xxx which use a 0-based index).
I have to remove an NSString (containing some confidential data) from memory but not only by setting it to nil, but by nullifying it's bytes. What I've tried so far is:
NSString *str = #"test";
NSLog(#"original string:%#", str);
CFStringRef ref = (__bridge CFStringRef)str;
const char * strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
memset(strPtr, 0, [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
NSLog(#"cleared string:%#", str);
but the function CFStringGetCStringPtr is returning NULL so it crashes at the line with the memset. Apple says here that in some cases it is normal for that function to return NULL, but then I don't know how to solve this.
Thanks in advance
Don't store confident data as strings. You can't remove them from memory easily.
If possible, use NSMutableData to store confident data, instead.
Try This:
NSMutableString *str = [NSMutableString stringWithString:#"test"];
NSLog(#"original string:%#", str);
CFStringRef ref = ( CFStringRef)str;
CFIndex stringLength = CFStringGetLength(ref), usedBytes = 0L;
const char * strPtr = NULL;
strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
char *freeUTF8StringPtr = NULL;
for(CFIndex idx = 0L; (strPtr != NULL) && (strPtr[idx] != 0); idx++)
{
if(strPtr[idx] >= 128) { strPtr = NULL; }
}
if((strPtr == NULL) && ((freeUTF8StringPtr = malloc(stringLength + 1L)) != NULL))
{
CFStringGetBytes(ref, CFRangeMake(0L, stringLength), kCFStringEncodingUTF8, '?', false, (UInt8*)freeUTF8StringPtr, stringLength, &usedBytes);
freeUTF8StringPtr[usedBytes] = 0;
strPtr = (const char *)freeUTF8StringPtr;
}
NSUInteger memorySize=[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"cleared string:%#", str);
I have tried something like this below:-
NSMutableString *str = #"test";
NSLog(#"original string:%#", str);
CFStringRef ref = (__bridge CFStringRef)str;//kCFStringEncodingUTF16
const char * strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF16);
NSUInteger memorySize=[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"cleared string:%d", memorySize);
Output := 4
Using the method described in this question, I can get a list of apps running on an iOS device.
I know PIDs and have access to their kinfo_proc structures.
How can I determine which are foreground processes and which are background (assuming my app is background)?
I tried to find this out base on information in kinfo_proc (see 1st link), via kp_proc.p_priority, but it looks like it is not possible to infer background/foreground state from priority.
I don't really care if this works correctly for AppStore Review but I would prefer a method that will work without a jailbreak(i.e. Private APIs are ok but which ones?). I want this to work at least on iOS 5
I considered writing a simple MobileSubstrate extension, injecting it into all apps and just hook everyone's applicationDidBecomeActive, but this requires a jailbreak and is too invasive.
Well, looks like some usage of nm and IDA on SpringBoardServices binary from simulator helped me on this.
Following code works on iOS 5.0.1 running on iPod Touch 4, iPhone 4 and iPad1 WiFi(all non-JB)
Of course you should never try to submit that to AppStore
- (NSArray*) getActiveApps
{
mach_port_t *p;
void *uikit = dlopen(UIKITPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(uikit, "SBSSpringBoardServerPort");
p = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(uikit);
void *sbserv = dlopen(SBSERVPATH, RTLD_LAZY);
NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) =
dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers");
//SBDisplayIdentifierForPID - protype assumed,verification of params done
void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) =
dlsym(sbserv, "SBDisplayIdentifierForPID");
//SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not)
void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) =
dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier");
//Get frontmost application
char frontmostAppS[256];
memset(frontmostAppS,sizeof(frontmostAppS),0);
SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS);
NSString * frontmostApp=[NSString stringWithFormat:#"%s",frontmostAppS];
//NSLog(#"Frontmost app is %#",frontmostApp);
//get list of running apps from SpringBoard
NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO);
//Really returns ACTIVE applications(from multitasking bar)
/* NSLog(#"Active applications:");
for(NSString *identifier in allApplications) {
// NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier);
NSLog(#"Active Application:%#",identifier);
}
*/
//get list of all apps from kernel
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
int ruid=process[i].kp_eproc.e_pcred.p_ruid;
int uid=process[i].kp_eproc.e_ucred.cr_uid;
//short int nice=process[i].kp_proc.p_nice;
//short int u_prio=process[i].kp_proc.p_usrpri;
short int prio=process[i].kp_proc.p_priority;
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
BOOL systemProcess=YES;
if (ruid==501)
systemProcess=NO;
char * appid[256];
memset(appid,sizeof(appid),0);
int intID,intID2;
intID=process[i].kp_proc.p_pid,appid;
SBDisplayIdentifierForPID(p,intID,appid);/
NSString * appId=[NSString stringWithFormat:#"%s",appid];
if (systemProcess==NO)
{
if ([appId isEqualToString:#""])
{
//final check.if no appid this is not springboard app
NSLog(#"(potentially system)Found process with PID:%# name %#,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio);
}
else
{
BOOL isFrontmost=NO;
if ([frontmostApp isEqualToString:appId])
{
isFrontmost=YES;
}
NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName",#"AppID",#"isFrontmost", nil]];
NSLog(#"PID:%#, name: %#, AppID:%#,isFrontmost:%d",processID,processName,appId,isFrontmost);
[array addObject:dict];
}
}
}
free(process);
return array;
}
}
}
dlclose(sbserv);
}
Of course 2nd loop is not strictly necessary but I needed non-localized names & PIDs too.
Great answer! But there is a small typo in your code, it should be:
First make sure that SBSERVPATH is defined and the correct header files are included:
#import <sys/sysctl.h>
#import <dlfcn.h>
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
Then first find the correct SB port:
mach_port_t *port;
void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(lib, "SBSSpringBoardServerPort");
port = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(lib);
And then find the active app:
mach_port_t * port = [self getSpringBoardPort];
// open springboard lib
void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
// retrieve function SBFrontmostApplicationDisplayIdentifier
void *(*SBFrontmostApplicationDisplayIdentifier)(mach_port_t *port, char *result) =
dlsym(lib, "SBFrontmostApplicationDisplayIdentifier");
// reserve memory for name
char appId[256];
memset(appId, 0, sizeof(appId));
// retrieve front app name
SBFrontmostApplicationDisplayIdentifier(port, appId);
// close dynlib
dlclose(lib);
This is what works for me on all IOS devices:
#define UIKITPATH "/System/Library/Framework/UIKit.framework/UIKit"
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
- (NSArray*) getActiveApps
{
mach_port_t *p;
void *uikit = dlopen(UIKITPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() =
dlsym(uikit, "SBSSpringBoardServerPort");
p = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(uikit);
if(self.frameWorkPath == nil || self.frameWorkPath.length == 0)
{
self.frameWorkPath = #SBSERVPATH;
self.frameWorkPath = [self.frameWorkPath stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]];
}
const char *cString = [self.frameWorkPath cStringUsingEncoding:NSUTF8StringEncoding];
//const char *bar = [self.frameWorkPath UTF8String];
void *sbserv = dlopen(cString, RTLD_LAZY);
NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) =
dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers");
//SBDisplayIdentifierForPID - protype assumed,verification of params done
void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) =
dlsym(sbserv, "SBDisplayIdentifierForPID");
//SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not)
void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) =
dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier");
//Get frontmost application
char frontmostAppS[512];
memset(frontmostAppS,sizeof(frontmostAppS),0);
SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS);
NSString * frontmostApp=[NSString stringWithFormat:#"%s",frontmostAppS];
if([self iOsMajorVersion] >= 7){
NSNumber *topmost = [NSNumber numberWithBool:YES];
NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
NSMutableArray * splitted = [frontmostApp componentsSeparatedByString:#"."];
if(frontmostApp.length > 0 && splitted != nil && splitted.count > 1 && topmost.boolValue == YES){
NSString *appname = [splitted lastObject];
[dict setObject:[appname capitalizedString] forKey:#"ProcessName"];
[dict setObject:frontmostApp forKey:#"ProcessID"];
[dict setObject:frontmostApp forKey:#"AppID"];
[dict setObject:topmost forKey:#"isFrontmost"];
NSLog(#"Running TOPMOST App %#",dict);
return #[dict];
}
else{
return nil;
}
}
//NSLog(#"Frontmost app is %#",frontmostApp);
//get list of running apps from SpringBoard
NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO);
//Really returns ACTIVE applications(from multitasking bar)
NSLog(#"Active applications:");
for(NSString *identifier in allApplications) {
// NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier);
NSLog(#"Active Application:%#",identifier);
}
//get list of all apps from kernel
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
size_t miblen = 4;
size_t size;
int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
struct kinfo_proc * process = NULL;
struct kinfo_proc * newprocess = NULL;
do {
size += size / 10;
newprocess = realloc(process, size);
if (!newprocess){
if (process){
free(process);
}
return nil;
}
process = newprocess;
st = sysctl(mib, miblen, process, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st == 0){
if (size % sizeof(struct kinfo_proc) == 0){
int nprocess = size / sizeof(struct kinfo_proc);
if (nprocess){
NSMutableArray * array = [[NSMutableArray alloc] init];
for (int i = nprocess - 1; i >= 0; i--){
int ruid=process[i].kp_eproc.e_pcred.p_ruid;
int uid=process[i].kp_eproc.e_ucred.cr_uid;
//short int nice=process[i].kp_proc.p_nice;
//short int u_prio=process[i].kp_proc.p_usrpri;
short int prio=process[i].kp_proc.p_priority;
NSString * processID = [[NSString alloc] initWithFormat:#"%d", process[i].kp_proc.p_pid];
NSString * processName = [[NSString alloc] initWithFormat:#"%s", process[i].kp_proc.p_comm];
BOOL systemProcess=YES;
if (ruid==501){
systemProcess=NO;
}
char * appid[256];
memset(appid,sizeof(appid),0);
int intID,intID2;
intID=process[i].kp_proc.p_pid,appid;
SBDisplayIdentifierForPID(p,intID,appid);
NSString * appId=[NSString stringWithFormat:#"%s",appid];
if (systemProcess==NO)
{
if ([appId isEqualToString:#""])
{
//final check.if no appid this is not springboard app
//NSLog(#"(potentially system)Found process with PID:%# name %#,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio);
}
else
{
BOOL isFrontmost=NO;
if ([frontmostApp isEqualToString:appId])
{
isFrontmost=YES;
}
NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost];
NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil]
forKeys:[NSArray arrayWithObjects:#"ProcessID", #"ProcessName",#"AppID",#"isFrontmost", nil]];
NSLog(#"PID:%#, name: %#, AppID:%#,isFrontmost:%d",processID,processName,appId,isFrontmost);
[array addObject:dict];
}
}
}
free(process);
return array;
}
}
}
dlclose(sbserv);
}
In my iPhone app I am getting the device token from Apple which I am assigning a public property inside the Delegate file as shown below:
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
self.dToken = [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding];
}
The dToken property is declared as shown below:
NSString *dToken;
#property (nonatomic,retain) NSString *dToken;
But when I try to retrieve the device token from another file I get the null value.
+(NSString *) getDeviceToken
{
NSString *deviceToken = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] dToken];
NSLog(#" getDeviceToken = %#",deviceToken); // This prints NULL
return deviceToken;
}
What am I doing wrong?
I suggest you to convert token to string in this way:
self.dToken = [[[deviceToken description]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]]
stringByReplacingOccurrencesOfString:#" "
withString:#""];
UPDATED:
As many people mentioned it is better to use next approach to convert NSData * to NSString *:
#implementation NSData (Conversion)
- (NSString *)hexadecimalString
{
const unsigned char *dataBuffer = (const unsigned char *)[self bytes];
if (!dataBuffer) {
return [NSString string];
}
NSUInteger dataLength = [self length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i) {
[hexString appendFormat:#"%02lx", (unsigned long)dataBuffer[i]];
}
return hexString;
}
#end
From the discussion at Best way to serialize an NSData into a hexadeximal string, here is a better way to do it. Is longer, but your code will be future-proof if Apple changes the way NSData emit debugger descriptions.
Extend NSData as follows:
#implementation NSData (Hex)
- (NSString*)hexString {
unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (self.length*2));
unsigned char* bytes = (unsigned char*)self.bytes;
for (NSUInteger i = 0; i < self.length; i++) {
unichar c = bytes[i] / 16;
if (c < 10) c += '0';
else c += 'A' - 10;
hexChars[i*2] = c;
c = bytes[i] % 16;
if (c < 10) c += '0';
else c += 'A' - 10;
hexChars[i*2+1] = c;
}
NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars
length:self.length*2
freeWhenDone:YES];
return [retVal autorelease];
}
#end
I know that this is an old question and that this may be new information that has come up since then, but I'd just like to point something out to all of the people who are claiming that using the description method is a really bad idea. In most cases, you'd be exactly right. The description property is generally just used for debugging, but for the NSData class, it's specifically defined as returning a hexadecimal representation of the receivers contents which is exactly what is needed here. Since Apple has put it in their documentation, I think you're pretty safe as far as them changing it.
This can be found in the NSData Class Reference here: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html