【问题标题】:Having same filename appdelegate.h for 2 targets in 1 project1 个项目中的 2 个目标具有相同的文件名 appdelegate.h
【发布时间】:2013-10-25 15:49:24
【问题描述】:

是否可以为不同的目标分离出 AppDelegate.h:iPhone/iPad?

我有一个默认的通用 main.m:

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

我为每个 iPhone/iPad 文件夹中的每个目标正确设置了 2 个目标,其中一个 appdelegate.h/.m。

它们的头文件相似,当我构建 iPhone 目标时,它从 iPad appdelegate.h 抱怨 Duplicate interface definition。但是,反过来就可以了。

我该如何解决这个问题?

【问题讨论】:

    标签: ios xcode


    【解决方案1】:

    您应该转到每个目标的“构建阶段”,并确保每个目标都在“编译源”下包含适当的应用委托。如果您为这两个应用程序代理分配不同的类,您可能还想更改 main.m 以使用适当的类:

    #import <UIKit/UIKit.h>
    
    #import "IphoneAppDelegate.h"
    #import "IpadAppDelegate.h"
    
    int main(int argc, char * argv[])
    {
        @autoreleasepool {
            if (NSClassFromString(@"IphoneAppDelegate"))
                return UIApplicationMain(argc, argv, nil, @"IphoneAppDelegate");
            else
                return UIApplicationMain(argc, argv, nil, @"IpadAppDelegate");
        }
    }
    

    就我个人而言,我更喜欢有一个单一的应用程序委托,并对 iPhone/iPad 进行条件检查,例如,

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
         // do iPad specific stuff
    }
    

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
         // do iPhone specific stuff
    }
    

    虽然看起来很笨拙,但两个平台上的大部分应用委托都是相同的,并且它引入了代码维护问题以拥有两个应用委托。

    【讨论】:

    • 单个应用程序委托中的 if else 语句过多,因此不使用单个文件。
    • @NoraOlsen 如果您想要两个不同的应用程序委托类,您可以 (a) 为每个目标各自的“编译源”包含适当的类; (b) 让main.m 抓住正确的那个。理论上你可以给它们取相同的名字,但是在这种情况下,一些 Xcode 的 UI 可能会混淆,所以唯一的名字可能会更好。
    • 我会不会遇到redefinition 的问题,因为我在main.m 中包含了两个头文件?似乎我需要做一个#if/#else 来避免main.m 中的这种情况以及预处理器宏?即使没有明确说明 2 个不同的头文件名,Xcode 也会包含所有头文件,因此我遇到了 iPad appdelegate.h 包含在我的 iPhone 目标中的原始问题。我也尝试过用户搜索路径排序。
    • @NoraOlsen 没有重新定义问题,因为我给了它们唯一的类名。就像您为弱链接类导入标头时一样,导入标头不需要该类的存在。我测试了上面的,它工作正常。但是如果你给这两个类起相同的名字,那么你就必须做那个预处理器检查逻辑。顺便说一句,如果您使用我的方法并且如果您的其他类需要与应用程序委托的自定义对象/方法进行交互,那么您可能需要定义一个指定公共接口的协议。
    【解决方案2】:

    一种方法是在目标的构建设置中添加“预处理器宏”,例如在 iPhone 目标中添加“BUILD_FOR_IPHONE=1”,在 iPad 中添加“BUILD_FOR_IPHONE=0”。然后您可以在 iPhone 的 AppDelegate.h 中添加以下内容

    #if BUILD_FOR_IPHONE
    <your normal .h contents>
    #endif
    

    在你的 iPad 上

    #if !BUILD_FOR_IPHONE
    ....
    #endif
    

    【讨论】:

      【解决方案3】:

      我不确切知道 iPhone 和 iPad 的目标,但是

      如果您在项目中有两个不同的构建目标,您只需为不同的 AppDelegate 文件选择适当的目标成员身份,即可指定要包含在构建中的不同文件。

      要有两个 AppDelegate.m 用于不同的构建目标: - 首先,让您的 AppDelegate.m 只检查一个构建目标。 - 其次,为了创建一个副本,去finder并寻找你原来的AppDelegate.m;创建子文件夹并将文件复制到那里。 - 现在,在 Xcode 中创建引用:将文件拖到原始 AppDelegate.m 旁边的 Xcode 窗口中,选中“创建引用”并只选择第二个构建目标。

      此时,您的项目中应该有两个 AppDelegate.m 彼此相邻。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-16
        • 2014-09-07
        • 2012-12-31
        • 2016-05-27
        相关资源
        最近更新 更多