Unheilig
Unheilig

Reputation: 16292

Objective-C class type error

I have a view created like the following:

Class MyClass = NSClassFromString(className);

UIView *myView = [[MyClass alloc] initWithFrame:..];

The above works, but I was hoping to know if it is possible to replace UIView and create the instance like this:

MyClass *myView = [[MyClass alloc] initWithFrame:..];

? It gives an error:

use of undeclared identifier myView

Why can I use it like this? And how can I use it this way?

So I then tried:

const char *class = [MyClass UTF8String];
Class MyClass = objc_allocateClassPair([UIView class], class, 0);
MyClass *myView = [[MyClass alloc] initWithFrame:..];

But this also doesn't work. It doesn't give the above warning but would when I subsequently do:

myView.backgroundColor = ....;

use of undeclared identifier myView

How can I be able to use the class type dynamically? And what is the difference between:

NSClassFromString(className);

and:

objc_allocateClassPair

?

Upvotes: 1

Views: 230

Answers (2)

Robert J. Clegg
Robert J. Clegg

Reputation: 7360

Okay - so it seems when you do this:

Class MyClass = NSClassFromString(className);

You're setting MyClass up as a UIView since className is a subclass of UIView

Which is why when you do this:

UIView *myView = [[MyClass alloc] initWithFrame:..];

It works. You're allocating and initialising myView as a UIView object. No problems here.

When you do this:

MyClass *myView = [[MyClass alloc] initWithFrame:..];

You get a crash.

Reason:

Here you're allocating and initialising myView as a MYClass object. Which is not a UIView since MyClass has no idea what initWithFrame means and thus, doesn't respond to it - crash. In fact - that code shouldn't even compile.

You're going about this in an ass about face kinda way. You're trying to convert a class that is not a subclass of UIView into a class that knows what UIView is and is able to respond to its messages.

AlieN's answer would solve the compiler error - since id is "Any type of class" and with introspection it would work. However, I don't like this method of solving your issue - its a hack.

Why not make MyClass a subclass of UIView and allow it to receive messages. Because, that's how you're trying to use it... as a UIView object.

As I am not sure what MyClass's actual job is, its difficult to solve the issue another way, without the need to subclass.

Can you elaborate on what MyClass's job is? (It seems like you're trying to give it more than one job here)

Edit

From your comments below - you're doing this:

Class MyClass = NSClassFromString(className);
MyClass *myView = [[MyClass alloc] initWithFrame:..];

If so the crash is simple to explain:

Its crashing because the second line of the above code creates a new instance of MyClass which is just a standard Class (Not a subclass of UIView) your first line become redundant.

Upvotes: 2

AlieN
AlieN

Reputation: 543

Use

Class MyClass = NSClassFromString(className);
id myView = [[MyClass alloc] initWithFrame:..];
[myView setBackgroundColor:[UIColor redColor]];

But it will compile even if you will try to

[myView addObject:...];

And will crash.

Upvotes: 1

Related Questions