Unrecognized selector which doesn't appear in source code causes crash - ios

Contents of NSString+sha1.h:
#include <CommonCrypto/CommonDigest.h>
#include <Foundation/Foundation.h>
#interface NSString (sha1)
- (NSString *) sha1;
#end
Contents of NSString+sha1.m:
#include "NSString+sha1.h"
#implementation NSString (sha1)
- (NSString *) sha1 {
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:input.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return [NSString stringWithString:output];
}
#end
Contents of UIImage+RenderBatteryImage.m:
#include "UIImage+RenderBatteryImage.h"
#include "NSString+sha1.h"
[...]
[#"A string (but not this one)" sha1]
When the code from the third file runs, I get this error:
-[__NSCFString sha1]: unrecognized selector sent to instance 0x12ee1caf0
What is causing this? I can confirm that I have no instances of uppercase SHA1 in any of my source files.

I have an assumption that require validation. In syslog you have following error:
-[__NSCFString sha1]: unrecognized selector sent to instance 0x12ee1caf0
Looks like your method sha1 is not found and it cause a crash. How it may happen? Compiler replace an object of #"A string (but not this one)" with some internal object that represents constant string and you do not have a category method defined for this particular constant string type.
Here is workflow that I suggest to apply to validate and fix assumption:
Comment out string where you do sha1 call and check that error is not happening
Replace literal with an actual object [NSString withString: #"your string"] to oversmart compiler
Here is actually some proof that my assumption right regarding compile-time replacement of a string by constant representation — What is the different between NSCFString and NSConstantString?

Sample code, a simple self-contained method, just add it to your class:
// Add Security.framework to the project.
#include <CommonCrypto/CommonDigest.h>
+ (NSString *) sha1:(NSString *)string {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (CC_LONG)data.length, hash.mutableBytes);
NSMutableString *hexAscii = [NSMutableString new];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[hexAscii appendFormat:#"%02x", ((uint8_t *)hash.mutableBytes)[i]];
return [hexAscii copy]; // Make immutable
}
Test (assuming that the method is in the class Test.
NSString *hashHexASCII = [Test sha1:#"test String"];
NSLog(#"hashHexASCII: %#", hashHexASCII);
Output:
hashHexASCII: 9269ca2a6a1695eff8d5acd47b57c045698e3ce1

Related

How to use Static Variable to save a string in objective-c?

I want to use Static Var to save a NSString.
So I define a Static Var in a .h file like this:
#ifndef GlobalParameters_h
#define GlobalParameters_h
//access token
static NSString *applicationToken;
#endif
In class A, I change the static var like this:
#import "ClassA.h"
#import "GlobalParameters.h"
extern NSString *applicationToken;
#implementation ClassA
+ (void)parseResponse:(NSString *)response
{
NSDictionary *responseDic = [response objectFromJSONString];
NSString *token = [responseDic objectForKey:#"token"];
applicationToken = [token copy];
NSLog(#"%#",applicationToken);
}
When the debugger run to
applicationToken = [token copy];
I found the "applicationToken" is nil,but the next sentence
NSLog(#"%#",applicationToken);
can output the right value in console! And in ClassB , the "applicationToken" is nil too.
I don't know why the static var is nil. I think the compiler will find the definition of "applicationToken" in GlobalParameters.h.But why I can't modify the static value?
Thanks for your help:)
static global variable mean that it's own for every object-file it's used. So there is willbe own applicationToken for ClassA, ClassB.
To create global variable for all object-files you need this:
In GlobalParameters.h:
#ifndef GlobalParameters_h
#define GlobalParameters_h
//access token
extern NSString *applicationToken;
#endif
In GlobalRarameters.m:
#import "GlobalParameters.h"
NSString *applicationToken;
P.S. I hope you use ARC, because if not, then applicationToken = [token copy]; will cause memory leaks.
Hey Its working fine , I am checking like this
Once check the are you getting "responseDic" (or) not , Check the
The dictionary have token key
static NSString *applicationToken;
applicationToken = #"srinivas";
NSLog(#"%#",applicationToken);
NSDictionary *responseDic = [NSDictionary dictionaryWithObject:#"static" forKey:#"token"];
NSString *token = [responseDic objectForKey:#"token"];
applicationToken = [token copy];
NSLog(#"%#",applicationToken);
[AppDelegate parseResponse:responseDic];

From NSString to escaped chars in iOS

I am not sure if I am asking the right question, please correct me if I'm wrong, but I've searched everywhere and I can't find an answer to help me with the following issue:
I have a NSString with the following content: "Björn Br. Björnsson"
and I need to get it to the following form: "Bj\u00f6rn Br. Bj\u00f6rnsson".
I've tried everything I found related on stackoverflow so far. If anyone has any idea how to get from ö type of characters to \u00f6 it would be awesome.
I have tried:
NSString *name = #"Björn Br. Björnsson";
NSString* string = [NSString stringWithCString:[name cStringUsingEncoding: NSUTF8StringEncoding] encoding:NSNonLossyASCIIStringEncoding];
or
NSMutableString *string = [[NSMutableString alloc] initWithString:name];
const char *encoded = [string cStringUsingEncoding:NSASCIIStringEncoding];
or
NSData* nsData = [name dataUsingEncoding:NSUTF8StringEncoding];
const char* data = [nsData bytes];
NSUInteger len = nsData.length;
NSMutableString* hex = [NSMutableString string];
for(int i = 0; i < len; ++i)[hex appendFormat:#"%02X", data[i]];
or
const char * encodedStringName = [crewmemName cStringUsingEncoding:NSISOLatin1StringEncoding];
and many other..
Thanks in advance.
You can create a category on NSString and call this method, this will encode to your desired way
#implementation NSString (URLEncoding)
- (NSString *) stringByUrlEncoding{
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)#"!*'();:#&;=+$,/?%#[]", kCFStringEncodingUTF8));
}
#end
NSString *name = #"Björn Br. Björnsson";
name =[name stringByReplacingOccurancesOfString:#"ö" withString:#"\u00f6"];
You may have to escape the backslash. Just type \\\ instead of \. But not sure about that.

UITableView Headers with UTF-8 Strings?

I'm formatting my UITableView headers with Unix %s formatting because the Objective C format code %# doesn't handle padding (e.g. %20#%20s). Unfortunately, if I have accented foreign characters, they aren't displayed properly. The word "voilà" appears like this:
Here's how I generate my table header:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
...
//NSString *tblHdr = [NSString stringWithFormat:#"%12s", #"voilà"];
NSString *tblHdr = [NSString stringWithFormat:#"%12s", [#"voilà" UTF8String]]; // Fixed example
...
return tblHdr;
}
[Update]
Here's the actual code from my project. I tried to keep it simple in my original example:
tblHdr = [NSString stringWithFormat:#"%-45s%12s%12s%35s",
[NSLocalizedString(#"Quiz Name", #"") UTF8String],
[NSLocalizedString(#"Correct", #"") UTF8String],
[NSLocalizedString(#"Missed", #"") UTF8String],
[NSLocalizedString(#"Score", #"") UTF8String]
];
It seems that the %s format expects a C string in the system encoding,
so this works
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding());
NSString *s = [NSString stringWithFormat:#"%12s", [#"voilá" cStringUsingEncoding:enc]];
(as long as the string can be represented in the system encoding).
Otherwise you can pad the string manually:
NSString *t = #"voilá";
if ([t length] < 12) {
t = [[#"" stringByPaddingToLength:(12 - [t length]) withString:#" " startingAtIndex:0] stringByAppendingString:t];
}
(or use #Daij-Djan's method, which was posted while I wrote this).
issue: %s formats a char* which is != NSString. so:
NSString *tblHdr = [NSString stringWithFormat:#"%12s", #"voilà".UTF8String];
This doesn't work as %s seems to not do multibyte right IMO!? Not sure
I'd stick with NSStrings... just add the spaces manually
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
//wrong
NSString *tblHdr = [NSString stringWithFormat:#"%12s", #"voilà".UTF8String];
NSLog(#"%#", tblHdr);
//ok
NSMutableString *rawTblHdr = #"voilà".mutableCopy;
while(12-rawTblHdr.length) {
[rawTblHdr insertString:#" " atIndex:0];
}
NSLog(#"%#", rawTblHdr);
}
}

NSData in base 10 [duplicate]

This question already has answers here:
Printing NSData using NSLog
(5 answers)
Closed 9 years ago.
Is it possible to NSLog NSData in base 10. Basically to see byte array of NSData.
I would like to see output something like this: [51, -55, 55, -54, -110]
You can define a category on NSData to produce a string with decimal data representation, like this:
#interface NSData (DecimalOutput)
-(NSString*)asDecimalString;
#end
#implementation NSData (DecimalOutput)
-(NSString*)asDecimalString {
NSMutableString *res = [NSMutableString string];
[res appendString:#"["];
// Construct an `NSString`, for example by appending decimal representations
// of individual bytes to the output string
const char *p = [self bytes];
NSUInteger len = [self length];
for (NSUInteger i = 0 ; i != len ; i++) {
[res appendFormat:#"%i ", p[i]];
}
[res appendString:#"]"];
return res;
}
#end
Now you can use this to NSLog strings in the new format:
NSLog("Data:%#", [myData asDecimalString]);

How to convert NData populated with hex values to NSString

I have a NSdata object that is populated with a bunch of information thats formated in hex.. I am trying to convert it into its proper string representation but am struggling to have any success.
One thing I have tried is to simply put it into a NSString and then NSLog it with a special character identifier thingy.. forgot the word (%02x), However to do this I am encoding it to NSUTF16.. which i dont want to do.. I mearly want to see exactly whats the data I am getting looks like as a NSString.
The reason I am doing this is because I am having some issues with my encoding later on in my code and im not sure if its because the data I am receiving is incorrect or me stuffing it up at some point when I am handling it.
Any help would be appreciated.
You can get a string representation of your NSData like so:
NSData *data = (your data)
NSString *string = [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
Does that answer your question?
Maybe I haven't understood, but something like this:
NSData *yourData;
NSLog(#"%#", [yourData description]);
doesn't fit your need?
Give this a try -
-(NSString*)hexToString:(NSData*)data{
NSString *hexString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
if (([hexString length] % 2) != 0)
return nil;
NSMutableString *string = [NSMutableString string];
for (NSInteger i = 0; i < [hexString length]; i += 2) {
NSString *hex = [hexString substringWithRange:NSMakeRange(i, 2)];
NSInteger decimalValue = 0;
sscanf([hex UTF8String], "%x", &decimalValue);
[string appendFormat:#"%d", decimalValue];
}
return string;
}

Resources