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.
}
Не заняло времени для управления памятью, но вы поняли идею.