0

I'm very very new to the target concept in Xcode. I have followed this tutorial to learn to create two targets in the same project. I just want to know how to make target A use AppDelegateA.swift as its designated app delegate, and target B use AppDelegateB.swift as its designated app delegate. Because on the tutorial, it actually teaches how to make two apps from the same AppDelegate. But I make two (almost) completely different apps, that share a lot of resources and libraries.

And while we're on the subject, can I also have target A use a storyboard called Main, and target B also use a storyboard called Main, but they are actually a different storyboard (but put together inside the same project)?

Brian
  • 14,610
  • 7
  • 35
  • 43
Chen Li Yong
  • 5,459
  • 8
  • 58
  • 124
  • I'm curious, why would you want this? – Alexander Oct 26 '16 at 04:44
  • @AlexanderMomchliov because I want to keep the code as separate as possible, if they are meant to be separate (in my logic). In my opinion, AppDelegate is the "entry point" of an application, and therefore should also separate between targets that's actually a very different application (but shares whole lot of libraries and resources). This is so that I can organise each of the targets in their own folders, including the AppDelegate, and can copy them out quickly into different project. – Chen Li Yong Oct 26 '16 at 04:56
  • 2
    if you have two very different applications, then they should be 2 different projects. Their shared code should be extracted into a third library project, which is referenced from the first two. – Alexander Oct 26 '16 at 05:40
  • @AlexanderMomchliov I think you refer to dependency. I have read a brief about dependency project, which I think it's an entirely different beast on its own that I need to digest slowly at separate time. Right now I just trying to explore what are the options I can get from target, what's possible and what's not. But I do appreciate your suggestion and I will keep that in mind when I learn about target dependency after I have understand a bit more about this current subject. Thank you very much. :) – Chen Li Yong Oct 26 '16 at 06:16
  • 1
    you can set the embedded files for each individual target in Xcode, you don't need to hardcode anything, you just need to attach the correct `AppDelegate.swift` file to the desired target under the _File Inspector_ / _Target Membership_ panel; I __would not go__ with the solution which is in the answer, that is a kinda horrible solution and could be a source of many bugs or issues. – holex Oct 26 '16 at 15:24
  • @holex in the end, I actually use compiler directives to select which storyboards I will use for the entire project, but I still use one AppDelegate, because the code that actually separate the program flow between the target is not much, to warrant the use of multiple AppDelegates. – Chen Li Yong Oct 27 '16 at 08:29
  • @AlexanderMomchliov after further studies of the situation, and separating ViewControllers design into their respective storyboards based on the target, actually it made me create an additional "shared" storyboard which has ViewControllers that's used by both of the apps, such as login screen, forgot password screen, side hamburger menu, user profile management, etc. Even though the content of the app is different, but turns out there are some screens and ViewControllers implementation I can share between them. – Chen Li Yong Oct 27 '16 at 08:34
  • @ChenLiYong, if you have 2 (or more) `AppDelegate.swift` files, you assign them to the desired target – as you could do in case of e.g. 2 (or more) `Main.storyboard` files. you just need to organise the customised files (e.g. in isolated folders) and the shared files (e.g. in a common folder) in the file system nicely as well; that is a quite standard way to deal with files for multiple targets. – holex Oct 27 '16 at 08:47
  • @holex ahh i see. but when I have two storyboard with different name (eg: one is `TargetA.storyboard` and another is `TargetB.storyboard`) and then I tried to rename `TargetB` to `TargetA`, Xcode gives me error "TargetB.storyboard” couldn’t be moved to “Base.lproj” because an item with the same name already exists." but they have been assigned to different target. I guess I need to put them in the different physical folder as well. – Chen Li Yong Oct 27 '16 at 09:40
  • @ChenLiYong, maybe it was in the same folder in the file system, that is why you couldn't give them the same name; but as long as you keep the custom files in isolated folders, you can suddenly can use the same name (the project can attach multiple files with the same name with no issue as long as they aren't in the same folder), and the different targets could set up to use the specified folder's content only; but it has to be managed explicitly in the file system as well not only in Xcode (but you can create _folders_ in Xcode not only _groups_ which is a kinda help to get the same outcome). – holex Oct 27 '16 at 09:49

3 Answers3

4

Yes you can create 2 different based upon the target make following changes:

in the projects

main.m

you could do something like

int main(int argc, char *argv[])
{
    @autoreleasepool {

        NSString *appDelegateName;
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
            appDelegateName =  NSStringFromClass([AppDelegateIPhone class]);
        } else {
            appDelegateName =  NSStringFromClass([AppDelegateIPad class]);
        }
        return UIApplicationMain(argc, argv, nil, appDelegateName);
    }
}

But IMO you should not do it.

Instead doi it as apple does it to, in app delegate load different view controllers or different XIBs.

    @implementation AppDelegate

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        // Override point for customization after application launch.
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
            self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil] autorelease];
        } else {
            self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil] autorelease];
        }
        self.window.rootViewController = self.viewController;
        [self.window makeKeyAndVisible];
        return YES;
    }

@end
Vinodh
  • 5,262
  • 4
  • 38
  • 68
  • 2
    That is (pre-ARC) Objective-C, not Swift. – Martin R Oct 26 '16 at 04:44
  • Oh i see, so instead of having two AppDelegate, we use the same AppDelegate, but load different screen altogether. Thank you for providing both ways! – Chen Li Yong Oct 26 '16 at 04:57
  • @MartinR it's okay, for my case, I just need to know the concept. I'm writing in swift, but I know a bit of obj c to convert it to swift. But, well, there's might be other people who need the direct swift version. :) – Chen Li Yong Oct 26 '16 at 05:00
  • I know that this is an old answer and may not apply now on days but wouldn't the app store reject your app if you had for example locations feature and health kit feature declared in your app delegate but feature flagged in that way? My understanding is that if they see any code reference of something that is not in use or in your .plist you will get rejected. – I'm not human Aug 07 '21 at 08:07
  • No apple won't reject – Vinodh Aug 12 '21 at 15:29
1

New answer to an old question that I was having myself. The answer is quite simple these days:

  1. Duplicate the main.m for each target
  2. Set the target membership for each main.m in the side panel on the right.
  3. Create the AppDelegate class for each target. They can have the same or different names and set the target membership for each AppDelegate appropriately.
  4. In each of the mains.m call the AppDelegate class that it needs to use. It can even have different names.
Cliff Ribaudo
  • 8,932
  • 2
  • 55
  • 78
0

Hope my answer here helps for second part of including multiple AppDelegate files based on targets. https://stackoverflow.com/a/43227300/2715840

For first part of using multiple targets you can do so by simply doublicating the base target , you will get your plist already copied , change name based on new target or keep it same name plist.info but in different path. for separating code files(like Appdelegates) , storyboards and Assets , or firebase plist config files you can find my answer in the above like valid for these purposes.

Hope this helps.

Community
  • 1
  • 1
IsPha
  • 389
  • 4
  • 9