您可以使用在运行时class_setSuperclass
更改超类。MyUUID
由于类型安全,这种方法在 Swift 中是非法的,但您仍然可以在 Objective-C 中这样做。
根据您的实际目标,您也许可以改用CFUUIDRef。
根据要求,这是该方法的示例class_setSuperclass
。只需将其放入一个新的单视图项目中即可。
#import <objc/runtime.h>
@interface MyUUID : NSUUID
- (void) UUIDWithHello;
@end
@implementation MyUUID
- (void) UUIDWithHello {
NSLog(@"Hello! %@", self.UUIDString);
}
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Make a UUID that you want to subclass
NSUUID *uuid = [[NSUUID alloc] init];
NSLog(@"Initial UUID: %@", uuid.UUIDString);
// Ignore deprecation warnings, since class_setSuperclass is deprecated
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
// Change MyUUID to inherit from the NSUUID's hidden subclass instead of NSUUID
class_setSuperclass([MyUUID class], [uuid class]); // [uuid class] is __NSConcreteUUID
// Turn deprecation warnings back on
#pragma GCC diagnostic pop
// Make a new myUUID and print it
MyUUID *myUuid = [[MyUUID alloc] init];
[myUuid UUIDWithHello];
}
@end
请注意,这有点危险。如果任何秘密子类NSUUID
有额外的实例变量,它将需要更多的内存,这[MyUUID alloc]
不会请求。当某些东西请求这些实例变量时,这可能会导致稍后崩溃。
为了解决这个问题,您可以MyUUID
像这样实例化您的实例:
NSLog(@"Initial UUID's class: %@", NSStringFromClass(uuid.class));
Class topSecretUUIDSubclass = uuid.class; // __NSConcreteUUID
MyUUID *myUuid2 = [[topSecretUUIDSubclass alloc] init];
[myUuid2 UUIDWithHello];
object_setClass(myUuid2, [MyUUID class]);
基本上这将制作myUuid2
a__NSConcreteUUID
然后将其更改为 a MyUUID
。但是,这仅在MyUUID
不添加任何实例变量时才有效。
如果MyUUID
确实需要添加自己的实例变量,则需要重写+alloc
以为这些实例变量提供额外的内存,使用class_createInstance()
.