IPhone Navigation-Based Application Model - objective-c

I am making a Navigation-Based Application for the IPhone and I start off with a big list of names (about 100) and I was wondering what would be the quickest and most efficient way to alter the content according to what name the user tapped on in the list.
Right now I change the content according to what the title is like this:
NSString *comparisonString = #"Bill Clinton";
NSString *comparisonString2 = #"Bob Dole";
if (self.title == comparisonString) {
NSString *alterString = [NSString stringWithFormat: #"He is a democrat from North Carolina "];
[appDelegate setModelData:alterString];
}
else if (self.title == comparisonString2) {
NSString *alterString = [NSString stringWithFormat: #"He was born into a family in New York City... "];
[appDelegate setModelData:alterString];
}
would this be the best way to do this? Seems like a lot of code would be repeated. I am brand new to Objective-C and developing for the IPhone, any advice will help me. Thank you!

What you've written so far in those two conditions is equivalent to this (with no if statement):
NSString *alterString = [NSString stringWithFormat: #"Content for %#!", self.title];
[appDelegate setModelData:alterString];
Hope that helps.
All you are doing is changing that same part of the string in both the if and else statements (and presumably more else statements later)
EDIT
ok, looking now at the edited question, you basically have a look up table now. So self.title is the key and you want to use that to lookup another string.
One way to do this is to create a plist with a dictionary that maps each name to a string. Then load that plist and look up the name from there. Something like this:
NSDictionary* people = [NSDictionary dictionaryWithContentsOfFile:pathToThePlist];
NSString *content = [people objectForKey:name];
(BTW, right now you are using '==' for string comparison, you want to use -[NSString isEqualToString:] for that in the future.

Related

Removing text from NSString between "#" and ":" while keeping the text after it

So I'm reading the most recent tweet from a twitter bot and assigning it to a string, but sometimes it tweets directly to users. Here's an example of what that might look like.
NSString tweet = #("#user hey heres my message: BLah blah with symbols!");
//part I want to keep is: " BLah blah with symbols!"
//or it could end up being
NSString tweet = #("#otheruser my msg is: Wow heres some more blah: and a second colon");
//part I want to keep is: " Wow heres some more blah: and a second colon"
I want to always remove the first part that talks to the user, while keeping the message on the end. There are too many different messages to use "stringByReplacingOccurrencesOfString"
I don't want to use "exlude-replies" from the twitter API because this bot is very popular and that would require fetching up to 100 since "count" applies before
any idea how I could do this? I think it has something to do with regular expressions, but I haven't ever used them before or been able to get one working how I want. I would really appreciate the help from anyone whos comfortable with regex
edit: also if a regex won't work for this case, id accept an explanation of the limitation preventing that :)
The easiest solution that I can think of is to create an NSMutable array, by using the NSString function componentsSeparatedBy:#":", and simply remove the first element.
NSMutableArray *tweetArray = [[NSMutableArray alloc] initWithArray: [tweet componentsSeparatedByString:#":"]];
[tweetArray removeObjectAtIndex:0];
Your issue with a colon appearing at random afterwards can be fixed by joining the pieces back together again.
tweet = [tweetArray componentsJoinedByString:#":"];
Edit: Fix an error pointed out by user 'maddy'
You'll have to stick this code in an if statement so that it does not execute in tweets that have a colon normally. You can use the fact that it always begins with #user however.
if ([tweet characterAtIndex:0] == '#' && [tweet characterAtIndex:1] != ' '){
NSMutableArray *tweetArray = [[NSMutableArray alloc] initWithArray: [tweet componentsSeparatedByString:#":"]];
[tweetArray removeObjectAtIndex:0];
tweet = [tweetArray componentsJoinedByString:#":"];
}
You can also use this.
NSString *myString = #"#username is me: by using this as sample text";
NSRange range = [myString rangeOfString:#":"];
NSString *newString= [myString substringFromIndex:range.location];
NSLog(#"New String is : %#", newString);

Having trouble taking an index of an array and making it an NSString

I get an array from a JSON and I parse it into an NSMutableArray (this part is correct and working). I now want to take that array and print the first object to a Label. Here is my code:
NSDictionary *title = [[dictionary objectForKey:#"title"] objectAtIndex:2];
arrayLabel = [title objectForKey:#"label"];
NSLog(#"arrayLabel = %#", arrayLabel); // Returns correct
//Here is where I need help
string = [arrayLabel objectAtIndex:1]; //I do not get the first label (App crashes)
NSLog(#"string = %#", string);
other things that I have already tried are as follows:
string = [NSString stringWithFormat:#"%#", [arrayImage objectAtIndex:1]];
and
string = [[NSString alloc] initWithFormat:#"%#", [arrayImage objectAtIndex:1]];
Any help is greatly appriciated!
EDIT: The app does not return a single value and crashes.
Your code doesn't match the structure of your JSON. In your comment on the deleted answer, you said you got an exception when sending objectAtIndex: to an NSString. In your case, arrayLabel isn't an array when you think it is.
If your JSON has an object, your code needs to treat it as an NSDictionary. Likewise for arrays and NSArray and strings and NSString.
In addition to whatever else was going on, you repeatedly refer to "first" but use the index 1. In most C-based programming languages (and others, as well) the convention is that indexes into arrays are 0-based. So, use index 0 to get the first element.

How can I handle this in cocoa? Retrieve an entry from a plist file?

I have this small excel file given by a brazilian government authority, it contains records for each city in Brazil, a ZIP Code range for each city and its "city code" .
I need to retrieve for a given city its "city code".
I imagine the best way would be to parse a given zip code for the city and return its "city code", based on the first two columns that display the zip code range.
I am confident that using AppleScript I can compile a plist file for the given Excel file. But can someone point me for a few lines of objectiveC code to retrieve the given entry from a plist file once I parse the ZIP code?
Please see excel file at http://www.idanfe.com/dl/codes.xls.zip
Thanks.
I have uploaded a sample plist file to http://www.idanfe.com/dl/cityCodes.plist
Further explanation:
I will parse a ZIP CODE value like: 01123010 which is in the range of 01001000 and 05895490, so my routines should return me City Code = 3550308 and City Name = São Paulo.
I have no idea how to achieve this, I might have built the sample plist wrong.
I am confident I can build a plist file using AppleScript, reading from the Excel sheet.
But retrieving the City code for a given ZIP CODE range is a puzzle.
+++ EDIT: +++
I think I have solved it, but it looks kind of clumsy, as almost everything I write.
This AppleScript reads the Excel sheet and writes the plist file : http://www.idanfe.com/dl/creating.scpt.zip
Here you find the 1 MB plist file: http://www.idanfe.com/dl/cityCodes.plist.zip
This is the code I wrote to get the City Code I need:
NSString *zipCodeString;
zipCodeString = #"99990000";
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"cityCodes" ofType:#"plist"];
NSDictionary *cityCodes_dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
NSArray *allKeys = [cityCodes_dictionary allKeys];
int i = 0;
for (i = 0 ; i <= [allKeys count]; i++) {
NSString *someKey = [allKeys objectAtIndex:i];
NSRange range08 = NSMakeRange (0, 8);
NSRange range88 = NSMakeRange (8, 8);
NSString *startZipCode = [someKey substringWithRange:range08];
NSString *finalZipCode = [someKey substringWithRange:range88];
int startZipCodeInt = [startZipCode intValue];
int finalZipCodeInt = [finalZipCode intValue];
if(startZipCodeInt <= [zipCodeString intValue] && finalZipCodeInt >= [zipCodeString intValue]){
NSLog(#"we found a winner");
NSString *cityCode = [NSString stringWithFormat: #"%#",[[cityCodes_dictionary objectForKey:someKey]objectForKey:#"City Code"]];
[cityCodeIBGEField setStringValue:cityCode];
NSLog(#"cityCode = %#",cityCode);
break;
} else {
// NSLog(#"no winners");
}
}
Basically I append the start zipCode and finalZip Code into one string of 16 digits, so I create one single record in the plist file.
Then when searching for the City Code I break the long key (2 zip codes) in 2 (back to normal zipCode) and search to see which record fits the given zipCode I need a cityCode for.
Some how it doesn't look the best for me, but for my own surprise the code is very fast, although in a loop.
I would appreciate comments...
Thanks,
I would use indexOfObjectPassingTest: to do this kind of search. Something like this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"cityCodes" ofType:#"plist"];
self.cityCodes_dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
[self findCityWithZip:#"01123010"];
}
-(void)findCityWithZip:(NSString *) searchZip {
NSUInteger indx = [self.cityCodes_dictionary.allKeys indexOfObjectPassingTest:^BOOL(NSString *zip, NSUInteger idx, BOOL *stop) {
NSString *startZipCode = [zip substringWithRange:NSMakeRange(0, 8)];
NSString *finalZipCode = [zip substringWithRange:NSMakeRange(8, 8)];
return (searchZip.integerValue < finalZipCode.integerValue && searchZip.integerValue > startZipCode.integerValue);
}];
NSLog(#"%#",[self.cityCodes_dictionary valueForKey:[self.cityCodes_dictionary.allKeys objectAtIndex:indx]]);
}
Reading the plist shouldn't be a problem at all if it is structured as a dictionary:
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: #"cities.plist"];
//NSString *zipStr = [dict valueForKey: #"CityNme"]; //this was an example
That's the easy part. The harder part is parsing and structuring the plist file from an xls file.
Or did I misunderstand your question?
PS: to get a quick look at the dictionary's plist structure, create a mock dictionary and NSLog it's description to see how it's supposed to be (or writeToFile to see the file contents or of course refer to the docs)
edit
You load the supplied plist file in a dictionary using the above code. Then you retrieve another dictionary from within it using
NSDictionary *city = [dict valueForKey : #"yourZipCodeHere"];
From that dictionary you get the cityCode like this
NSString *cityCode = [city valueOrKey: #"City Code"];
As for your range problem, I'm not sure I understand it completely. But you can get an array of all the zip codes using
NSArray *zipArray = [dict allKeys];
And then you can simply iterate over that to get the correct zip code.
PS: I don't know much apple script and would be interested in how you converted the xls to plist using it.

App Store ID via Appirater different than ID from plist, and apparently random

I'm having an issue with grabbing the App Store ID from my plist, and using it with Appirater. I NSLogged the URL that was being used when the user pushes "Rate Now", and the App Store ID is way different from the App Store ID I set in Info.plist. No idea where it is getting these numbers from -- they are a different set of 9 numbers each time. This is really strange.
The code in Appirater.m that deals with grabbing the App Store ID and using it in the link looks like this: NSString *const kAppiraterAppIdBundleKey = #"AppStoreId";
NSString *templateReviewURL = #"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID";
....
+ (NSString*)appStoreAppID {
NSString* value = [[[NSBundle mainBundle] infoDictionary] objectForKey:kAppiraterAppIdBundleKey];
NSAssert1(value, #"Error - you have not specified %# property in your info.plist", kAppiraterAppIdBundleKey);
return value;
}
//...
+ (void)rateApp {
//...
NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:#"APP_ID" withString:[NSString stringWithFormat:#"%d", [self appStoreAppID]]];
//...
}
I added a field in the plist called "AppStoreId", and entered the 9 digit code. I made it a string type. Now, the code runs perfectly when I replace "APP_ID" with the actual 9 digit code in that iTunes link above, but when I keep it as APP_ID, I get the error "Cannot connect to the iTunes Store.", and the NSLog output has 9 random numbers in the link, and again, they are different each time.
This is probably an easy fix, but I can't seem to figure it out.
Random numbers? You're using:
[NSString stringWithFormat:#"%d", [self appStoreAppID]]
where appStoreAppID is an NSString.
So you're replacing "APP_ID" with the pointer to the NSString, not the contents of the NSString.
Just use %# instead of %d.

getting NSArray length/count - Objective C

Well I've looked at similar problems over the site but haven't reached a solution thus far so I must be doing something wrong.
Essentially, I am importing a text file, then splitting each line into an element of an array. Since the text file will be updated etc.. I won't every know the exact amount of lines in the file and therefore how many elements in the array. I know in Java you can do .length() etc.. and supposedly in Objective C you can use 'count' but i'm having no luck returning the length of my array... suggestions?
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"allshows"
ofType:#"txt"];
NSString *fileString = [NSString stringWithContentsOfFile:filePath];
NSArray *lines = [fileString componentsSeparatedByString:#"\n"];
NSUInteger *elements = [lines count];
NSLog(#"Number of Shows : ", elements);
and what is being output is NOTHING. as in "Number of Shows : " - blank, like it didn't even count at all.
Thank you for any help!
You're missing the format string placeholder. It should be:
NSLog(#"Number of shows: %lu", elements);
You need to use a format specifier to print an integer (%d):
NSLog(#"Number of Shows : %d", elements);
Looking at your other post, it seems like you are a Java developer. In Java's System.out, you just append the variables. In Objective-C, I suggest you look at "print format specifiers". Objective-C uses the same format.