NSManagedObject - 如何获取属性的类型

Posted

技术标签:

【中文标题】NSManagedObject - 如何获取属性的类型【英文标题】:NSManagedObject - How to get the type of the property 【发布时间】:2010-12-13 01:00:06 【问题描述】:

我正在尝试将 json 字符串直接解析为托管对象。 json 字符串包含所有字符串,但我的 Entity 有 Date 对象。

如果这是我的 json 字符串


"name":"John",
"dob": "12/12/2008",
etc...

这是我的实体 Person:

name : NSString
dob: Date
etc...

我想通过遍历 Json dict 的键来直接解析该 json,并将值设置为我实体的匹配键:

Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];

for (NSString *key in keys) 

 [aPerson setValue:[jsonDict valueForKey:key] forKey:key];


这仅在我的所有实体的属性都是 NSString 时才有效。

如何获取实体属性的类型/类以便能够设置各种类型?

例如。 如果键 = @"dob" 如何获取 aPerson.dob 的类型/类?

所以我的代码看起来像:

Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];

for (NSString *key in keys) 
    if([[aPerson objectForKey:key] isKindOfClass:[NSDate class]])
    
       // Create an NSDate object
    else
       [aPerson setValue:[jsonDict valueForKey:key] forKey:key];
    

谢谢

更新:

好的,我尝试使用 isKindOfClass,结果如下:

// for key = @"name" 
// aPerson.name is NSString
[[aPerson valueForKey:key] isKindOfClass:[NSString class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE

// for key = @"age"
// aPerson.age is NSNumber
[[aPerson valueForKey:key] isKindOfClass:[NSNumber class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE

// for key = @"dob"
// aPerson.dob is NSDate
[[aPerson valueForKey:key] isKindOfClass:[NSDate class]] => FALSE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => FALSE

怎么样? @dynamic dob 和 NSDate,是 notOfClass NSDate!

请告诉我我错过了什么!

【问题讨论】:

除了我下面的答案之外,您可以使用 if ([key isEqualToString:"dob"]) // 创建 NSDate 对象... 感谢 Rog,但我希望使解析更加动态,只获取实体属性的类型,而不必知道密钥的名称,即。 “多布” 是的,所有公平点。这是未经测试的使用if ([[movie valueForKey:key] isKindOfClass:[NSDate class]]) 我试过了,但由于某种原因,我的 NSDate 属性没有被识别为 kindOfClass NSDate!正如更新中发布的那样。感谢您的帮助。 返回的 dob 是什么? NSNull 还是别的什么? 【参考方案1】:

我知道,这是一个迟到的答案,但是当我今天正在寻找一个好的解决方案时...... 这是我现在使用的:

NSEntityDescription * myEntity = [object entity];
NSDictionary * attributes = [myEntity attributesByName];
if ([[[attributes objectForKey:key] attributeValueClassName] isEqualToString:@"NSDate"]) 
    // this type is NSDate
                        

希望这会有所帮助:)

【讨论】:

【参考方案2】:

您可以将您的 JSON 字符串转换为 NSDate,然后将其分配给您的 NSManagedObject,或者您可以在您的 Person 类中创建一个自定义设置器,它接受一个 NSString 并返回 NSDate。这是一个例子:

- (NSDate*)convertStringToDate:(NSString*)dateString   
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    // this is imporant - we set our input date format to match our input string
    // if format doesn't match you'll get nil from your string, so be careful
    [dateFormatter setDateFormat:@"d MMMM yyyy"];
    NSDate *dateFromString = [dateFormatter dateFromString:dateString];
    [dateFormatter release];
    return dateFromString;

【讨论】:

感谢 Rog,但我仍然需要知道何时应该将字符串转换为日期。我需要知道 person.xx 中 xx 的类型,才能动态创建它们的对象。例如。 person.dob、person.loginDate 等...如果我能分辨出它们都是 NSDate 属性,那么我可以从该 json 字符串中创建一个 NSDate。 不一定。您可以传递 (id) 而不是 NSString,然后在您的 setter 中使用 isKindOfClass 进行条件评估。 试过了,问题是它创建了一个无限循环,因为我需要通过它的设置器 self.dob 来设置 dob,它是一个动态属性。 一切都好,我能够实现动态属性的设置器,现在它工作正常。谢谢你的帮助。我已经发布了解决方案。【参考方案3】:

非常感谢 Rog,让我朝着正确的方向前进,我最终覆盖了我的 setter,如下所示:

-(void)setDob:(id)value

    [self willAccessValueForKey:@"dob"];
    if ([value isKindOfClass:[NSString class]]) 
        [self setPrimitiveValue:[DateFormatter dateFromString:value] forKey:@"dob"];
    else
        [self setPrimitiveValue:value forKey:@"dob"];
    
    [self didChangeValueForKey:@"dob"];

现在一切都很好,而不是 1000 行代码解析,全部在 3 内完成! 不错!

【讨论】:

不错的解决方案,干净整洁。感谢发布!

以上是关于NSManagedObject - 如何获取属性的类型的主要内容,如果未能解决你的问题,请参考以下文章

获取 NSManagedObject 的属性作为 NSDictionary

如何计算/迭代 NSManagedObject 具有的所有属性?

将获取的 NSManagedObject 分配给属性

Swift 从实体(核心数据)获取特定的 NSManagedObject

如何将其他 NSManagedObjects 存储为 NSManagedObject 的属性

观察 NSManagedObject 属性的变化:如何避免循环?