Objective-C: instantiating a Class object

My company wants to be insure that if my Objective-C to Swift conversions fail in anyway, that the app can revert to using the older Objective-C code. By using a remotely controllable flag, the app can switch which code runs as, both are compiled into the app.

Essentially, I create a protocol that describes the original class, then both classes (with a "s" or "o" appended to them) conform to the protocol.

Protocol: Object Objective-C class: oObject Swift class: sObject

That said, I hit one issue that I just can't seem reason out. I create a Objective-C function that returns the appropriate class:

Class<Object> classObject(void) {
    if (myFlag) {
        return [sObject class];
    } else {
       return [oObject class];
    }
}

Swift deals with this really well - I can create an initialized object using:

let object = classObject().init()

but I cannot find a way to do this in Objective-C:

Object *object = [[classSalesForceData() alloc] init];

fails with "No known class method for selector 'alloc'"

Is there a way to do this?

David

PS: my workaround is to return an allocated object:

Object *createObject(void) {
    if (myFlag) {
        return [sObject alloc];
    } else {
       return [oObject alloc];
    }
}
Answered by DTS Engineer in 827091022
Written by dhoerl in 826962022
If I add a protocol conformance to Class, it breaks

Yeah, that is a bit weird. I’m not even sure I understand what Class<MyProtocol> means in Objective-C. Remember that classes are objects, so does it mean that the class instances conform to the protocol? Or that the class itself conforms to the protocol? *shrug*

Regardless, I don’t think you need to solve that problem. Standard practice is to pass around Class and then cast the result object to id<MyProtocol>, and I don’t see any reason to deviate from that practice.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

This is a really strange way of converting an app from ObjC to Swift.

You should tell your company that you can convert one bit at a time, and that it will be tested appropriately.

Being asked to keep two versions of code working in the same app, to me, seems absolutely insane.

I’m not sure why this is failing in your setup, by the standard way to create an instance dynamically in Objective-C is this:

static id makeObject(Class cls) {
    return [[cls alloc] init];
}

This compiles just fine in Xcode 16.2.

Having said that, if there are just two choices then I’m not sure why you need to do this dynamically. You could write code like this:

static id makeObject(BOOL useNew) {
    if (useNew) {
        return [[NewClass alloc] init];
    } else {
        return [[OldClass alloc] init];
    }
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I played around with your example. If I add a protocol conformance to Class, it breaks:

static id makeObject(Class<sObject> cls) {
    return [[cls alloc] init];
}

It gets a bit more complicated, as there are several initializers for this class: that said, I could add parameters to the function and switch on those to return a properly initialized. However, returning an allocated object works well, as it can be passed to various initializers.

Can you comment on why the function above (with the protocol conformance) fails?

What to me is so interesting here is that Swift deals with this just fine! I would have expected the converse!

David

Written by dhoerl in 826962022
If I add a protocol conformance to Class, it breaks

Yeah, that is a bit weird. I’m not even sure I understand what Class<MyProtocol> means in Objective-C. Remember that classes are objects, so does it mean that the class instances conform to the protocol? Or that the class itself conforms to the protocol? *shrug*

Regardless, I don’t think you need to solve that problem. Standard practice is to pass around Class and then cast the result object to id<MyProtocol>, and I don’t see any reason to deviate from that practice.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Objective-C: instantiating a Class object
 
 
Q