Encoding issue: An NSString into a key of an NSDictionary - objective-c

So I'm taking a data file and encoding it into a string:
///////////////////////////////
// Get the string
NSString* dataString = [[NSString alloc] initWithData:data
encoding:encoding];
NSLog(#"dataString = %#",dataString);
The file was a list of French words and they NSLog fine, showing appropriate accents (just one example):
abandonnèrent
Now, in the very next part of the code I take this NSString of the file contents and convert it to a dictionary where the words are the keys and the objects are two additional dictionaries:
///////////////////////////////
// Now parse the file (string)
NSMutableDictionary *mutableWordlist = [[NSMutableDictionary alloc] init];
int i = 0;
for (NSString *line in [dataString componentsSeparatedByString:#"\n"]) {
NSArray *words = [line componentsSeparatedByString:#"\t"];
NSNumber *count = [NSNumber numberWithInt:(i+1)];
NSArray *keyArray;
NSArray *objectArray;
if ([words count] < 2) { // No native word
keyArray = [[NSArray alloc] initWithObjects:#"frequency", nil];
objectArray = [[NSArray alloc] initWithObjects:count, nil];
}
else {
keyArray = [[NSArray alloc] initWithObjects:#"frequency", #"native", nil];
objectArray = [[NSArray alloc] initWithObjects:count, [words[1] lowercaseString], nil];
}
NSDictionary *detailsDict = [[NSDictionary alloc] initWithObjects:objectArray forKeys:keyArray];
[mutableWordlist setObject:detailsDict forKey:[words[0] lowercaseString]];
i++;
}
self.wordlist = mutableWordlist;
NSLog(#"self.wordlist = %#", self.wordlist);
But here the keys have encoding issues and log as so if they have an accent:
"abandonn\U00e8rent
" = {
frequency = 24220;
};
What is happening?

Nothing (wrong) is happening.
When you NSLog an NSString it is being output as Unicode text. However when you NSLog the NSDictionary they keys are being output with unicode escape sequences, \U00e8 is the escape code you can use in a string if you cannot type an è - say because your source file is in ASCII.
So the difference is only in how the string is being printed, the string is not different.
HTH

Related

Reading from SQL database into NSArray

I have an iPad that reads data from an SQL database. The following code works fine and retrieves 2 fields from each record and reads them into an NSArray.
I now need to read 5 of the fields and I can't help but think that there is a better way of doing it rather than running 5 separate queries through php (the getinfo.php file with the choice parameter set to pick the different fields).
Any pointers to a better method for doing this?
NSString *strURLClass = [NSString stringWithFormat:#"%#%#", #"http://wwwaddress/getinfo.php?choice=1&schoolname=",obsSchoolName];
NSArray *observationsArrayClass = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURLClass]];
observationListFromSQL = [[NSMutableArray alloc]init];
NSEnumerator *enumForObsClass = [observationsArrayClass objectEnumerator];
NSString *strURLDate = [NSString stringWithFormat:#"%#%#", #"http://wwwaddress/getinfo.php?choice=5&schoolname=",obsSchoolName];
NSArray *observationsArrayDate = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURLDate]];
observationListFromSQL = [[NSMutableArray alloc]init];
NSEnumerator *enumForObsDate = [observationsArrayDate objectEnumerator];
id className, dateOfObs;
while (className = [enumForObsClass nextObject])
{
dateOfObs = [enumForObsDate nextObject];
[observationListFromSQL addObject:[NSDictionary dictionaryWithObjectsAndKeys:className, #"obsClass", dateOfObs, #"obsDate",nil]];
}
Yes, you can do that with less code by "folding" the statements into a loop, and using a mutable dictionary:
// Add other items that you wish to retrieve to the two arrays below:
NSArray *keys = #[#"obsClass", #"obsDate"]; // Key in the dictionary
NSArray *choices = #[#1, #5]; // Choice in the URL string
NSMutableArray *res = [NSMutableArray array];
NSMutableArray *observationListFromSQL = [NSMutableArray array];
for (int i = 0 ; i != keys.count ; i++) {
NSNumber *choice = choices[i];
NSString *strURLClass = [NSString stringWithFormat:#"http://wwwaddress/getinfo.php?choice=%#&schoolname=%#", choice, obsSchoolName];
NSArray *observationsArray = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURLClass]];
NSEnumerator *objEnum = [observationsArrayClass objectEnumerator];
NSString *key = keys[i];
NSMutableDictionary *dict;
if (res.count < i) {
dict = res[i];
} else {
dict = [NSMutableDictionary dictionary];
[res addObject:dict];
}
id item;
while (item = [objEnum nextObject]) {
[res setObject:item forKey:key];
}
}

How to create an NSarray with NSAttributedStrings but keeping the attributes within the array?

I want to store different strings with different attributes and store all of them in one array and then display the objects in one label but each object with its respective attribute.
Any suggestions?
EDIT: Solution derived from rmaddy's answer
NSDictionary *redAttrs = #{NSForegroundColorAttributeName:[UIColor redColor]};
NSDictionary *greenAttrs = #{NSForegroundColorAttributeName:[UIColor colorWithRed:0.118 green:0.506 blue:0.000 alpha:1.000]};
NSDictionary *orangeAttrs = #{NSForegroundColorAttributeName:[UIColor orangeColor]};
NSString *stringUm = #"Brazil";
NSString *stringDois = #"USA";
NSString *stringTres = #"England";
NSMutableAttributedString *redString = [[NSMutableAttributedString alloc] initWithString:stringUm];
[redString setAttributes:redAttrs range:NSMakeRange(0,4)];
NSMutableAttributedString *greenString = [[NSMutableAttributedString alloc] initWithString:stringDois];
[greenString setAttributes:greenAttrs range:NSMakeRange(0,2)];
NSMutableAttributedString *orangeString = [[NSMutableAttributedString alloc] initWithString:stringTres];
[orangeString setAttributes:orangeAttrs range:NSMakeRange(0,4)];
NSArray *myStrings = [[NSArray alloc] initWithObjects:redString, greenString, orangeString, nil];
NSLog(#"%#", [myStrings description]);
NSMutableAttributedString *result = [[NSMutableAttributedString alloc]init];
NSAttributedString *delimiter = [[NSAttributedString alloc] initWithString: #", "];
for (NSAttributedString *str in myStrings) {
if (result.length) {
[result appendAttributedString:delimiter];
}
[result appendAttributedString:str];
}
_lblUm.attributedText = result;
Your question is very unclear. But based on your comment to gerrytan's answer, your goal is clearer.
If you have an array of NSAttributedString objects, then you can create a single string by appending them all together with an NSMutableAttributedString.
NSArray *myStrings = ... // your array of NSAttributedString objects
NSMutableAttributedString *result = [[NSMutableAttributedString alloc] init];
// Put this delimiter between each string - change as desired
NSAttributedString *delimiter = [[NSAttributedString alloc] initWithString:#", "];
for (NSAttributeString *str in myStrings) {
if (result.length) {
[result appendAttributedString:delimiter];
}
[result appendAttributedString:str];
}
myLabel.attributedText = result;
UILabel only supports one NSAttributedString. I think what you can do is to place multiple UILabel side by side for each string on the array

Extracting number from NSString

I have an NSString which when logged gives me an answer like this one:
Response: oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z
The two numbers change every single time.
Is there a way to extract the two numbers and create two strings with one of each??
Like:
NSString *key = #"9tmqsojggieln6z";
//copy the string in a new string variable
NSMutableString *auth_token = [NSMutableString stringWithString:response];
NSRange match = [auth_token rangeOfString: #"&oauth_token="];
[auth_token deleteCharactersInRange: NSMakeRange(0, match.location+13)];
//auth_token will now have the auth token string
NSMutableString *auth_token_secret = [NSMutableString stringWithString:response];
NSRange range1 = [auth_token_secret rangeOfString:[NSString stringWithFormat:#"&oauth_token=%#", auth_token]];
[auth_token_secret deleteCharactersInRange:range1];
NSRange range2 = [auth_token_secret rangeOfString:#"oauth_token_secret="];
[auth_token_secret deleteCharactersInRange: range2];
//auth_token_secret will have the required secret string.
I had the same problem. As response I get the ids of objects sometimes as string sometimes as numbers. Then I wrote a category for NSDictionary which has the following method:
- (NSString *)stringFromStringOrNumberForKey:(NSString *)key
{
id secret = [self objectForKey:key];
if ([secret isKindOfClass:[NSNumber class]]) {
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
secret = [numberFormatter stringFromNumber:secret];
}
return secret;
}
I would try the following:
NSString *_response = #"oauth_token_secret=6h8hblp42jfowfy&oauth_token=9tmqsojggieln6z";
NSMutableDictionary *_dictionary = [[NSMutableDictionary alloc] init];
NSArray *_parameters = [_response componentsSeparatedByString:#"&"];
for (NSString *_oneParameter in _parameters) {
NSArray *_keyAndValue = [_oneParameter componentsSeparatedByString:#"="];
[_dictionary setValue:[_keyAndValue lastObject] forKey:[_keyAndValue objectAtIndex:0]];
}
// reading the values
NSLog(#"token_secret : %#", [_dictionary valueForKey:#"oauth_token_secret"]);
NSLog(#"token : %#", [_dictionary valueForKey:#"oauth_token"]);

opencv ios cvseq storage

I am intending to pre-load all the images that I have stored inside application. Pre-loading of images involves:
Read images from bundle.
Extract object descriptors using cvExtractSurf from opencv framework.
Store IPLImage with corresponding object descriptors and keypoints.
I am having an issue in creating a dictionary containing CvSeq* keys and CvSeq* descs.
Please suggest how to store these values in NSMutableDictionary.
-(void) preloadImages:(NSMutableDictionary *)dictionary{
NSArray *d = [[NSBundle mainBundle] pathsForResourcesOfType:#"png" inDirectory:nil];
CvSURFParams params = cvSURFParams(500, 1);
CvMemStorage* storage = cvCreateMemStorage(0);
for( int i=0;i<[d count];i++){
NSString *searchForMe = #"myapp.app/1";
NSString *s = [[NSString alloc] initWithString:[d objectAtIndex:i]];
NSRange range = [s rangeOfString:searchForMe];
if( range.location != NSNotFound ){
NSMutableDictionary *surfDict = [[NSMutableDictionary alloc] init];
NSString *substring = [s substringFromIndex:range.location];
substring = [substring stringByReplacingOccurrencesOfString:#"myapp.app/" withString:#""];
UIImage *testImage = [UIImage imageNamed:substring];
IplImage *iplTestImage = [OpenCVUtilities CreateGRAYIplImageFromUIImage:testImage];
CvSeq *keys = 0 ;
CvSeq *descs = 0;
cvExtractSURF( iplTestImage, 0, &keys, &descs, storage, params );
[surfDict setObject:(id)testImage forKey:#"uiImage"];
NSLog(#"Image name : %#", substring);
[dictionary setObject:surfDict forKey:[NSString stringWithFormat:#"%d",i]];
[dictionary setObject:(NSObject *)keys forKey:#"keys"]; // error here
[dictionary setObject:(NSObject *)descs forKey:#"descs"]; // error here
[surfDict release];
}
}
}
Create a class that has an instance variable of type cvseq, add your cvseq to the object, and add that class to the dictionary.

objective-c spilt array in multiple arrays for uitableview grouped

hi i have an array of objects which need to be sorted (alphabet on name)
ArtistVO *artist1 = [ArtistVO alloc];
artist1.name = #"Trentemoeller";
artist1.imgPath = #"imgPath";
ArtistVO *artist2 = [ArtistVO alloc];
artist2.name = #"ATrentemoeller";
artist2.imgPath = #"imgPath2";
ArtistVO *artist3 = [ArtistVO alloc];
artist3.name = #"APhextwin";
artist3.imgPath = #"imgPath2";
//NSLog(#"%#", artist1.name);
NSMutableArray *arr = [NSMutableArray array];
[arr addObject:artist1];
[arr addObject:artist2];
[arr addObject:artist3];
NSSortDescriptor *lastDescriptor =
[[[NSSortDescriptor alloc]
initWithKey:#"name"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSArray * descriptors =
[NSArray arrayWithObjects:lastDescriptor, nil];
NSArray * sortedArray =
[arr sortedArrayUsingDescriptors:descriptors];
NSLog(#"\nSorted ...");
NSEnumerator *enumerator;
enumerator = [sortedArray objectEnumerator];
ArtistVO *tmpARt;
while ((tmpARt = [enumerator nextObject])) NSLog(#"%#", tmpARt.name);
works fine. but now i need to split this awway up for usage in a grouped uitableview
self.sortedKeys =[[NSArray alloc]
initWithObjects:#"{search}",#"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",nil];
NSMutableArray *arrTemp0 = [[NSMutableArray alloc]
initWithObjects:#"000",nil];
NSMutableArray *arrTemp1 = [[NSMutableArray alloc]
initWithObjects:#"Andrew",#"Aubrey",#"Aalice", #"Andrew",#"Aubrey",#"Alice",#"Andrew",#"Aubrey",#"Alice",nil];
NSMutableArray *arrTemp2 = [[NSMutableArray alloc]
initWithObjects:#"Bob",#"Bill",#"Bianca",#"Bob",#"Bill",#"Bianca",nil];
NSMutableArray *arrTemp3 = [[NSMutableArray alloc]
initWithObjects:#"Candice",#"Clint",#"Chris",#"Candice",#"Clint",#"Chris",nil];
NSMutableArray *arrTemp4 = [[NSMutableArray alloc]
initWithObjects:#"Dandice",#"Dlint",#"Dhris",nil];
NSDictionary *temp =[[NSDictionary alloc]
initWithObjectsAndKeys:arrTemp0, #"{search}", arrTemp1,#"A",arrTemp2,
#"B",arrTemp3,#"C",arrTemp4,#"D",nil];
self.tableContents =temp;
so all Artist with first letter "a" come in one array ... with "b" in one array and so on.
do i need to do some string comparism or is there a better approach?
How about:
Create an empty NSMutableDictionary.
Loop through all your strings. For each string:
If string is empty, ignore this string.
Get a NSString containing first character of the string converted to uppercase. This will be your dictionary key.
Look in the dictionary to see if it already contains this key.
If not, create a new NSMutableArray containing just your string and add it as the value to this new key.
If so, add this string to the end of the existing array.
End of loop.