iOS/Objective-C: Попытка отсканировать строку на наличие подстрок, которые будут назначены нескольким NSStrings

Я пытаюсь выполнить задание Стэнфордского iPhone Programming (FA10) "Flickr Fetcher" - пока все идет хорошо, однако я зашел в тупик:

Я успешно извлек местоположение "100 лучших" фотографий, которые представлены в виде строки "Страна, Штат, Город". Я хотел бы создать две строки NSS - одна страна, другая строка штат и город. Откуда я могу тогда сделать

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

в моем табличном представлении методы источника данных.

NSScanner - это мой лучший выбор из исследований стекового потока и Apple Documentaion.

- (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);
        }
    }

Я просто пытаюсь увидеть, правильно ли строка подстроки сама - однако я получаю "SIGBART" в начале цикла while, ошибка заключается в следующем:

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

Из всей документации, которую я видел на NSScanner, кажется, что она настроена правильно, однако, независимо от того, какие изменения я делаю, кажется, что она не может даже начать цикл.

Что мне нужно сделать, чтобы правильно настроить NSScanner, чтобы избежать "SIGABRT"? (для записи, я предполагаю, что "SIGABRT" - это ошибка?). Спасибо всем за ваше время, вы все лучшие!

(Кстати: я знаю, что это еще не полностью реализовано как для страны, так и для штата, я просто хочу привыкнуть к NSScanner, остальное я буду реализовывать, как только получу контроль над NSScanner)

РЕДАКТИРОВАТЬ 1: SosBorn! Ты потрясающая! Спасибо вам большое! Итак, я реализовал это для моего 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];
}

Это работало как полный шарм, НО у меня был некоторый плохой доступ, происходящий в Делегате, пытаясь получить доступ self.window.rootViewController = self.viewController - это не имеет никакого смысла (на самом деле у меня есть полностью пустая таблица и т. д.) - поэтому я думаю, что я играл с плохим управлением памятью с моей подстрокой и теперь у меня возникают проблемы с этим вызов делегата.

Чак, мне очень понравился твой комментарий, так как меня учили, что правильный способ создания переменных - это вызвать [myclass alloc] init]; и затем отпустите, когда вы закончите - как я. Конечно, моя цель-C зеленость показывает немного... краснеть.

Вы, и это невероятное сообщество, - это наш актив для нас, студентов, спасибо за ваше время и преданность делу. Единственный путь к прогрессу - это путь сотрудничества!

РЕДАКТИРОВАТЬ 2: Хорошо - теперь это полностью исправлено без ужасных проблем с утечкой. Чак ты был прав! У меня в голове были целиком и полностью перемешаны ресурсы alloc init - вот мое окончательное решение:

    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");
   }

Еще раз спасибо, SosBorn, я чувствовал, что забыл основы CS ಠ_ಠ. Единственное, что меня действительно беспокоит, так это то, почему мы должны инициализировать экземпляр NSMutableArrays таким образом - я обнаружил, что это был единственный способ заставить их работать на самом деле.

1 ответ

Решение

Не совсем уверен, почему это терпит крах, но я думаю, что другой подход к этому послужит вам лучше. У вас есть topPlacesArray, почему бы не выполнить итерацию по массиву и не обработать каждую запись массива отдельно? Я делаю некоторые предположения о topPlacesArray, но это будет выглядеть примерно так:

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.
}

Не заняло времени для управления памятью, но вы поняли идею.

Другие вопросы по тегам