我是编程新手,我觉得有点吓人的帖子,而且我被卡住了。我不想快速修复!请帮我理解这一点。
我创建了一个名称,年龄,身高和性别的自定义方法。当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);
答案 0 :(得分:1)
您无法在componentsSeparatedByString
对象上执行Person
,因为它不是字符串且没有该方法。 (NSMutableArray
个对象不会自动转换为NSString
s。)但要获得Person
的年龄,无论如何都应该相当简单。只需访问Person
的{{1}}媒体资源:
age
修改:您可以在int age = self.people[0].age;
NSLog(@"Age: %d", age);
componentsSeparatedByString
上技术上使用mystring1
,如下所示:
NSString
但是,当您可以直接访问NSArray *listItems = [mystring1 componentsSeparatedByString:@", "];
NSLog(@"List Items: %@", listItems[1]);// age
的{{1}}媒体资源时,我认为没有这样做。
答案 1 :(得分:1)
componentsSeparatedByString
方法是NSString类的实例方法。您无法以这种方式在Person
课程上调用它。
如果您尝试访问年龄,我不知道您为什么需要该代码,那么:
NSLog(@"Age %d", self.people[0].age);
就够了。如果你想要实现任何其他的东西,那么你可以获得如下组件:
NSArray *listItems = [self.people[0].description componentsSeparatedByString:@", "];
NSLog(@"List Items: %@", listItems[1]);// age
答案 2 :(得分:1)
我认为您的对象似乎转换为字符串的原因是这一行,
NSString *mystring1 = [self.people objectAtIndex:0];
如果您要打印所有内容,则需要指定属性
NSString *nameString = [[self.people objectAtIndex:0]name];
答案 3 :(得分: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
已解决已阅读
答案 4 :(得分:0)
我认为您对为什么在记录对象时遇到字符串感到困惑,但是您无法对其执行任何方法。
这就是为什么你认为你得到一个字符串,你已经实现了来自NSObject protocol的description
属性。当您使用%@
参数记录对象时,您将获得此属性的结果,该属性是一个字符串。
所以看看你的代码:
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对象确实实现了{{1}方法(因为它是一个公共财产)所以你得到了一个年龄。
另一种做法:
age
为什么我这样做?
首先,我从数组中获取firstObject并将其放入一个类型变量中。这更安全,好像索引0处没有对象(即数组为空),那么您不会让应用程序崩溃。 NSInteger age;
Person *person = self.people.firstObject;
if (person) {
age = person.age;
} else {
age = NSNotFound;
}
会在firstObject
上返回第一个对象(如果存在),如果它不存在的话。
其次,只有从数组中正确提取了人物,才能将年龄分配给nil
变量。您应该更喜欢NSInteger
超过NSInteger
(以及int
超过CGFloat
)的特定类型,因为它们在32位或64位运行时将使用正确大小的变量`systems。
第三,如果无法创建人员,我会为该年龄分配float
的值。这是一个非常大数字的typedef,可以与之比较。只是在年龄时返回0并不足以告诉你有错误。此人可以年龄为0.使用此代码,您可以使用以下代码测试年龄:
NSNotFound
这有多大意义吗?并不是的。当您开始编写真实的复杂应用程序时,这种防御性编程将自然而然地呈现给您。数组可以是空的,您的数据可能会被错误地创建,等等。编写优雅地处理这些可能性的代码是编程的真正技能。不幸的是,它有点啰嗦,你在网上找到的大多数教程都向你展示了简单,快乐的道路。
我希望这可以让您更好地了解您的代码正在做什么,以及您在编写健壮的代码时可以做些什么。