Bryan P
Bryan P

Reputation: 4202

Passing a Class as parameter and instantiating an object using this class

Is this possible, I searched the net and found no answer to this. My senior also said that this is not possible.

I'm trying to add this as a category, so I want to extract 4 types of objects out of it, all of them uses the same code, it's just the classes that differ so I thought of this:

- (NSDictionary *) getObjectsOfClass:(Class)class
{

    NSMutableDictionary *objDict = [NSMutableDictionary dictionary];

    [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:class]) {

            /*
            Is there a way to do this?
            class *label = (class *)obj;

            */


        }
    }];

    return objDict;
}

So is there a way to make this work? It's ugly to see 4 functions with almost the same codes, you agree right?

Upvotes: 3

Views: 886

Answers (4)

sergio
sergio

Reputation: 69027

You can instantiate your class argument like this:

id newInstance = [class new];

What you cannot syntactically do is using class * as a way to tell the compiler which type your local variable is. But this is also not required, thanks to Objective C dynamics typing capabilities.

In other words, there is not reason to cast to class (and you cannot do that; class is only known at runtime, casting has effect at compile time).

EDIT:

If you know a base class common to all of your classes, e.g. UIView, then you could do:

UIView* newInstance = obj;

then access its properties, e.g.:

if (newInstance.tag ==…)

Or you could use message sending instead of properties and do:

if ([obj tag] == ...)

Upvotes: 2

Because of you said "But I'm adding it to uiview, to get the textfields, labels, pickerviews etc, so that I can just call [self.view getObjectsOfClass:[UILabel class]"

For this code

  [self.view getObjectsOfClass:[UILabel class]];

it will return all its UILabel immediate children of it.

- (NSMutableArray *) getObjectsOfClass:(Class)class
{

    NSMutableArray *objArray = [NSMutableArray array];

    [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {


        // All visible things are inherited from UIView. Tag property is belongs to UIView
        // UILabel are inherited from UIView
        if ([self isKindOfClass:[UIView class]] && [obj isKindOfClass:class]) {

            UIView *aView = (UIView*)obj;

            if (aView.tag == 100) {

                //This is the view with tag 100

            }

            [objArray addObject:obj];


        }
    }];

    return objArray;
}

Upvotes: 2

Balram Tiwari
Balram Tiwari

Reputation: 5667

What about passing class name as string & creating object out of it. May be like this

    -(NSArray *)arrayOfObjectsForClass:(NSString *)className{

        NSMutableArray *objectArray = [[NSMutableArray alloc]init];
        CGFloat yAxis = 10;
        for(int i =0;  i<5; i++){
           id object = [[NSClassFromString(className) alloc]initWithFrame:CGRectMake(0, yAxis, 100, 50)];
           [object setTitle:[NSString stringWithFormat:@"Button %d", i+1]];
           [objectArray addObject:object];
           yAxis+= 60;
         }

       return objectArray;
    }

Upvotes: 4

Apurv
Apurv

Reputation: 17186

If all of them are derived from a common base class, you can cast them into that common base class. If few functions are not available then create a category of that common base class and add those common functions into it. This will allow you to have single code block rather than 4 different one.

Upvotes: 2

Related Questions