在 Core Data 中检测字符串或整数

Posted

技术标签:

【中文标题】在 Core Data 中检测字符串或整数【英文标题】:Detect string or integer in Core Data 【发布时间】:2011-12-11 21:03:04 【问题描述】:

我已经从 Core Data Books 示例中将一些 Core Data 支持内置到我的应用程序中。该示例使用日期和字符串。但是,我尝试添加添加和编辑整数值的功能。

//If the value is a string
if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) 
        textField.hidden = NO;
        datePicker.hidden = YES;
        textField.text = [editedObject valueForKey:editedFieldKey];
        textField.placeholder = self.title;
        [textField becomeFirstResponder];
    
    //If the value is a number
    else 
        textField.hidden = NO;
        datePicker.hidden = YES;
        textField.text = [[editedObject valueForKey:editedFieldKey] stringValue];
        textField.placeholder = self.title;
        [textField becomeFirstResponder];
    

第一个 if 语句是示例代码(没有检查它是否为字符串,我添加了它),并且我添加了 else 语句以在它不是字符串而是整数时运行。它可以工作,但是现在当我编辑一个字符串时,它会跳过 if 语句,所以这行:if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) 无法以某种方式工作。

如果您查看 Apple 的 CoreDataBooks 示例,我的代码是相同的,只是我添加了一个采用整数 16 的字段。

编辑

在第一个 if 语句上设置断点并在控制台中返回 po [editedObject valueForKey:EditedFiledKey] 时,我得到:Can't print the description of a NIL object.

我认为这是因为它是在制作对象之前?这发生在视图出现时(视图输入新字符串)。

这是在按下保存按钮时运行此代码:

- (IBAction)save 

    // Set the action name for the undo operation.
    NSUndoManager * undoManager = [[editedObject managedObjectContext] undoManager];
    [undoManager setActionName:[NSString stringWithFormat:@"%@", editedFieldName]];

    // Pass current value to the edited object, then pop.
    if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) 
        [editedObject setValue:textField.text forKey:editedFieldKey];
    
    else 
        [editedObject setValue:[NSNumber numberWithInteger:[[textField text] integerValue]] forKey:editedFieldKey];
    

    [self.navigationController popViewControllerAnimated:YES];

当它运行时,它会跳过第一个 if 语句并运行 else 语句,然后崩溃并显示错误:Unacceptable type of value for attribute: property = "firstName"; desired type = NSString; given type = __NSCFNumber; value = 0.

firstName 是我的数据模型中的字符串属性。我猜是因为第一个 if 语句失败,它会向前推进一个整数?我真的不确定。

【问题讨论】:

editedObject 来自哪里?也许该值不是字符串。你应该在那行代码上设置一个断点,然后运行po [editedObject valueForKey:editedFieldKey] 看看它是什么。 检查我的编辑,我发布了一些结果。 【参考方案1】:

好的,所以基于调试器中的nil 值,让我解释一下发生了什么。在 Objective-C 中,发送到nil 对象的任何消息都将简单地什么都不做,然后返回nil(恰好与0falseNO 具有完全相同的内存值)。

所以你正在这样做:

if ([[editedObject valueForKey:editedFieldKey] isKindOfClass:[NSString class]]) 

如果editedObjectnil,那么valueForKey 将不执行任何操作并返回nil。然后你将isKindOfClass 发送到nil,它也不会执行任何操作并返回nil。在 if 语句中,nil 将评估为 NO,将您发送到 else 语句。

您在哪里执行此操作:

textField.text = [[editedObject valueForKey:editedFieldKey] stringValue];

editedObjectnil,级联到stringValue 返回nil,因此您尝试将文本字段的值设置为nil,这是无效的并且会导致您的应用崩溃。

解决方案是重组代码以检查nil。以下是我将如何编写您的代码:

// don't do anything for a nil value note this will detect editedObject being nil, or the result of valueForKey: being nil.
if (![editedObject valueForKey:editedFieldKey]) 
  return;


// figure out the string value
NSString *textFieldValue = [editedObject valueForKey:editedFieldKey];
if ([textFieldValue isKindOfClass:[NSNumber class]]) 
  textFieldValue = [(NSNumber *)textFieldValue stringValue]


// update the text field
textField.hidden = NO;
datePicker.hidden = YES;
textField.text = textFieldValue;
textField.placeholder = self.title;
[textField becomeFirstResponder];

【讨论】:

认为这可行,很有意义。我会保留该代码,因为它看起来更合乎逻辑。但是,我仍然遇到同样的崩溃和错误。【参考方案2】:

我用更多的 Core Data 应用解决了同样的问题。我还调整了 Core Data Books 应用程序。如果您注意到,在原始应用程序中,他们使用 BOOL 变量 (editingDate) 来决定是否显示日期选择器。我创建了第二个 BOOL 变量 ('editingTextView`) 并根据需要编辑的内容更改这些 BOOL 变量。它可能不是最有效的方法,但它很容易编程,并且很容易遵循 Core Data Books 中已有的内容。

【讨论】:

以上是关于在 Core Data 中检测字符串或整数的主要内容,如果未能解决你的问题,请参考以下文章

实际上,Core Data 如何检测冲突?

如果Core Data count / fetch请求中的实体名称错误,如何避免崩溃?

如何将字符串保存到Core Data Swift

循环或映射Core Data数组以获取对象的每个出现

在 pig 中转储一个字符串或一个(字符串,整数)元组

在motionEnded中检测# of Core Data对象:?