【问题标题】:How to run a project out of 2 embedded different project如何从 2 个嵌入式不同项目中运行一个项目
【发布时间】:2017-01-25 00:27:16
【问题描述】:

我有两个 iOS 项目,我想将其作为一个项目,并根据条件一次运行一个项目。

例如:我有 2 个名为 ProjectAProjectB 的项目。我想嵌入 ProjectA 和 ProjectB 合并为一个名为 ProjectC 的项目。 ProjectC 的条件取决于我必须运行 projectAProjectB 代码的条件。

注意:运行项目的条件将应用于运行时而不是编译时。

我怀疑这真的可能吗?我需要有关如何解决此问题的专业指导。

【问题讨论】:

  • 所以 ProjectC - 它的 ios 应用程序生成一些需要被 XCode 捕获并运行 projectA 或 ProjectB 的通知。正确的?如果我是对的,您能否提供更多详细信息,为什么需要它?两个应用程序之间的通信?
  • 我有两个不同的项目完整的项目,我想整合两个项目,以便我可以根据条件使用该项目。这是我的要求。跨度>
  • 项目 A 和项目 B 是独立应用程序,对吗?这是什么条件?它是在启动时确定的,还是期望在运行时动态发生(即用户从菜单中选择或动态更改它)。后者更难。
  • @MobileBen,它发生在运行时。
  • 这并不能真正回答我的问题。在运行时很重要。如果它只是停止发布,那么方法就大不相同了。我不清楚为什么当前的答案如此受欢迎。它真的没有回答这个问题。

标签: ios iphone ios7


【解决方案1】:

好的,所以基于阅读问题并提出一些问题......我真的不清楚为什么关于 pod 的答案会获得如此多的选票。并不能解决问题。

假设我们有现有的 ProjectA 和 ProjectB。 ProjectC 尚不存在,但希望使 ProjectC 成为 A 和 B 的“组合”,其中 A 或 B 将根据某些条件运行。运行后,应用程序将一直运行该版本,直到重新启动。

两种基本方法是将所有代码和资产组合到 ProjectC 中,或者尝试制作您加载的 A 和 B 框架。但是,对于任何一种情况,您都需要对代码库进行调整。您需要完成的工作量也是项目复杂程度的副产品。

我参与了一个项目,我们成功地完成了您对大型应用程序的要求。我们基本上通过将我们的 iPhone 和 iPad 项目结合代码/资产制作了一个“通用应用程序”。我们在运行时“启动”了适当的版本。

在你付出这样的努力之前,你需要权衡后果。我会列出一些。

  • 如果您的 A/B 依赖于 bundle id,您就会遇到问题。 ProjectC 将拥有自己的捆绑包 ID。例如,是否有任何第 3 方 API(例如 Facebook)正在使用中,您仍然希望使用它们并且看起来像 ProjectA 或 ProjectB?如果是,但它们与捆绑包 ID 相关联,您就会遇到问题。
  • 如果您使用 IAP,您的产品 ID 需要不同。因此,如果这些产品 ID 是硬编码的,那么显然 A 和 B 中的代码将需要更改。如果它们是服务器驱动的,您需要确保服务器代码并实际提供正确的产品 ID。如果预计 ProjectA 的所有者仍应拥有 ProjectC 的 IAP,这是可能的……但是成本需要根据您的规模来管理服务器端逻辑。
  • 在调试代码时需要付出多少努力?
  • ProjectA 和 ProjectB 是否仍在积极开发中?这样做可能会使这些项目以后很难维护。
  • 为此要留出多少时间?这样做很乏味且需要时间。

您可能会更成功地将 A 和 B 的源/资产合并到 C 中。换句话说,您不会将 A 或 B 的项目文件添加到 C 中。为什么?因为您需要能够轻松识别所有冲突点,然后提供解决方法。一个简单的冲突示例是AppDelegate,这是项目默认创建的。您将拥有其中的 3 个(A、B、C)。

请记住,所有方法都充满问题。如果您选择框架(无论它们是否是 Pod)并且您决定将资产放入框架包中,则必须更改代码才能访问它们,因为它们不再位于 mainBundle 中。

好的,一般准则是什么?

  • 选择一种方法(例如,组合或框架)。我将讨论结合。
  • 预先确定尽可能多的冲突。为每种类型的冲突确定您的策略。例如,要解决AppDelegate,您总是可以使用ProjectAAppDelegateProjectBAppDelegate
  • 检查Info.plist。这是其他冲突的一个很好的来源。 C 的Info.plist 将是两者的组合。
  • 想出一个处理冲突的策略。例如,我们有一个命名约定,当我们有冲突的类名时会使用。
  • 将您的 ProjectA 和 ProjectC 源代码/资产添加到 Project C 中。开始修复冲突。
  • 多喝咖啡。

您需要控制的其他关键事项之一是基于决策的切入点。如果您可以在main.m 中调用UIApplicationMain 之前做出决定,您可以执行以下操作:

    Class appDelegate;

    if (runA) {
        appDelegate = [ProjectAAppDelegate class];
    } else {
        appDelegate = [ProjectBAppDelegate class];

    }

    return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegate));

如果这不起作用,那么您必须在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中执行此操作。您可能希望项目 C 的 AppDelegate 成为 A 和 B 的代理。例如:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    [self.projectAppDelegate applicationDidBecomeActive:application];
}

projectAppDelegate 设置为您需要的正确版本。

请注意,您还需要手动加载情节提要以确保启动正确的情节提要。请记住,如果您在加载过程中花费大量时间做出决定(您说这是一次网络调用),您的应用程序可能会被启动。

如果它们是框架,您也许可以找到一些可以执行的漂亮动态加载,但关键应该是可维护性/易于调试。

我要在这里停下来主要是因为有很多不同的事情要做,我真的没有时间把它们都写出来。

Additional info based on follow up question

您将有一些文件重复的可能性很高。我举了AppDelegate的例子。 enum 将不那么频繁,但会发生。还要记住,它不是您关心的文件名,而是您关心的类或其他定义的数据类型。这些是对编译器/链接器很重要的冲突。

比如说:

项目A:

typedef NS_ENUM(NSInteger, State) {}

项目B:

typedef NS_ENUM(NSInteger, State) {}

这就是我提前制定策略的意思。示例策略:

  1. ProjectA 是“赢家”,因此只有 ProjectB 会有变化
  2. ProjectB 是“赢家”,因此只有 ProjectA 会有变化
  3. 项目 A 和项目 B 都会发生变化。

所以对于 1,结果是

项目A:

typedef NS_ENUM(NSInteger, State) {}

项目B:

typedef NS_ENUM(NSInteger, PBState) {}

注意我听到了什么。为了让我的生活更轻松,我使用了一些预定义的前缀来指定它是 ProjectB。在这种情况下是 PB。

对于 2: 项目A:

typedef NS_ENUM(NSInteger, PAState) {}

项目B:

typedef NS_ENUM(NSInteger, State) {}

对于 3: 项目A:

typedef NS_ENUM(NSInteger, PAState) {}

项目B:

typedef NS_ENUM(NSInteger, PBState) {}

由您来制定规则,但要保持一致。 您将需要一个策略来解决所有数据类型更改。例如,如果您从State -> PBState 出发,您显然只想修改 ProjectB。这是将它放在自己的项目中会有所帮助的地方。不过,您可以使用 Xcode 的 Search Scope 来帮助控制这一点。

哦,还有一些其他的事情。

首先,投资一个脚本来查找 ProjectA 和 ProjectB 中的所有重复文件。您基本上需要根据您需要的扩展名(例如.m、.h、.xib 等)在 ProjectA 和 ProjectB 上执行find。这将为您提供潜在候选人列表,您可以从那里制定规则。

由于我是完成这部分项目的傻瓜,我基本上将这个列表保存在一个文本文件中。当我合并文件时,我将它移动到文件中的不同部分(由几个换行符分隔)。记账的方法有很多种,只是我选择的方法。

我也会确保你有一个很好的差异工具,比如 Araxis Merge(这是我使用的)。

另外,请经常拍摄快照以防万一。您可以使用 git 分支。我经常只是复制实际的目录,以便以后在需要时对它们进行比较。

【讨论】:

  • 感谢您为我的问题提供详细答案的努力。我将遵循您在上面列出的指导方针。我必须说这个答案很好地澄清了我的查询。我还有一个澄清一下,当项目 A 和项目 B 具有相同的文件名或枚举结构时,您是否遇到过枚举和文件重复的问题。您能否就如何处理该部分提出建议。
  • @karthik 我在答案中添加了更多信息。希望这能回答它。我建议您与您的团队讨论注意事项,以便每个人都了解风险。
  • 这个答案不仅广泛,而且是正确的。我也不知道豆荚的回答是如何得到这么多赞成的,它只是没有解决这个问题。干得好,@karthik。你应该得到赏金。
【解决方案2】:

我建议你创建 pod 并调用你的项目,你可以根据场景/用例调用它,这样你可以在你的 pod 中保留任意数量的项目。

你可以参考这个link

另一种方法是让您的两个项目保持相同的路径,创建动态框架并将这些引用用于项目“C”我的意思是您正在计划的新项目

任何一种方法都可以解决您的问题。

【讨论】:

  • 据我所知,可可豆荚用作依赖管理器,可用于下载和链接第三方框架,我不确定这如何解决我的问题。请您详细说明您的答案至少有一种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多