iOS NSMutableString returns weird character - ios

I make an array of several words, then I put all words into a mutable string, and then a mutable array of every character of this string. However, "wordSplitted" that is a mutable array of the characters give random scrambled characters at each startup of app in Simulator, showing in the log:
2012-07-22 09:12:01.108 xxx[4484:b603] wordSplitted contains: (
"",
"",
"\U221e",
"-",
G,
N,
P,
"",
""
)
It should be b, i, l, h, u, k, s, k, j.
NSArray *threeWords = [NSArray arrayWithObjects:#"bil", #"huk", #"skje", nil];
NSMutableString *allTogether = [[NSMutableString alloc]init];
/*
for (NSString *s in threeWords)
{
[allTogether appendString:s];
}
*/
for (int b = 0; b < [threeWords count]; b++)
{
[allTogether appendString:[threeWords objectAtIndex:b]];
}
NSLog (#"allTogether contains %#", allTogether);
//[threeWords release];
[allTogether release];
NSMutableArray *wordSplitted = [[NSMutableArray alloc]init];
//this function gives me headache
for (int a = 0; a < 9; a ++)
{
//gives also scrambled characters
//[wordSplitted addObject:[NSString stringWithFormat:#"%C",[allTogether characterAtIndex:a]]];
NSRange range = {a,1};
[wordSplitted addObject:[allTogether substringWithRange:range]];
}
NSLog (#"wordSplitted contains: %#", wordSplitted);
How can I display normal characters like alphabets?

You call [allTogether release] but then reference it later on. Normally this would cause your program to crash, but something about the CFMutableArray backing makes this not always happen.
Basically, don't release the array until you're sure you're done using it.

about string splitting
http://www.idev101.com/code/Objective-C/Strings/split.html

Related

How to get the desired dictionary result using mutable arrays in ios

I have three mutable array:
wkdatearray values like this: date from 2016-01-10 to 2016-01-16.
spentonarray values like this: 2016-01-10 to 2016-01-13.
hoursarray values like this: 7,3,4,5,1.
So, I compare the index objects of wkdatearray and spentarray like this:
for (int i = 0; i < self.wkDateArray.count; i++) {
for (int j = 0; j < self.spentonArray.count; j++) {
if ([
[self.wkDateArray objectAtIndex: i] isEqualToString: [self.spentonArray objectAtIndex: j]
]) {
NSLog(# "Matched Indexes %d %#", i, [self.wkDateArray objectAtIndex: i]);
} else {
}
}
Now I want to get the result like :
If the index value of self.wkdatearray and self.spentonarray are matched or equals then I have to set the hours array value as object for self.wkdatearray[0],[1]…[6]. like this in newsheet dictionary. Now I manually put string #"".
newSheet = [NSDictionarydictionaryWithObjectsAndKeys:strEntryID,entryID, proj,project,projID,projectId, strIssue,issue,strIssueID,issueId, strActivity,activity,strActivityId,activityId,#"",comment,#"",self.wkDateArray[0],#"",self.wkDateArray[1],#"",self.wkDateArray[2],#"",self.wkDateArray[3],#"",self.wkDateArray[4],#"",self.wkDateArray[5],#"",self.wkDateArray[6], nil];
If the index value of self.wkdatearray and self.spentonarray are not matched and not equals then the hours value like this #“‘ as object for self.wkdatearray[0].like this in newsheet dictionary. Now, I put by default object values as #""for self.wkdatearray[0...6].
Here the hours array having 5 values only.
How to do both the conditions inside the for loop? Or is there any other way to do this?
First of all make the newSheet dictionary mutable. You do not need 2 for loops.
int minIndexCount = MIN(self.wkdatearray.count, self. spentonArray.count)
we first take the min of wkdatearray.count and spentonArray.count since for example if there are only 2 items in spentonArray then if we try to use index 4 of wkdatearray then we do not have index 4 in spentonArray, meaning the primary condition that the indexes of both wkdatearray and spentonArray should be equal fails. Hence by taking min we ensure that we are only going to compare those indexes whixha re available in both wkdatearray and spentonArray.
for (int i = 0; i < minIndexCount; i++) {
if ([[self.wkDateArray objectAtIndex: i] isEqualToString: [self.spentonArray objectAtIndex: i]])
{
NSLog(# "Matched Indexes %d %#", i, [self.wkDateArray objectAt Index: i]);
[newSheet setValue:self.hoursarray[i] forKey:self.weekArray[i]]
} else {
}
}
If by "matched or equals" you mean that if the index's are the same AND the strings are matched.
for (int i = 0; i < self.wkDateArray.count; i++) {
for (int j = 0; j < self.spentonArray.count; j++) {
if (i==j && [
[self.wkDateArray objectAtIndex: i] isEqualToString: [self.spentonArray objectAtIndex: j]
]) {
NSLog(# "Matched Indexes %d %#", i, [self.wkDateArray objectAtIndex: i]);
} else {
}
}
Take note of the beginning of the if statement that has if (i==j && ...

How do I manipulate a copy of NSDictionary's contents without changing the contents of original

EDIT
The following "simpler" code works as expected. See the code below with explanation of my observations within comments.
- (void) changeDictValue
{
//If the method just uses the line below, then calling changeDictValue has no impact on self.bcastSeqNumList
NSMutableDictionary *seqListToUpdate = [NSMutableDictionary dictionaryWithDictionary:self.bcastSeqNumList] ;
//But if it instead uses the line below, calling changeDictValue does change self.bcastSeqNumList
NSMutableDictionary *seqListToUpdate = self.bcastSeqNumList ;
seqListToUpdate[#(lastContSeqType)]=#(0) ;
seqListToUpdate[#(maxRcvdSeqType)]=#(1) ;
seqListToUpdate[#(missingSeqType)]=nil ;
}
So, it looks like there is some bug in my code below (or some special Obj-C logic on how NSSets are handled during a calling on dictionaryWithDictionary:) that causes the NSSet associated with the missingSeqType key to be affected even though I am doing the manipulations on a new dictionary derived from self.bcastSeqNumList. Any clues?
END EDIT
I have a NSDictionary that represents sequence numbers.
1. One key (lastContSeqType) represents the largest sequence number X such that I have received all the sequence numbers <=X
2. One key (maxRcvdSeqType) represents the maximum sequence number I have received till now
3. One key (missingSeqType) represents a set of "missing sequence numbers"
I have one such dictionary for "broadcast messages" and one such dictionary for each unicast message with a far-end.
When I get a list of stored sequence numbers from the server, I use stored the sequence number list at my end and the received sequence number list to determine which sequence numbers to retrieve.
When I execute following lines of code,
In The first implementation of getMissingSequenceNumsFromServer:(NSDictionary *) dict, things are working as expected, the bcastSeqNumList is getting updated, lastContSeqType is updated to 4 and missingSeqType is empty.
In the second implementation, where I create a new dictionary from the contents of self.bcastSeqNumList and then manipulate this "copied" Dictionary, I don't expect self.bcastSeqNumList to be affected by any of the manipulations inside the method. I am seeing that lastContSeqType key is unaffected, but the missingSeqType key is affected and becomes an empty list (i.e the NSNumber object #(4) is being removed). Why is this happening?
self.bcastSeqNumList= [#{#(lastContSeqType) : #(1), #(maxRcvdSeqType) : #(6), #(missingSeqType) : [NSMutableSet setWithObject:#(4)]
} mutableCopy];
NSLog(#"Bcast seq num list = %#",self.bcastSeqNumList) ;
NSMutableDictionary *rcvdDict= [#{#"currBroadcastSeqNumStart" : #(5), #"currBroadcastSeqNumEnd" : #(6)
} mutableCopy];
[self getMissingSequenceNumsFromServer:rcvdDict] ;
NSLog(#"Bcast seq num list = %#",self.bcastSeqNumList) ;
Case 1 Implementation
- (void) getMissingSequenceNumsFromServer:(NSDictionary *) dict
{
NSInteger serverStoreSeqStart=[dict[#"currBroadcastSeqNumStart"] integerValue] ;
NSInteger serverStoreSeqEnd=[dict[#"currBroadcastSeqNumEnd"] integerValue] ;
NSMutableDictionary *seqListToUpdate = self.bcastSeqNumList ;
NSInteger mySeq = [seqListToUpdate[#(lastContSeqType)] integerValue] ;
if(mySeq < serverStoreSeqStart-1)
{
//Ask for all stored messages in server
//[self getMessagesfromStart:serverStoreSeqStart toEnd:serverStoreSeqEnd] ;
NSLog(#"Getting messages from %ld and to %ld",serverStoreSeqStart,serverStoreSeqEnd) ;
NSLog(#"Never received seq nums %ld to %ld",mySeq+1,serverStoreSeqStart-1) ;
NSInteger nextSeqToRemove ;
for(nextSeqToRemove=mySeq+1;nextSeqToRemove<=serverStoreSeqStart-1;nextSeqToRemove++)
{
if([seqListToUpdate objectForKey:#(missingSeqType)])
{
if([seqListToUpdate[#(missingSeqType)] containsObject:[NSNumber numberWithInteger:nextSeqToRemove]])
{
NSLog(#"SeqNum %ld is in missing seq num list and being removed since we got server seq %ld > than this",(long)nextSeqToRemove,(long)serverStoreSeqStart) ;
//Remove it
[seqListToUpdate[#(missingSeqType)] removeObject:#(nextSeqToRemove)] ;//
//If set is empty
if([seqListToUpdate[#(missingSeqType)] count] ==0)
{
//Nothing left in missing seq table. set it to nil and return
[seqListToUpdate removeObjectForKey:#(missingSeqType)] ;
seqListToUpdate[#(lastContSeqType)]=seqListToUpdate[#(maxRcvdSeqType)] ;
NSLog(#"Missing seq num list empty. Setting last contig to max = %#",seqListToUpdate[#(lastContSeqType)]) ;
break ;
}
}
}
else
{
//mising Seq Type has no elements, nothing to remove
break ;
}
}
//At the end..if serverSeqToStore >= maxSeq, then lastCOnt=maxSeq and missing seq empty.
//Else...if missing seq Empty, then
seqListToUpdate[#(lastContSeqType)] = [NSNumber numberWithInteger:serverStoreSeqStart-1] ;
if(seqListToUpdate[#(maxRcvdSeqType)] <= seqListToUpdate[#(lastContSeqType)])
{
seqListToUpdate[#(maxRcvdSeqType)] = seqListToUpdate[#(lastContSeqType)] ;
//Set to misisng seq num list = nil
}
else
{
//remove seqnums
}
}
else if (mySeq < serverStoreSeqEnd)
{
//[self getMessagesfromStart:mySeq+1 toEnd:serverStoreSeqEnd] ;
NSLog(#"Getting messages from %ld and to %ld",mySeq+1,serverStoreSeqEnd) ;
}
else if (mySeq > serverStoreSeqEnd)
{
NSLog(#"My stored sequence number %ld exceeds the max stored at server %ld",(long)mySeq,(long)serverStoreSeqEnd) ;
}
}
Case 2 Implementation
The following line
seqListToUpdate = self.bcastSeqNumList ;
is replaced by the line below so that any changes to seqListToUpdate should not affect the contents of self.bcastSeqNumList
seqListToUpdate = [NSMutableDictionary dictionaryWithDictionary:self.bcastSeqNumList] ;
You have to make a deep copy. At the moment, you're just copying the references to the same objects. You also have to copy the objects, that are referenced in the dictionary.
The easiest way of doing a deep copy is using NSKeyedArchiver to archive and unarchive.
NSDictionary* deepCopy = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject:originalDict]];

Will this unicode encryption fail?

I'm not needing any serious security, I just need to stop 11 year olds with plist editors from editing their number of coins in my game with ease.
I created a function that takes a string, for each unicode value of a character it raises this unicode value by 220 plus 14 times the character number that it is in the string.
Obviously this will fail (I think) if the string was like a million characters long because eventually you run out of unicode characters, but for all intents and purposes, this will only be used on strings of 20 characters and less.
Are there any unicode characters in this range that will not be stored to a plist or will be ignored by Apple's underlying code when I save the plist so that when I retrieve it and decrypt the character will be gone and I can't decrypt it?
+(NSString*)encryptString:(NSString*)theString {
NSMutableString *encryptedFinal = [[NSMutableString alloc] init];
for (int i = 0; i < theString.length; i++) {
unichar uniCharacter = [theString characterAtIndex:i];
uniCharacter += +220+(14*i);
[encryptedFinal appendFormat:#"%C", uniCharacter];
}
return encryptedFinal;
}
+(NSString*)decryptString:(NSString*)theString {
NSMutableString *decryptedFinal = [[NSMutableString alloc] init];
for (int i = 0; i < theString.length; i++) {
unichar uniCharacter = [theString characterAtIndex:i];
uniCharacter += +220+(14*i);
[decryptedFinal appendFormat:#"%C", uniCharacter];
}
return decryptedFinal;
}
It works for a range of a string of length 20 characters or less if you are encrypting one of the first 26+26+10+30 characters in the unicode index at any given point along the 20 character line. It probably works higher, I just didn't test it any higher.
This is the code I created to test it, all unicode characters were stored in an NSString and stayed valid for counting later.
int i = 0;
NSMutableString *encryptedFinal = [[NSMutableString alloc] init];
NSString *theString = #"a";
int j = 26+26+10+30;//letters + capital letters + numbers + 30 extra things like ?><.\]!#$
int f = 0;
int z = 0;
while (f < j) {
while (i < 220+220+(14*20)) {
unichar uniCharacter = [theString characterAtIndex:0];
uniCharacter += +f;
uniCharacter += +220+(14*i);
[encryptedFinal appendFormat:#"%C", uniCharacter];
i++;
}
z += i;
f++;
i = 0;
}
NSLog(#"%#", encryptedFinal);
NSLog(#"%i == %i?", z, encryptedFinal.length);
There are two thing that you can do:
Save the number of coins using NSData rather than using
NSNumber. Then use
NSData+AES
to encrypt it. You can even encrypt your entire .plist file to
ensure that no other fields are changed.
Security through obscurity. Just save the number of coins as an important sounding field. e.g.:Security Token Number. You can also create a bogus number of coins field whose value is ignored. Or maybe save the same value in both the fields and flag the user for cheating if the two values don't match.

Compare and get the Index from NSMutableArray

I have an array, which is a collection of arrays.
say
(
( 1, x, y, a),
( 2, m, n, o),
( 3, s, t, u, v, w)
)
If I want to get the index of m, how do I get it?
Can that be done using NSMutableArray contains:(id) ?
Check with this code:
int arrayPos = 0;
for (NSArray *tempArray in collectionArray)
{
if(tempArray containsObject:#"m")
{
int indexOfWord = [tempArray indexOfObject:#"m"];
NSlog(#"Array pos: %d Index is : %d",pos, indexOfWord);
}
pos++;
}
In the for loop you get each array that is added in the collection array. After that you are checking the existence of the word in the array. If it is present you are displaying it.
Also printing the position of array also.
The element is situated at:
NSString *str = [[collectionArrayObjectAtIndex:pos] objectAtIndex:indexOfWord];
NSArray *arrWithArr;
NSArray *arrWithM;
NSInteger arrIndex;
for (int i = 0; i< [arrWithArr count]; i++) {
if ([[arrWithArr objectAtIndex:i] containsObject:#"m"]) {
arrIndex = i; break;
}
}
NSInteger mIndex = [[arrWithArr objectAtIndex:arrIndex]indexOfObject:#"m"];
The function you're talking about, "[NSMutableArray contains:]" will tell you if object "B" exists in an array of {A, B, C}.
What you really need to do is come up a second function that does a fast enumeration through your parent array and then does the "contains" thing on the sub-arrays. If it finds "m", return "YES" and the index of that entry in the parent array.

Objective C parsing hiccup

Please bear with me. I am new to C altogether, let alone Objective C. I am trying to do something that should be simple however its not working. I am scanning a string of numbers that also contains symbols. As the mini function runs through the input string it appends numbers to a new string until it comes across an operator (I'm writing a calculator in my own way as a learning exercise.) Right now I am just doing the beginning part and scanning the string and appending character. Here is my code:
char userInput[99];
NSMutableString *number = nil;
int i;
printf( "Please enter math: " );
scanf( "%s", userInput );
fpurge( stdin );
NSString *InputString = [NSString stringWithUTF8String:userInput];
for (i=0; i < [InputString length]; i++) {
char current = [InputString characterAtIndex:i];
if (isalnum(current)) {
[number appendString:[NSString stringWithCharacters:&current length:1]];
NSLog(#"%# ", number);
}
}
For the life of me I can not seem to figure out why it keeps printing 2012-05-02 19:23:20.935 CALC[1447:403] (null) instead of the number value for each number it comes across. So for example if there are 5 numbers in the entered string it will print that 5 times.
You never initialized number--so when you call -appendString: on it, you're only appending to nil, and the result is just nil back. Try this for your second line:
NSMutableString *number = [NSMutableString string];
Now number is an empty string object, which is very different from being nil, which is no object at all.

Resources