Objective-C: How to change the class of an object at runtime?

左心房为你撑大大i 提交于 2019-11-26 14:01:38

问题


I tried to answer Using a UITableView subclass with a UITableViewController with ISA Switching like so:

self.tableView->isa = [MyTableView class];

But, I get the compile error: Instance variable 'isa' is protected.

Is there a way to get around this? And, if so, is it safe to do?

I'm asking because @AmberStar's answer to that question seems slightly flawed. (See my comment.)


回答1:


If your tableview class provides ANY storage this will break. I would not recommend the path you're going down. But the correct method would be to use object_setClass(tableView, [MyTableView class]).

Please make sure this is really what you want.

Here is a small code-sample showing how this is a horrible idea.

#import <objc/runtime.h>

@interface BaseClass : NSObject
{
    int a;
    int b;
}
@end

@implementation BaseClass

@end

@interface PlainSubclass : BaseClass
@end

@implementation PlainSubclass
@end

@interface StorageSubclass : BaseClass
{
@public
    int c;
}
@end

@implementation StorageSubclass
@end



int main(int argc, char *argv[])
{
    BaseClass *base = [[BaseClass alloc] init];
    int * random = (int*)malloc(sizeof(int));
    NSLog(@"%@", base);

    object_setClass(base, [PlainSubclass class]);
    NSLog(@"%@", base);

    object_setClass(base, [StorageSubclass class]);
    NSLog(@"%@", base);
    StorageSubclass *storage = (id)base;
    storage->c = 0xDEADBEEF;
    NSLog(@"%X == %X", storage->c, *random);
}

and the output

2011-12-14 16:52:54.886 Test[55081:707] <BaseClass: 0x100114140>
2011-12-14 16:52:54.889 Test[55081:707] <PlainSubclass: 0x100114140>
2011-12-14 16:52:54.890 Test[55081:707] <StorageSubclass: 0x100114140>
2011-12-14 16:52:54.890 Test[55081:707] DEADBEEF == DEADBEEF

As you can see the write to storage->c wrote outside the memory allocated for the instance, and into the block I allocated for random. If that was another object, you just destroyed its isa pointer.




回答2:


The safe way is to create a new instance.

Swapping isa is not safe - you have no idea what the memory layout of a class is or what it will be in the future. Even moving up the inheritance graph is really not safe because objects' initialization and destruction would not be performed correctly - leaving your object in a potentially invalid state (which could bring your whole program down).



来源:https://stackoverflow.com/questions/8512793/objective-c-how-to-change-the-class-of-an-object-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!