1

I have a singleton object which has some properties and I would like to set all these values to nil or "NO" based on the type of properties. One way to do it is to write a reset method in which I set all these properties to nil myself like below..

This may even have instance variables which are also to be cleared.

-(void)reset
{
    //Properties
    self.lastLoggedInUser = nil;
    self.localMasterDownload = NO;
    self.isFirstLaunchDone = NO;
    self.lastArchvingDate = nil;
    self.archivingDueDate = nil;
    self.dbEncryptionKey = nil;
    self.checkInDone = NO;
    //Instance variables
    _isPostionModuleExtandedMode = NO;
    _isPassengerModuleExtandedMode = NO;
}

But I am looking for a more generic and efficient method of doing this..

Any help is appreciated.

Thanks.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Ankit Srivastava
  • 12,347
  • 11
  • 63
  • 115
  • What you posted is the most efficient way. Any approach that dynamically processes the objects's properties will be far less efficient. – rmaddy Aug 13 '14 at 07:04
  • @rmaddy Is there any way I can use the objective-c runtime to my use..? Say If I have a lot properties and I dont want to write so much code.. instead I want write a method in the base class instead which will clear this for me...? – Ankit Srivastava Aug 13 '14 at 07:05
  • 1
    I've never done what you want but start by looking at http://stackoverflow.com/questions/11774162/list-of-class-properties-in-objective-c – rmaddy Aug 13 '14 at 07:10
  • The dynamic nature of Objective-C makes this very difficult to implement. What you really need is a brute force aproach. You'd have to every possible property name from aaaaaaaaaaaaaaaaaa to zzzzzzzzzzzzzzzzzzz (that would be hundreds of trillions of possible property names) and test each one with `respondsToSelector:`. Class introspection doesn't work, because there could be additional property names that are not exposed. For example NSManagedObject gets it's properties from the `mom` file, not from anything inherent in the class. Alternatively, just manually reset everything as you're doing. – Abhi Beckert Aug 13 '14 at 07:29
  • 1
    Is there some reason you can't destroy and re-allocate the instance? – jscs Aug 13 '14 at 14:56
  • @JoshCaswell Initialisation of the singleton is a heavy task. – Ankit Srivastava Aug 14 '14 at 08:17

2 Answers2

1

This gets you your classes properties, from there you just have to convert the key string into something that trys to nil the property. Its possible I think.

NSMutableDictionary *dict = [NSMutableDictionary dictionary];

unsigned count;
objc_property_t *properties = class_copyPropertyList([self class], &count);

for (int i = 0; i < count; i++) {
    NSString *key = [NSString stringWithUTF8String:property_getName(properties[i])];
    if([self valueForKey:key]!=nil){
        [dict setObject:[self valueForKey:key] forKey:key];


    }else{
        [dict setObject:@NO forKey:key];

    }
}

free(properties);

return [NSDictionary dictionaryWithDictionary:dict];
0
- (void) resetProperties {
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList([self class], &outCount);
    for(i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
        const char *propName = property_getName(property);
        if(propName) {
            NSString *propertyName = [NSString stringWithCString:propName encoding:[NSString defaultCStringEncoding]];

            id value = [self valueForKey:propertyName];
            NSLog(@"[berore]XXXresetProperties => [%@] %@=%@", [propertyName class],propertyName, value);

            /* You can add some other checks */
            if ([value isKindOfClass:[NSNumber class]]) {
                [self setValue:[NSNumber numberWithInteger:0] forKeyPath:propertyName];
            }
            if ([value isKindOfClass:[NSString class]]) {
                [self setValue:nil forKeyPath:propertyName];
            }
            if ([value isKindOfClass:[NSDictionary class]]) {
                [self setValue:nil forKeyPath:propertyName];
            }

            id valueRes = [self valueForKey:propertyName];
            NSLog(@"[after]XXXresetProperties => [%@] %@=%@\n---\n", [propertyName class],propertyName, valueRes);
        }
    }
    free(properties);
}

You can get it there: https://github.com/energy6x6/iOS-clear-all-property-in-class

Anton Petrusha
  • 1,881
  • 2
  • 11
  • 9