check id isKindOfType CFType

时间:2011-11-17 13:39:03

标签: objective-c core-data plist

简要说明:如何在运行时确定id是否为CFType

我正在实现dynamic core data attributes并且在ExtendedManagedObject的willSave方法中我想检查id值是否为CFType以将其存储到plist文件中。

如果我试图保存为UIImage,那就是没有免费的CF桥接(apple docs),我收到错误:

2011-11-17 17:16:25.294 [490:707]保存扩展数据时出错:属性列表对格式无效(属性列表不能包含'CFType'类型的对象)

我可以用某种方法检查它,或者我必须自己实现(只是来自docs的isKindOfClass)?

我不想在NSManagedObject子类中实现访问器,我不知道我将从实体属性中获得多少URL。问题是关于运行时的动态扩展属性。

- (void)willSave
{
NSDictionary *changes = [self valueForKey:@"extendedChanges"];
if (changes!=nil) {
    // merge changes into snapshot
    NSMutableDictionary *dict = [[self extendedSnapshot] mutableCopy];
    NSEnumerator *e = [changes keyEnumerator];
    NSString *key;
    while (key=[e nextObject]) {
        id value = [changes objectForKey:key];



        if (value==[NSNull null])
            [dict removeObjectForKey:key];
        else if (#ugly and I'm not shure is thread safe **else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]] || [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]])**)
            [dict setObject:value forKey:key];
    }

    // archive as binary plist
    NSData *data = nil;
    if ([dict count]>0) {
        NSString *error=nil;
        data = [NSPropertyListSerialization dataFromPropertyList:dict 
                                                          format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error];
        if (error!=nil) {
            NSLog(@"Error saving extended data: %@", error);
            [error release];
        }
    }
    [dict release];
    [self setPrimitiveValue:data forKey:@"extendedData"];
}
[super willSave];
}

2 个答案:

答案 0 :(得分:7)

这是解决问题的错误方法。您引用的博客文章将扩展属性保存为序列化plist。 plist只能包含以下类型的对象,如official doc

中所述
  

NSArrayNSDictionaryNSDateNSDataNSStringNSNumber

其他课程是不允许的。不要将任何其他类的对象添加到以这种方式扩展的属性中。

此外,将图像文件保存在CoreData数据库中并不是一个好主意,一般来说,在官方文档中阅读On Blobs。而是将UIImage保存在文件中,并在CoreData数据库中写入文件路径。


如果您只有一个未保存到数据库的瞬态属性,您甚至不必经历创建扩展属性的麻烦。只需将其添加为NSManagedObject的子类的属性:

@interface MyManagedObject: NSManagedObject {
}
@property(retain, nonatomic) UIImage* thumbnail;
@property(retain, nonatomic) NSDictionary* thumbnailDictionary;
@end

未在CoreData模型中添加thumbnail。然后在@synthesize文件中执行相应的.m。以这种方式添加到托管对象的属性只是没有保存。

如果您想保留未知数量的缩略图,可以将NSDictionary(或NSArray)包含UIImage*个。


如果您确实希望从CFType获取NSObject*,请执行以下操作:

NSObject* x= ...;
CFTypeID typeID=CFGetTypeID((CFTypeRef)x);
if(typeID != CFStringGetTypeID() &&
   typeID != CFDateGetTypeID() &&
   typeID != CFDataGetTypeID() &&
   typeID != CFDictionaryGetTypeID() &&
   typeID != CFArrayGetTypeID()  ) {
       ... it's a non-plistable type ...
}

丑陋的if子句就在那里,因为没有公共函数可以为你提供一个非桥接的Objective-C对象的CFTypeID。 阅读CFType参考。但我不建议这样做。

答案 1 :(得分:0)

尝试以UIImage格式存储图片也会导致“属性列表无法包含CFType类型错误的对象。最佳方法是将UIImage转换为NSData之前写给pList。