简体   繁体   中英

Create a Swift class in Objective-C by name

I am working through an issue where I have a mixed code base and creation paradigm where a single class (in Objective-C) has the names of all classes I can create and use.

Previously the code base was completely Objective-C so when I had a name of a class I needed to create I simply went:

- (Class)sourceClass {
    return NSClassFromString(sourceClassName);
}

Now I have to support returning Swift classes. I have tried using the bundle name with a dot in front of the class. This did not work (returns nil):

NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *classStringName = [NSString stringWithFormat:@"%@.%@", appName, sourceClassName];
return NSClassFromString(classStringName);

I also tried some crazy formatting I found online, also returned nil:

NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *classStringName = [NSString stringWithFormat:@"_TtC%lu%@%lu%@", appName.length, appName, sourceClassName.length, sourceClassName];
return NSClassFromString(classStringName);

Trying to mix and match Objective-C and Swift using runtimes like this is going to be very problematic. For a start all of your Swift classes and any properties or functions you need will have to be exposed to Objective-C. Next as you've discovered there's the naming issues. The best way to check the names will be to do a quick classes dump of all the classes in the project. Here's some bit's of code from one of my projects that scans a bundle for classes:

 // Get a reference to your main bundle or the bundle where the Swift classes are.
CFBundle * bundle = //....
NSURL *executableURL = (NSURL *) CFBridgingRelease(CFBundleCopyExecutableURL(bundle));
if (executableURL) {

    STLog(self, @"Scanning executable: %@", executableURL);

    unsigned int count = 0;
    const char** classes = objc_copyClassNamesForImage(executable, &count);
    STLog(self, @"Found %i classes", count);
    if (count == 0) {
        return;
    }

    for(unsigned int i = 0;i < count;i++) {
        Class nextClass = objc_getClass(classes[i]);
        // Print the class name here
    }
}

Using something like that should help you to ensure you can see the classes you're after and get their names correct.

Finally though, what concerns me about the description of your code is the concept of using a single class as a factory for everything else. This sounds like an extremely limiting and problematic design. I'd suggest you take a moment to sit back and reassess if it's really a good idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM