自定义对象将NSDictionary作为类型返回

时间:2017-06-14 11:24:33

标签: ios objective-c xcode object

我的对象 CCategory.h

    @interface CCategory : NSObject

@property(strong, nonatomic) NSNumber * _Nonnull categoryId;
@property(strong, nonatomic) NSNumber * _Nonnull originalId;
@property(strong, nonatomic) NSString * _Nonnull name;
@property(strong, nonatomic) NSString * _Nonnull type;
@property(nonatomic, strong) CCategory * _Nullable  parent;
@property (nullable, nonatomic, retain) NSOrderedSet<CCategory *> *children;



- (instancetype _Nonnull )initWithId:(NSNumber *_Nullable)categoryId
               andOriginalId:(NSNumber *_Nullable)originalId
                   andName:(NSString *_Nonnull)name
                   andType:(NSString *_Nonnull)type
                   andParent:(CCategory *_Nullable)parent
                   andChildren:(NSOrderedSet<CCategory *> *_Nullable)children NS_DESIGNATED_INITIALIZER;
@end

CCategory.m

@implementation CCategory


- (instancetype)init {
    return [self initWithId:0 andOriginalId:0 andName:@"" andType:@"" andParent:nil andChildren:nil];
}

- (instancetype)initWithId:(NSNumber *)categoryId
               andOriginalId:(NSNumber *)originalId
                   andName:(NSString *)name
                   andType:(NSString *)type
                    andParent:(CCategory *)parent
                   andChildren:(NSOrderedSet<CCategory *> *)children {

    self = [super init];
    if (self) {
        self.categoryId = categoryId;
        self.originalId = originalId;
        self.name = name;
        self.type = type;
        self.parent = parent;
        self.children = children;

    }
    return self;
}

@end

这是我检查班级类型的方法:

        CCategory * firstItem = [itemsArray objectAtIndex:0];

        CCategory *child = [firstItem.children objectAtIndex:0];

        NSString *className = NSStringFromClass([child class]);

        NSLog(@"First Item is: %@", className);

firstItem返回类型CCategory,子类返回类型NSDictionary

从数据库对象接收后包含所有数据,但由于某种原因,子节点是NSDictionary类型,而不是CCategory类类型。这是为什么?如何让孩子输入CCategory

1 个答案:

答案 0 :(得分:1)

因为你声明某些类的某个对象并不意味着它是正确的类。 如果您编写例如

NSArray *array = [@[@"Hello"] firstObject]; 

array实际上是NSString个对象。

因此,当你解析你的回复并从我猜的CCategory对象创建你的NSDictionary对象时。
这就是为什么children似乎实际上是NSOrderedSet NSDictionary而不是CCategory个对象的原因。

一种可行的方法是为孩子们递归initWithId:andOriginalId:andName:andType:andParent:andChildren:

而不是self.children = children;

NSMutableOrderedSet *childrenSet = [[NSMutableOrderedSet alloc] init]; 
for (NSDictionary *aChildDict in [children array])
{
    CCategory *aChild = [CCategory alloc] initWithId:aChildDict[keyWhereThereIsID], etc.] 
    [childrenSet addObject:aChild];
}
self.children = childrenSet;

但是在init方法中设置它更像是一种黑客行为,因为它说children应该是NSOrderedSet<CCategory *> *

所以由你决定,要么重新命名方法以清楚它的作用,也许接受NSOrderedSet<NSDictionary *> *代替children,之前解析它,创建另一个等等。

一种可能的懒惰选择是:

重命名为andChildren:(NSOrderedSet *)children

NSMutableOrderedSet *childrenSet = [[NSMutableOrderedSet alloc] init]; 
for (id *aChildObject in [children array])
{
    CCategory *aChild = nil;
    if ([aChildObject isKindOfClass:[NSDictionary class]]) //Need parsing
    {
        NSDictionary *aChildDict = (NSDictionary *)aChildObject;
        aChild = [CCategory alloc] initWithId:aChildDict[keyWhereThereIsID], etc.];
    }
    else if ([aChildObject isKindOfClass:[CCategory class]]) //Already a CCategory Object
    {
        aChild = (CCategory  *)aChildObject;
    }
    else 
    {
        NSLog(@"Ooops, child of wrong class: %@", NSStringFromClass([aChildObject class]);
    }

    if (aChild) { [childrenSet addObject:aChild]; }
}
self.children = childrenSet;