3

I'm attempting to complete the Stanford iPhone Programming (FA10) assignement "Flickr Fetcher" -- so far things are going well, however I have come to an impasse:

I have successfully extracted the location of the "Top 100" pictures, which are formated in a string as "Country, State, City". I would like to create two NSStrings -- one being the country, the other string being the State and City. From where I can then do

cell.textLabel.text = countryString;
cell.detailTextLabel.text = stateCityString;

in my table view datasource methods.

From research on stackoverflow and the Apple Documentaion, NSScanner seems to be my best bet -- here is what I have so far...

- (void)viewDidLoad {
    //Get the top 100 photos from Flickr
    self.topPlacesArray = [FlickrFetcher topPlaces];

    NSString *mainLabelString = [[NSString alloc] init];
    NSString *stringFromArray = [[NSString alloc] init];

    //This retrieves the string of the location of each photo
    stringFromArray = [topPlacesArray valueForKey:@"_content"];

    NSScanner *theScanner = [NSScanner scannerWithString:stringFromArray];
    NSCharacterSet *commaSet = [[NSCharacterSet alloc] init];
    commaSet = [NSCharacterSet characterSetWithCharactersInString:@","];

    while ([theScanner isAtEnd] == NO) {
        if ([theScanner scanUpToCharactersFromSet:commaSet intoString:&stringFromArray]) {
            NSLog(@"%@",stringFromArray);
        }
    }

I'm just trying to see if the string properly substrings itself -- however I am getting a "SIGBART" at the beggining of the while loop, the error is this:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x8939eb0'

From all the documentation I have seen on NSScanner, it seems I have it set up properly, however, no matter what changes I do, it seems unable to even begin the loop.

What do I have to do to set up NSScanner properly, to avoid the "SIGABRT"? (for the record, i'm assuming "SIGABRT" is a segfault?). Thank you all for your time, you all are the best!

(Btw: I know this is not fully implemented yet for both country and state-city, i just want to get used to NSScanner, I will implement the rest once I get NSScanner under control)

EDIT 1: SosBorn! You are incredible! Thank you so much! So I have implemented this for my viewDidLoad:

- (void)viewDidLoad
{
    self.topPlacesArray = [FlickrFetcher topPlaces];
    NSArray *ArrayOfStrings = [[NSArray alloc] init];
    NSArray  *placeElements = [[NSArray alloc] init];
    NSString *country = [[NSString alloc] init];
    NSString *city = [[NSString alloc] init];
    NSString *state = [[NSString alloc] init];

    ArrayOfStrings = [topPlacesArray valueForKey:@"_content"];

    for (NSString *place in ArrayOfStrings) {

        placeElements = [place componentsSeparatedByString:@", "];
        if ([placeElements count] == 3 && [placeElements objectAtIndex:0] != nil) {
           city = [placeElements objectAtIndex:0];
           [self.cityArray addObject:city];
           state = [placeElements objectAtIndex:1];
           [self.stateArray addObject:state];
           country = [placeElements objectAtIndex:2];
           [self.countryArray addObject:country];
           NSLog(@"%@, %@, %@", city, state, country);    
        }
       else {
           NSLog(@"Did this work?");
       }
    }

    [ArrayOfStrings release];
    [placeElements release];
    [country release];
    [city release];
    [state release];
    [super viewDidLoad];
}

This worked like a complete charm BUT i'm having some bad access going on in the Delegate when trying to access self.window.rootViewController = self.viewController -- this doesn't make any-sense (i actually have a completely empty table, etc...) -- so i'm thinking I played with bad memory management with my substring-ing and now it gets in trouble with this delegate call.

Chuck, I was very interested in your comment as I was taught that the proper way to make variables is to call [myclass alloc] init]; and then release when you are done -- as I have. Of course my objective-C greenness is showing a bit... blush.

You all and this incredible community are such an asset to us Students -- thank you for all your time and dedication. The only path to progress is a path of cooperation!

EDIT 2: Ok -- now it's totally fixed with no terrible leaking problems. Chuck you were right! I had the pricniples of alloc init completely mixed up in my head -- here was my final solution:

    NSMutableArray *array1 = [[NSMutableArray alloc] init];
NSMutableArray *array2 = [[NSMutableArray alloc] init];
NSMutableArray *array3 = [[NSMutableArray alloc] init];

self.cityArray = array1;
self.countryArray = array2;
self.stateArray = array3;

[array1 release];
[array2 release];
[array3 release];


NSArray *ArrayOfStrings = [topPlacesArray valueForKey:@"_content"];
NSArray *topPlaces = [NSArray arrayWithArray:ArrayOfStrings];
NSArray *topPlacesSorted = [topPlaces sortedArrayUsingSelector:@selector(compare:)];
ArrayOfStrings = topPlacesSorted;

for (NSString *place in ArrayOfStrings) {
    NSArray *placeElements = [place componentsSeparatedByString:@", "];
    if ([placeElements count] == 3 && [placeElements objectAtIndex:0] != nil) {

        NSString *city = [placeElements objectAtIndex:0];

        [self.cityArray addObject:city];

        NSString *state = [placeElements objectAtIndex:1];

        [self.stateArray addObject:state];

        NSString *country = [placeElements objectAtIndex:2];

        NSString *stateAndCountry = [NSString stringWithFormat:@"%@, %@", state, country];

        [self.countryArray addObject:stateAndCountry];

        NSLog(@"%@, %@, %@", city, state, country);    
    }
   else {
       NSLog(@"Nil Request");
   }

Thank you again SosBorn, i was feeling like I had forgotten the basics of CS ಠ_ಠ. The only thing that really bothers me is why do we have to initialize instance NSMutableArrays that way -- i found this was the only way to get them to actually work.

1
  • 1
    FYI, every single alloc-init in that code is pointless at best and a leak at worst. You just reassign new objects to the variables without using those ones you created. Commented Jul 8, 2011 at 6:35

1 Answer 1

1

Not totally sure why it is crashing, but I think another approach to this would serve you better. You have a topPlacesArray, why not iterate through the array and process each array entry seperately? I am making some assumptions about the topPlacesArray, but it would look something like this:

for (NSString *place in topPlacesArray)
{
  //Place is probably in this format: "Country, State, City"
  NSArray *placeElements = [place componentsSeperatedByString:@","];
  //This should give you an array with three elements. Country State and city.
  NSString *country = [placeElements objectAtIndex:0];
  NSString *cityState = [NSString stringWithFormat:@"%@, %@", country, cityState];
  //Now you have your strings that you need. Do whatever you need to do with them.
  //Add them to an array or set the value of a text label, etc.
}

Didn't take the time to handle memory management but you get the idea.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.