gpt4 book ai didi

ios - Objective-C 框架和命名空间冲突

转载 作者:行者123 更新时间:2023-12-01 22:00:00 25 4
gpt4 key购买 nike

我们希望将 2 个版本的 iOS 应用程序放在同一个包中。这样,我们的客户可以在推送更新后恢复到旧版本。我曾希望通过将当前和以前的版本构建到框架中并在提示用户后调用适当的版本来实现这一点。

作为测试,我创建了两个框架,LibA 和 LibB,每个都包含类 Thing。

我遇到的问题是这个运行时警告......
objc[21117]: Class Thing is implemented in both /private/var/containers/Bundle/Application/0E6374C5-52FB-421F-90D6-ADC9A4C22B5D/DualBootTestApp.app/Frameworks/LibA.framework/LibA (0x102b144b0) and /private/var/containers/Bundle/Application/0E6374C5-52FB-421F-90D6-ADC9A4C22B5D/DualBootTestApp.app/Frameworks/LibB.framework/LibB (0x102ba4460). One of the two will be used. Which one is undefined.
在现实世界中,这些框架将是同一个应用程序的两个版本,因此 99% 的类名在每个版本中都是相同的。

每个框架实际上都调用了自己的 Thing 版本,但运行时警告向我表明我不能依赖这种行为。

更新

我刚刚尝试使用 Cocoa Touch 静态库。使用静态库时,我不会收到运行时警告,但始终会调用来自 LibB 的类 Thing 版本,即使调用来自 LibA 也是如此。

我开始相信某种为 objective-c 类名称添加前缀的宏可能是唯一的解决方案。大量共享代码使这成为一个严峻的前景。

有谁知道我可以隐藏类名的方法,这样只有每个框架才能看到自己的类?

有没有更好的方法将应用程序的两个版本添加到同一个包中?甚至可能吗? Appstore审核会有问题吗?

最佳答案

如果你已经将你的类变成了框架,那么恭喜你,你已经完成了最困难的部分。但是请记住,如果您的大部分应用程序代码都在一个框架中,那么有些事情可能不会像预期的那样运行。例如,任何最终调用 NSBundle.mainBundle 的代码(例如 +[UIImage imageNamed:] )可能是错误的,假设您也对 Assets 进行了版本控制。

但是让我们假设您已经成功地框架化了您的应用程序版本。

如果您想在运行时选择其中一个,则不能链接到这两个框架。相反,您需要使用 dlopenNSClassFromStringdlsym到达一个入口点。

这是一个例子:

#import <dlfcn.h>
#import "HeaderWithEntryPointMethod.h"

void pickedAppVersion(int version) {
NSString *frameworkName = [NSString stringWithFormat:@"AppV%d", version];
NSString *frameworkExecutable = [NSString stringWithFormat:@"%@.framework/%@", frameworkName, frameworkName]; // this should traverse the symlink
NSString *frameworkPath = [[[NSBundle mainBundle] privateFrameworksPath] stringByAppendingPathComponent:frameworkExecutable];
void *frameworkHandle = dlopen(frameworkPath.UTF8String, RTLD_NOW);
if (frameworkHandle != NULL) {
Class EntryPointClass = NSClassFromString(@"EntryPoint");
assert(EntryPointClass != Nil);
[EntryPointClass entryMethod];
// App framework should do everything from here
if (dlclose(frameworkHandle) != 0) {
NSLog(@"failed to close chosen app framework: %s", dlerror());
}
}
else {
NSLog(@"failed to open app framework: %@ because: %s", frameworkName, dlerror());
}
}


至于究竟是什么 EntryPoint是和 +entryMethod做,这取决于你。如果需要 C 函数入口点,请使用 dlsym而不是 NSClassFromString .

回复:App Store 评论:我想它可能会引起一两个人的注意,但只要你允许用户,尤其是评论者选择,应该没有问题。 dlopen通常用于在运行时选择性地加载框架,以简化应用程序启动和加载应用程序按需使用的功能。

关于ios - Objective-C 框架和命名空间冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60266482/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com