LeTadas
LeTadas

Reputation: 3556

Custom object returns NSDictionary as type

my 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

This is how I check class type:

        CCategory * firstItem = [itemsArray objectAtIndex:0];

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

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

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

firstItem returns type CCategory, child returns type NSDictionary

After receiving from database object contains all data, but children for some reason is the NSDictionary type, not CCategory class type. Why is that? and how can I make children type CCategory?

Upvotes: 0

Views: 79

Answers (1)

Larme
Larme

Reputation: 26036

Because you declare some object of some class doesn't mean that it's of the correct class. If you write for instance

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

array will be in fact a NSString object.

So, when you parse your response and create your CCategory object from what I guess a NSDictionary object.
That's why children seems to be in fact an NSOrderedSet of NSDictionary and not of CCategory objects.

A possible way to do it, is to call recursively initWithId:andOriginalId:andName:andType:andParent:andChildren: for the children.

So instead of 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;

But that's more of a hack to set it like that in the init method, because it says children should be NSOrderedSet<CCategory *> *.

So it's up to you, to either rename the method to be clear of what it does and maybe accept a NSOrderedSet<NSDictionary *> * for children instead, parse it before, create another one, etc.

One possible lazy option is to do that:

Rename to 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;

Upvotes: 1

Related Questions