I'd like to encrypt an NSString so that it isn't human-readable. The level of security doesnt manner (in other words, if somebody were to decrypt the text there wouldn't be any sensitive information for them to steal.
NSString *myTextToEncrypt = #"Hello World!";
[myTextToEncrypt encrypt];
// myTextToEncrypt is now something unreadable, like '2rwzdn1405'
Then I should be able to unencrypt this string
[myTextToEncrypt unencrypt]; // myTextToEncrypt should now be #"Hello World!" again
How do I do this? I've read some about CommonCrypto and AES Encryption but this all seems like overkill for what I'm trying to do (the encryption methods I've read are all for passwords or other sensitive pieces of data)
Simplest one is use your own encryption, e.g.
Utils.h
#interface Utils : NSObject
+(NSString*)encyptString:(NSString*)str;
+(NSString*)decryptString:(NSString*)str;
#end
Utils.m
#import "Utils.h"
int offset = 15;
#implementation Utils
+(NSString*)encyptString:(NSString*)str
{
NSMutableString *encrptedString = [[NSMutableString alloc] init];
for (int i = 0; i < str.length; i++) {
unichar character = [str characterAtIndex:i];
character += offset;
[encrptedString appendFormat:#"%C",character];
}
return encrptedString;
}
+(NSString*)decryptString:(NSString*)str
{
NSMutableString *decrptedString = [[NSMutableString alloc] init];
for (int i = 0; i < str.length; i++) {
unichar character = [str characterAtIndex:i];
character -= offset;
[decrptedString appendFormat:#"%C",character];
}
return decrptedString;
}
#end
How to use it
NSString *str = #"hello world";
NSString *enr = [Utils encyptString:str];
NSLog(#"Encrypted Text=%#", enr);
NSLog(#"Decrypted Text=%#", [Utils decryptString:enr]);
Logs
2013-08-11 10:44:09.409 DeviceTest[445:c07] Encrypted Text=wt{{~/~{s
2013-08-11 10:44:09.412 DeviceTest[445:c07] Decrypted Text=hello world
You can use base64 to do this.
There are some implementations in Objective-C available (as this one).
Note that the content will be about 30% bigger after it's encoded.
Related
I have a NSString with hex string like "&# x62a;&# x631;&# x642;&# x628;" which means "ترقب".
Now I want to convert the hex string into another NSString object which shows "ترقب". How to do that ?
- (NSMutableString *) hextostring:(NSString *) str{
//ت
NSMutableString *string = [[NSMutableString alloc]init];
str = [str stringByReplacingOccurrencesOfString:#"&#" withString:#"0"];
str = [str stringByReplacingOccurrencesOfString:#" " withString:#"z;"];
NSArray *arr = [str componentsSeparatedByString:#";"];
for (int i =0; i<[arr count]; i++) {
if ([[arr objectAtIndex:i] isEqualToString:#"z"]) {
[string appendString:#" "];
} else {
unsigned x;
[[NSScanner scannerWithString: [arr objectAtIndex:i]] scanHexInt: &x];
[string appendFormat:#"%C",(unichar)x];
}
}
NSLog(#"%#",string);
return string;
}
Your string looks like HTML escape sequences, except for the spaces after the #'s. If this is really what you have (check something isn't just displaying Unicode as escapes) then there is a myriad of ways to convert it. You can just process the string picking out the hex chars and producing UniChar values from them, etc.
If you want a high-level, maybe somewhat long-winded approach, you and try:
- (NSString *)decodeHTMLescapes:(NSString *)raw
{
NSString *nospaces = [raw stringByReplacingOccurrencesOfString:#" " withString:#""]; // one way to remove the spaces
const char *cString = [nospaces UTF8String]; // C string
NSData *bytes = [[NSData alloc] initWithBytesNoCopy:(void *)cString length:strlen(cString) freeWhenDone:NO]; // as bytes
NSAttributedString *attributed = [[NSAttributedString alloc] initWithHTML:bytes documentAttributes:nil]; // interpret as HTML
NSString *decoded = attributed.string; // and finally as plain text
return decoded;
}
That (a) strips the spaces, (b) creates a C string and (c) creates a byte buffer, all that so we can (d) interpret that byte buffer as HTML, and (e) finally gets the string back. The use of initWithBytesNoCopy:length:freeWhenDone: is to reduce the copying all this does.
Use it like:
NSString *raw = #"&# x62a;&# x631;&# x642;&# x628;";
NSString *decoded = [self decodeHTMLescapes:raw];
NSLog(#"%# -> %#", raw, decoded);
HTH
split the sentence into words with out using "componentsSeparatedByString:"
my word is "This is a well known simple"
I wrote like this separtedWord=[noteTextView.text componentsSeparatedByString: #" "];
but I want with out using componentsSeparatedByString.please help me
I have wrote following logic. Created two properties like this :
#property(nonatomic,strong) NSMutableArray *strings;
#property(nonatomic,strong) NSMutableString *tempString;
Wrote business logic like this :
NSString *sampleString = #"This is a well known simple";
self.tempString = [[NSMutableString alloc] init];
self.strings = [[NSMutableArray alloc] init];
for( int i = 0; i < sampleString.length; i++ )
{
unichar currentChar = [sampleString characterAtIndex:i];
NSString *character = [NSString stringWithCharacters:¤tChar length:1];
if( currentChar != ' ' )
{
[self.tempString appendString:character];
if( i == sampleString.length - 1 )
{
[self addString:self.tempString];
}
}
else
{
[self addString:self.tempString];
[self.tempString setString:#""];
}
}
NSLog(#"Array Of String = %#",self.strings);
- (void)addString:(NSString *)string
{
[self.strings addObject:[NSString stringWithString:string]];
}
2014-07-24 15:23:22.306 ViemoPlayer[1834:70b] Array Of String = (
This,
is,
a,
well,
known,
simple
)
Hope this helps.
Convert the NSString into a char array.
Loop through the array and an if statement inside, and keep appending the charecters inside the charArray into a local NSMutableString using
for(int i =0;i<[myCharArray count];i++){
NSMutableString *teststring;
[teststring appendString:[myCharArray objectAtIndex : i]];
if([myCharArray objectAtIndex] == " "){
NSLog(teststring);
teststring = #""; //emptying the testString when we get a space
}
}
That should do it
I am creating a word scrambler and I am having issues randomizing the letters. When the letters get randomized, it doesn't make sense.
For example, the word PARK shows as AAPA. So, as you can tell it won't make sense for the user when it is time to unscramble.
Just so you know, I am using a .plist file to hold the words.
This is the code I am using to randomize the letters:
_words = [NSMutableArray arrayWithCapacity:scramblelength];
for (int i=0;i<scramblelength;i++) {
NSString *letter = [scramble substringWithRange:[scramble rangeOfComposedCharacterSequenceAtIndex:arc4random()%[scramble length]]];
Then, I am creating UIImageViews to display the scrambled words:
if (![letter isEqualToString:#""]) {
GameView *boxes = [[GameView alloc] initWithLetter:letter andSideLength:boxSide];
boxes.center = CGPointMake(xOffset + i*(boxSide + kTileMargin), kScreenHeight/4*3);
[self.scrambleView addSubview:boxes];
[_words addObject:boxes];
What am I doing wrong here? I would like for the letters in the scrambled words to make sense.
Please help, I am stuck on this one!
Thanks!
As long as your string length will fit in 32 bits, this should be fine. If not, I would replace arc4random_uniform with a uniform random number generator in C++ and compile this as an Objective-C++ module.
The code simply iterates through the string, and swaps each composed character sequence with some random composed character sequence from the same string.
Sorry, that's what happens when you are arrogant and just type out code. Let me know if you have trouble with this one...
For much larger strings, there is a more efficient way, but this seems to do the trick.
NSMutableString category...
#interface NSMutableString (Scramble)
- (void)scramble;
#end
#implementation NSMutableString (Scramble)
static void
swapRanges(NSMutableString *string, NSRange iRange, NSRange jRange)
{
// Need to replace the "trailing" component first
if (NSEqualRanges(iRange, jRange)) return;
if (iRange.location > jRange.location) {
NSRange tmpRange = iRange;
iRange = jRange;
jRange = tmpRange;
}
NSString *iString = [self substringWithRange:iRange];
NSString *jString = [self substringWithRange:jRange];
[string replaceCharactersInRange:jRange withString:iString];
[string replaceCharactersInRange:iRange withString:jString];
}
- (void)scramble
{
for (NSUInteger i = 0; i < self.length; ++i) {
NSRange iRange = [self rangeOfComposedCharacterSequenceAtIndex:i];
NSUInteger j = arc4random_uniform(self.length);
NSRange jRange = [self rangeOfComposedCharacterSequenceAtIndex:j];
swapRanges(self, iRange, jRange);
}
}
#end
NSString category...
#interface NSString (Scramble)
- (NSString*)scrambledString;
#end
#implementation NSString (Scramble)
- (NSString *)scrambledString
{
NSMutableString *result = [self mutableCopy];
[result scramble];
return [result copy];
}
#end
Sample use...
[someMutableString scramble];
NSString *mixedUp = [someString scrambledString];
Or, if you are comfortable with C++, convert to a std::wstring, call std::random_shuffle, then convert that to a NSString. Lots less bugs when using proven, well tested code.
When you are getting a random letter, you need to do something to remove that letter from your NSMutableArray (ie the word's letters when in order). So as you iterate through the word, each time there are fewer characters remaining. Right now, from your limited code block (the first one), it appears you might not be doing that. You want something like "[_words removeObjectAtIndex:letterIndex]" and you would also want to iterate from number of letters down to zero as you remove items from the array also: for (int i=[_words count]; i > [_words count]; i--) because you need to go from 4 letters down to 0 letters left.
So, I'm sure there are more efficient ways to do this, but I go by the rule of not optimizing until you need to. With that in mind, this code appears to work correctly:
- (NSString *)scrambleWord:(NSString *)word {
NSMutableArray *letterArray = [self letterArrayFromWord:word];
NSMutableString *returnValue = [[NSMutableString alloc] init];
do {
int randomIndex = arc4random() % letterArray.count;
[returnValue appendString:letterArray[randomIndex]];
[letterArray removeObjectAtIndex:randomIndex];
if (letterArray.count == 1) {
[returnValue appendString:letterArray[0]];
break;
}
} while (YES);
if ([[returnValue copy] isEqualToString:word]) {
return [self scrambleWord:word];
} else {
return [returnValue copy];
}
}
- (NSMutableArray *)letterArrayFromWord:(NSString *)word {
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < word.length; i = i + 1) {
[array addObject:[NSString stringWithFormat:#"%C", [word characterAtIndex:i]]];
}
return array;
}
I would like to create a string based on the number of characters passed in. Each character passed in will be a "X". So for example, if the length passed in is 5, then the string created should be
NSString *testString=#"XXXXX";
if it is 2 then it would be
NSString *testString=#"XX";
Can anyone tell me what the most efficient way to do this would be?
Thank you!
If you know the maximum length is some reasonable number then you could do something simple like this:
- (NSString *)xString:(NSUInteger)length {
static NSString *xs = #"XXXXXXXXXXXXXXXXXXXXXXXXXXX";
return [xs substringToIndex:length];
}
NSString *str = [self xString:5]; // str will be #"XXXXX";
If you pass in too large of a length, the app will crash - add more Xs to xs.
This approach is more efficient than building up an NSMutableString but it does make an assumption about the maximum length you might need.
- (NSString *)stringOf:(NSString *)str times:(NSInteger)count
{
NSMutableString *targ = [[NSMutableString alloc] initWithCapacity:count];
for (int i=0; i < count; i++)
{
[targ appendString:str];
}
return targ;
}
and
[self stringOf:#"X" times:4];
note that initWithCapacity: (in performance manner) better than init. But I guess that's all for efficiency.
The way I would do it is
NSMutableString *xString = [[NSMutableString alloc] init];
while ( int i = 0; i < testString.length; i++ ) {
[xString appendString:#"X"];
i++;
}
NSUInteger aLength. // assume this is the argument
NSMutableString *xStr = [NSMutableString stringWithCapacity: aLength];
for ( NSUInteger i = 0; i < aLength; i++ ) {
[xStr appendFormat:#"X"];
}
The following will do what you ask in one call:
NSString *result = [#"" stringByPaddingToLength:numberOfCharsWanted
withString:characterToRepeat
startingAtIndex:0];
where numberOfCharsWanted is an NSUInteger and characterToRepeat is an NSString containing the character.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing code which should reverse a string. When I run the following code it throws an error:
- (NSString*) reversingName:(NSString *)myNameText
{
NSString *result;
int len = [myNameText length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len;i>0;i--)
{
[reverseName appendFormat:[NSString stringWithFormat:#"%c",[myNameText characterAtIndex:i]]];
}
result = reverseName;
return result;
}
The for loop line should be as follows:
for(int i=len-1;i>=0;i--)
So your method should be
- (NSString*) reversingName:(NSString *)myNameText
{
int len = [myNameText length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len-1;i>=0;i--)
{
[reverseName appendString:[NSString stringWithFormat:#"%c",[myNameText characterAtIndex:i]]];
}
return [reverseName autorelease];
}
I thought I'd throw another version out there in case anyone's interested.. personally, I like the cleaner approach using NSMutableString but if performance is the highest priority this one is faster:
- (NSString *)reverseString:(NSString *)input {
NSUInteger len = [input length];
unichar *buffer = malloc(len * sizeof(unichar));
if (buffer == nil) return nil; // error!
[input getCharacters:buffer];
// reverse string; only need to loop through first half
for (NSUInteger stPos=0, endPos=len-1; stPos < len/2; stPos++, endPos--) {
unichar temp = buffer[stPos];
buffer[stPos] = buffer[endPos];
buffer[endPos] = temp;
}
return [[NSString alloc] initWithCharactersNoCopy:buffer length:len freeWhenDone:YES];
}
I also wrote a quick test as well to compare this with the more traditional NSMutableString method (which I also included below):
// test reversing a really large string
NSMutableString *string = [NSMutableString new];
for (int i = 0; i < 10000000; i++) {
int digit = i % 10;
[string appendFormat:#"%d", digit];
}
NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970];
NSString *reverse = [self reverseString:string];
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSince1970] - startTime;
NSLog(#"reversed in %f secs", elapsedTime);
Results were:
using NSMutableString method (below) - "reversed in 3.720631 secs"
using unichar *buffer method (above) - "reversed in 0.032604 secs"
Just for reference, here's the NSMutableString method used for this comparison:
- (NSString *)reverseString:(NSString *)input {
NSUInteger len = [input length];
NSMutableString *result = [[NSMutableString alloc] initWithCapacity:len];
for (int i = len - 1; i >= 0; i--) {
[result appendFormat:#"%c", [input characterAtIndex:i]];
}
return result;
}
(NOTE: I don't have enough reputation points yet to vote or comment on answers so I'd appreciate if anyone could vote on this answer for me. I've been a long time reader but now want to start contributing more!)
try this sample code :
NSString *name = #"abcdefghi" ;
int len = [name length];
NSMutableString *reverseName = [[NSMutableString alloc] initWithCapacity:len];
for(int i=len-1;i>=0;i--)
{
[reverseName appendFormat:[NSString stringWithFormat:#"%c",[name characterAtIndex:i]]];
}
NSLog(#"%#",reverseName);
Reverse a String in Swift 2.0:
let string = "This is a test string."
let characters = string.characters
let reversedCharacters = characters.reverse()
let reversedString = String(reversedCharacters)
The short way :
String("This is a test string.".characters.reverse())
OR
let string = "This is a test string."
let array = Array(string)
let reversedArray = array.reverse()
let reversedString = String(reversedArray)
The short way :
String(Array("This is a test string.").reverse())