Building an NSstring out of an NSMutableArray - nsstring

My eyes hurt from hours of trying to figure this one - and i have looked for an answer for quite a while on-line (it will be embarrassing to tell how much...).
all i am trying to do is to enumerate using a for-in loop on anExpression which is a NSMutableArray that holds NSNumbers and NSStrings.
my NSLog print for the variable ans returns an empty string.
What am i doing wrong?
NSString *ans = #"";
for (id obj in anExpression)
{
if ([obj isKindOfClass:[NSString class]])
[ans stringByAppendingString:(NSString *)obj];
if ([obj isKindOfClass:[NSNumber class]])
[ans stringByAppendingString:(NSString *)[obj stringValue]];
NSLog(#"String so far: %# ", ans);
}

I think you mean
ans = [ans stringByAppendingString:(NSString *)obj];
not just
[ans stringByAppendingString:(NSString *)obj];
NSStrings are immutable -- you can't append to them. -stringByAppendingString: returns a new string (which you could then assign to ans).
Alternatively, you might use an NSMutableString and the -appendString: method.

Hey, sorry for the bad coding format, posting it again ...
NSString *ans = #"";
for (id obj in anExpression)
{
if ([obj isKindOfClass:[NSString class]])
[ans stringByAppendingString:(NSString *)obj];
if ([obj isKindOfClass:[NSNumber class]])
[ans stringByAppendingString:(NSString *)[obj stringValue]];
NSLog(#"String so far: %# ", ans);
}
[ans autorelease];
NSLog(#"final string is: %# ", ans);
return ans;

the method stringByAppendingString: returns a new string made by appending the given string to the receiver.
so you want ans = [ans stringByAppendingString:obj];

Related

Why does this type conversion of NSString to NSNumber returns invalid value of -1?

This is the line of code in question:
bks.quantity = [NSNumber numberWithInteger: [[arrayOfSplitStrings[i] objectAtIndex:[[sd.dictionaryOfUserIndexes objectForKey: #"29"] intValue]] intValue]-1];
sd.dictionaryOfUserIndexes objectForKey: #"29" contains a string (representing a quantity) that has to be converted to NSNumber. When the statement is executed with a valid string quantity (0-10) it always returns -1, when it is supposed to return the NSNumber for the value.
What am I doing wrong?
This is not a "straight forward" answer (since the solution is just a silly one), it's more a suggestion on work methods, that's why I post an answer.
It's not always good to put it various lines in a single line.
Especially when in your case you encounter an issue. It's better to split each command, one by one, and to debug, check the value of each ones.
In your case:
bks.quantity = [NSNumber numberWithInteger: [[arrayOfSplitStrings[i] objectAtIndex:[[sd.dictionaryOfUserIndexes objectForKey: #"29"] intValue]] intValue]-1];
==>
NSInteger userOfIndexes = [[sd.dictionaryOfUserIndexes objectForKey: #"29"] intValue];
NSLog(#"userOfIndexes: %d", userOfIndexes);
NSInteger n = [arrayOfSplitStrings[i] objectAtIndex:userOfIndexes] intValue];
NSLog(#"n: %d", n);
bks.quantity = [NSNumberWithInteger:n-1];
I added NSLog(), but the values could be check with breakpoints and debugger. I could have also add a check on arrayOfSplitStrings with
NSArray *splitStrings = arrayOfSplitString[i];
NSLog(#"splitStrings: %#", splitStrings);
and replace n with:
NSInteger n = [splitStrings objectAtIndex:userOfIndexes] intValue];
That way, you would have check that apparently (according to your comment), your issue was were to put the "-1.
NSInteger n = [[arrayOfSplitStrings[i] objectAtIndex: userIndex-1] intValue];

NSPredicate Character and/or Letter Substitutions

I've seen some, somewhat, similar questions about filtering out special characters in a predicate - but nothing suitable for my needs. I'm not really sure if what I want to do is even possible but I'll put it to the community instead:
I'm working with strings of pronunciations for a dictionary that contain a lot of IPA characters for instance:
ȵ
ɕ
ŋ
Ẓ
What I would like to do is set up some substitutions for these characters, something like:
n=ȵ
x=ɕ
ng=ŋ
r=Ẓ
in a search predicate so that a search for n* would result with anything beginning in ȵ, etc, etc...
Even other IPA 'letters' like "v" would be best resembled by a "w" if there is a simple way to switch in SEARCH letters for other STRING letters that would be great...
It seems like this should be done outside the predicate. Create a dictionary where the keys are the strings to be replaced and the values are the replacements. Then, have a loop which iterates over the dictionary and performs each replacement on the string that you will be searching. The resulting string after replacement is the string that you use in the predicate.
got the answer from here:
stackoverflow.com/questions/21852502/nspredicate-ignore-numbers-in-string-pinyin
an other question to which I asked...
this is the code [incase this is helpful for anyone else later] I used for string "pro" in class Words
- (NSString *)searchableStringValueTwo {
NSCharacterSet *invalidSet = [NSCharacterSet characterSetWithCharactersInString:#"ȵ"];
NSString *searchString = [[pro componentsSeparatedByCharactersInSet:invalidSet] componentsJoinedByString:#"n"];
return searchString;
}
- (NSString *)searchableStringValueThree {
NSCharacterSet *invalidSet = [NSCharacterSet characterSetWithCharactersInString:#"ɕ"];
NSString *searchString = [[pro componentsSeparatedByCharactersInSet:invalidSet] componentsJoinedByString:#"x"];
return searchString;
}
- (NSString *)searchableStringValueFour {
NSCharacterSet *invalidSet = [NSCharacterSet characterSetWithCharactersInString:#"ŋ"];
NSString *searchString = [[pro componentsSeparatedByCharactersInSet:invalidSet] componentsJoinedByString:#"ng"];
return searchString;
}
- (NSString *)searchableStringValueFive {
NSCharacterSet *invalidSet = [NSCharacterSet characterSetWithCharactersInString:#"Ẓ"];
NSString *searchString = [[pro componentsSeparatedByCharactersInSet:invalidSet] componentsJoinedByString:#"r"];
return searchString;
}
- (NSString *)searchableStringValueSix {
NSCharacterSet *invalidSet = [NSCharacterSet characterSetWithCharactersInString:#"v"];
NSString *searchString = [[pro componentsSeparatedByCharactersInSet:invalidSet] componentsJoinedByString:#"w"];
return searchString;
}

sqlite get single row

NSString *cityInput = cityField.text;
NSString *code = #"";
NSString *query = #"SELECT code FROM country WHERE cityname = UPPER(?)";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [query UTF8String],-1, &statement, nil) == SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [cityInput UTF8String], -1, SQLITE_STATIC);
while(sqlite3_step(statement) == SQLITE_ROW) {
code = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)];
}
}
if(sqlite3_step(statement) != SQLITE_DONE){
NSLog(#"DB: query KO");
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"ALERT" message:#"City not found" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
return;
}
sqlite3_close(database);
Two questions:
1) for get single row i must use while loop?
2) if there isn't result in the query how alert "city not found"
Obviously you will get the last row,,
code
should be an array u might declare it like this
NSMutableArray *code=[NSMutableArray array];
then in the while loop use
[code addobject:[NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0)]];
I hope this is clear enough:)
Using while gives you the last row and it is not needed. Add limit 1 clause to your query, or simply take the first row returned;
Decide whether to show alert by checking return code.
Maybe two answers,
1) No, just an if clause will do
2) Do an assignement and then run an if clause on it
int result = sqlite3_step(statement)
if (result == SQLITE_ROW){
//processline
}
else{
//show alert
}

Core Data: fetching items is slow with predicate

For my iPhone application I set up a data model for Core Data. It contains one entity Words and its attributes are language : String, length : Integer16 and word : String.
I prefilled my model's SQLite database with a word list (200k items) writing a separate iPhone application using the identical data model and coping the filled database to the main application.
Now using NSFetchedRequest I can query for managed objects as I like, but the results come in slow. I use the following method:
- (NSString *)getRandomWordLengthMin:(int)minLength max:(int)maxLength
{
NSString *word = #"";
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Words"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSString *predicateString = #"length >= %d AND length <= %d";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString,
minLength, maxLength];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
int entityCount = [context countForFetchRequest:fetchRequest error:&error];
[fetchRequest setFetchLimit:1];
if(entityCount != 0)
{
[fetchRequest setFetchOffset:arc4random()%entityCount];
}
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if([fetchedObjects count] != 0)
{
Words * test = [fetchedObjects objectAtIndex:0];
word = [NSString stringWithFormat:#"%#", [test word]];
}
return word;
}
Using an SQLite editor I already set an index manually on column zLength, but this didn't bring any speedup. Where is the bottleneck?
EDIT:
I figured out that getting int entityCount = ... is slow. But even getting all objects and then selecting one random word is slow:
Words * test = [fetchedObjects objectAtIndex:arc4random()%[fetchedObjects count]];
You are effectively running two fetches here, one to get the fetch count and then one to fetch the actual object. That will slow things down.
Your predicate is "backwards." Compound predicates evaluate the first expression e.g. length >= %d and then evaluate the second e.g. length <= %d only against the results of the first. Therefore you should put the test that eliminates the most objects first. In this case, length <= %d probably eliminates more objects so it should come first in the predicate.
Since you don't actually need the entire Words managed object but just the word string, you can set the fetch return type to NSDictionaryResultType and then set the property to fetch to just the word attribute. That will speed things up considerably.
Part of your problem here is that Core Data is designed to managed a structured object graph and you are using a random/unstructured graph so you are cutting against the grain of Core Data's optimizations.
Do not use the SQLite editor to edit the SQLite backing store for a Core Data storage. The internals of the database is private and subject to change.
Instead go the the model editor in Xcode and simply put a checkmark on the "indexed" option for the entity attribute you want indexed.
Not sure but maybe this predicate is easier to optimize:
NSString *predicateString = #"length BETWEEN (%d, %d)";

Trim file extension UITableView

I want to trim the file extension from text I have an NSMutableArray in table cells.
NSMutableArray *theFiles = [NSMutableArray new];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager directoryContentsAtPath:#"/Test"];
for (NSString *s in fileList){
[theFiles addObject:fileList];
}
cell.textLabel.text = theFiles[indexPath.row];
return cell;
This lists for example "Xylophone.m4r" I want to remove the .m4r.
Try -[NSString stringByDeletingPathExtension] (in NSPathUtilities.h).
Actually, for my use, I was able to create a plist programmatically and just not use an extension and it works great! However, anothe rway to do this is:
[string stringByReplacingOccurrencesOfString:#".fileextension" withString:#""];
Just have to delete path extension component:
cell.textLabel.text = [[theFiles objectAtIndex:indexPath.row] stringByDeletingPathExtension];

Resources