2014-12-27 3 views
-2

Я новичок в программировании, и я чувствую себя немного запуганной публикацией, и я застрял. Я не хочу быстрого исправления! Пожалуйста, помогите мне понять это.- [Person componentsSeparatedByString:]: непризнанный селектор, отправленный в экземпляр

Я создал собственный метод с именем, возрастом, высотой и полом. Он вызывается, когда NSMutableArray добавляет пользовательские объекты в массив. По какой-то причине я не могу вытащить указанные предметы из NSMutableArray. Скажем, возраст нужно распечатать. Я получаю сообщение об ошибке сказав ...

-[Person componentsSeparatedByString:]: непризнанного селектора послал к экземпляру

Person.m

- (id)initWithName:(NSString *)n 
      age:(int)a 
     height:(float)h 
     gender:(char)g 
{ 
self = [super init]; 
if (self) { 
    self.name = n; 
    self.age = a; 
    self.height = h; 
    self.gender = g; 
} 

    return self; 
} 

- (NSString *)description 
{ 
NSString *descriptionString = [[NSString alloc] initWithFormat:@"%@, %d, %.1f, %c", 
           self.name, 
           self.age, 
           self.height, 
           self.gender]; 
NSLog(@"Description String: %@", descriptionString); 
    return descriptionString; 
} 

При добавлении объектов в NSMutableArray они преобразуются в NSString? Как я могу получить возраст людей без названия и высоты целых строк в NSLog?

ViewController.m

[self.people addObject:[[Person alloc] initWithName:@"Jake" age:29 height:73.5 gender:'f']]; 
[self.people addObject:[[Person alloc] initWithName:@"Jerry" age:24 height:82.3 gender:'m']]; 
[self.people addObject:[[Person alloc] initWithName:@"Jessica" age:29 height:67.2 gender:'f']]; 

NSString *mystring1 = [self.people objectAtIndex:0]; 
NSLog(@"%@", mystring1); 

// Works 
//NSString *list = @"Norm, 42, 73.2, m"; 

NSArray *listItems = [self.people[0] componentsSeparatedByString:@", "]; 
NSLog(@"List Items: %@", listItems[1]);// age 

Выход

Description String: Jake, 29, 73.5, f 
Jake, 29, 73.5, f 
-[Person componentsSeparatedByString:]: unrecognized selector sent to instance 

Решено:

Обратите внимание на дополнительные [возраст];

int age = [[self.people objectAtIndex:0]age]; 
NSLog(@"%d", age); 
+1

Нет, они не преобразуются в строку при добавлении их в массив. Что заставляет вас думать, что они делают? – rdelmar

+0

Где хранится 'componentsSeparatedByString'? В документе для NSString. Является ли ваш класс Person подклассом NSString? Нет. Знаете ли вы что-нибудь об объектно-ориентированном программировании? –

+1

Не нужно чувствовать себя запуганным ... Я думаю, что ваш код показывает, что вы, по крайней мере, имеете базовое понимание. Вы просто смущены тем, как получить доступ к свойствам вашего объекта. Нет необходимости преобразовывать ваше Person в строку, –

ответ

1

Я думаю, что причина, кажется, как ваш объект становится конвертируются в строку эта линия,

NSString *mystring1 = [self.people objectAtIndex:0]; 

вы должны указать свойство, если это все, что вы хотите напечатать

NSString *nameString = [[self.people objectAtIndex:0]name]; 
+0

Омг, спасибо! Я не знал, что вы можете сделать это дополнительно [имя]; – Jay

+0

Рад, что я мог бы помочь, не могли бы вы принять мой ответ, если он ответит на ваш вопрос. –

1

Вы не можете выполнить componentsSeparatedByString на вашем Person объекта, так как это не является строкой и не имеет этого метода. (NSMutableArray объектов не автоматически преобразуется в NSString с.) Но чтобы получить возраст вашего Person, должно быть довольно просто в любом случае. Просто доступ к Person «s age свойство:

int age = self.people[0].age; 
NSLog(@"Age: %d", age); 

Edit: Вы можете использовать технически componentsSeparatedByString на вашем mystring1NSString, например, так:

NSArray *listItems = [mystring1 componentsSeparatedByString:@", "]; 
NSLog(@"List Items: %@", listItems[1]);// age 

Но опять же, я не вижу смысла делая это, когда вы можете получить доступ к объекту Person 's age.

1

Метод componentsSeparatedByString является методом экземпляра класса NSString. Таким образом, вы не можете назвать это на своем Person.

Я не знаю, почему вам нужен этот код, если вы пытаетесь получить доступ к возрасту, а затем:

NSLog(@"Age %d", self.people[0].age); 

достаточно.Если вы пытаетесь достичь любой другой вещи, то вы можете получить такие компоненты, как:

NSArray *listItems = [self.people[0].description componentsSeparatedByString:@", "]; 
NSLog(@"List Items: %@", listItems[1]);// age 
0

Казалось бы, что это будет работать; однако я не могу вызвать .age в моем массиве.

NSLog(@"Age %d", self.people[0].age); 

дает следующий результат ...

Property 'age' not found on object of type 'id' 

Можно было бы также думать componentsSeparatedByString будет работать. Он не разделяет мою строку запятой и дает ошибку.

-[Person componentsSeparatedByString:]: unrecognized selector sent to instance 

Решенные дочитать

0

Я думаю, вы получаете путать о том, почему при входе объекта вы получаете строку, но вы не можете выполнять какие-либо методы на него.

И вот почему вы думаете, что получаете строку, вы внедрили свойство description, которое исходит от NSObject protocol. Когда вы делаете журнал объекта с параметром %@, вы получаете результат этого свойства, которое является строкой.

Так, глядя на ваш код:

NSString *mystring1 = [self.people objectAtIndex:0]; //1 
NSLog(@"%@", mystring1);        //2 

Первое состоит в том, что вы получаете первый объект из вашего массива. objectAtIndex возвращает id, который является указателем на NSObject. Это не строго типизированный возврат. Вы назначаете его на NSString, который является неправильным, потому что он как фактически объект человека. Но поскольку вы не называете на него каких-либо методов NSString, компилятор не помещает это неправильное назначение.

Во-вторых, вы только что получили результат свойства description, как я уже упоминал.

Отредактированный решение:

int age = [[self.people objectAtIndex:0]age]; 

Работает, но вот почему: вы получаете objectAtIndex:0, который возвращает id. Затем вы отправляете сообщение age. Objective-C - динамический язык, что означает, что вы можете отправлять любое сообщение любому объекту (хотя вы получаете крах во время выполнения, если объект не реализует метод). В этом случае ваш объект Person реализует метод age (поскольку это общественная собственность), поэтому вы возвращаетесь назад.

Другой способ сделать это:

NSInteger age; 
Person *person = self.people.firstObject; 
if (person) { 
    age = person.age; 
} else { 
    age = NSNotFound; 
} 

Почему я делаю это так?

Во-первых, я получаю первый объект из массива и помещаю его в типизированную переменную. Это безопаснее, если нет объекта с индексом 0 (т. Е. Массив пуст), то вы не будете разбивать свое приложение. firstObject возвращает первый объект, если он существует, на nil, если это не так.

Во-вторых, только если человек был правильно извлечен из массива, присвойте мне возраст переменной NSInteger. Вы должны предпочесть конкретные типы NSInteger над intCGFloat над float), потому что они будут использовать переменную правильного размера при работе в 32-битных или 64-битных системах.

В-третьих, если человек не может быть создан, мне присваивается значение NSNotFound. Это typedef для очень большого количества, с которым вы можете сравнить. Просто вернуть 0 в возрасте недостаточно, чтобы сказать вам, что произошла ошибка. Лицо могло бы возрастом 0 с помощью этого кода вы можете испытать возраст:

if (age != NSNotFound) { 
    // This is a valid age, do something with it 
} else { 
    // A person object could not be extracted from the array, this is not a valid age 
} 

Это перебор? На самом деле, нет. Когда вы начнете писать настоящие сложные приложения, такое защитное программирование будет естественно для вас. Массивы могут быть пустыми, ваши данные могут быть неправильно созданы и т. Д. Написание кода, который изящно обрабатывает эти возможности, является настоящим навыком программирования. К сожалению, это немного длиннее, и большинство учебных пособий, которые вы найдете в Интернете, показывают вам простой, счастливый путь.

Надеюсь, это даст вам лучшее представление о том, что делает ваш код, и о том, что еще вы можете сделать, чтобы написать надежный код.

+0

Спасибо, что нашли время написать этот роман ответа. Мне было много чего посмотреть! – Jay