How to create macOS app without storyboard?

I would like to create a macOS app without using Interface Builder.


How must the Xcode macOS app template be modified after deleting Main.storyboard and its corresponding Info.plist line

to show a single simple window at startup?

Accepted Reply

Well, if you want to inflict yoursel that pain in order to ignore IB, here is a complete way bof doing :

h ttps://stackoverflow.com/questions/39785679/programmatically-creating-menus-with-swift-3-and-cocoa


Need to mention, that without IB and autolayout, internationalizing will be nightmarish (if you want to support right to left for instance)

Replies

I understand your question as : don't use storyboards, but use Interface Builder as one did in XCode 7.3.


If you want to get a project created as you did in XCode 7.3, without storyboard, but with a main menu as entry point.


In XCode 8.3 (or 9 probably)

- Create New MacOS project : it will be create with storyboard

- In project navigator, delete Main.stroryBoard

- in infos.plist, delete the mainStoryboard entry

- with the file Menu, create Ne File : in User Interface, select Main Menu ; the file should appear under MainMenu.xib name

- in infos.plist, create a new entry Main nib file base name : give it MainMenu value

- In Interface Builder, add a window to the MainMenu.xib (drag the window from the object selection panel to the xib screen)


Here you are, the app should run and show a main menu with a window on screen.


You're exactly in the situation of project created in XCode 7.3 with "Use storyboard" option deselected

Thanks for your answer, but my intention was to create the app just programmatically and really without using IB, storyboards, .xibs ...


I know the solution for iOS, this looks like:


- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
   
    self.window.rootViewController = ...; // use an appropriate view controller here      
   
    [self.window makeKeyAndVisible];
   
    return YES;
}


I'm searching for the macOS equivalent for this.

The default startup code loads a main storyboard or NIB, primarily for the menu bar (though there can be an initial window as well). You can avoid some pain if you create at least a main XIB with a minimal menu bar (apple, application and help menus, say). There are also some other "magic" menu items on the File, Edit and perhaps Window menus, but it's not clear whether you care about those or not. Again, menus are easier if you can at least provide the standard ones via a XIB, even if you add your app-specific items programmatically.


Once you get to application:didFinishLaunching…, there's nothing special you need to do. At that point, you can just go ahead and create a window. You don't have to use any window controllers or view controllers, though you can of course do that programmatically too if you want them.


(For anyone following along this thread, I feel compelled to add that there's no benefit whatsoever of creating a UI programmatically and avoiding IB, but some people insist on doing it. OTOH it does have signficant downsides: larger code size and complexity, possibility of needless bugs, and the chance of missing standard Cocoa behaviors that normally integrate themselves into your app for free.)

Well, if you want to inflict yoursel that pain in order to ignore IB, here is a complete way bof doing :

h ttps://stackoverflow.com/questions/39785679/programmatically-creating-menus-with-swift-3-and-cocoa


Need to mention, that without IB and autolayout, internationalizing will be nightmarish (if you want to support right to left for instance)

I'm just curious: why do you want to do this?

I can understand choosing standalone xibs over storyboards, since storyboards made some fundamental changes in how you structure a Mac app. But if you want to go nibless (I wouldn't) i'd at least recommend you use one xib for menu bar. You can create menu in code and set it on NSApplication (see the mainMenu property). There really is no point in doing that though. You are just doing extra work for no reason really.

Thanks for the link, but unfortunately I am not enough experienced in Swift to get this working.

My problem here is that I don't know where to place the main block in the Swift app template generated by Xcode.


Maybe I can figure this out with some more time.

I have been developing iOS apps for more almost 8 years now, and already at the beginning I have decided to work without IB.

Working with IB seemed very tedious to me, I found it very much easier to do the UI things directly by code. I think this also helped me

to better understand how things really work instead relying onsome "magic".


Now I am starting my first macOS project and I would like to know if I can develop a macOS app in the same way (without IB).

I don't know how this will end up, perhaps I follow the advices in the other posts and use IB for the menu or some more.

But to make my decision, I would like to know how the code-only solution looks like.

You just found why you should use nib, at least to define the menu bar ; doing all programmatically is overly complex.


Did you try the solution I proposed on Aug 20, 2017 11:39 AM ?


You should, it is simple and will put you in the right direction.

Meanwhile I found the solution for the Swift problem:

I had to remove the @NSApplicationMain attribute from the delegate class

and put the startup code into a separate main.swift file, then everything is fine.


No, I did not try your first suggestion until now, but I will do this soon.

Beacause Auto Layaut requare that you must do many visual routine work in Interface Builder. And sometimes a constraints works with difference in next versions of OS

At least because IB have no zoom options (i've almost punch my monitor when trying to move label with single character instead of resize it!). And it's just nightmare when you've decided to change margins for all application, for example. Working with contsrains in IB is really hard…

For 100% macOS app without storyboard and mainmenu xib you also need to connect the main() function to call the AppDelegate , this way the NSApplication will call applicationDidFinishLaunching in AppDelegate.

so this is the main file :

`#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
AppDelegate * delegate;

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

        delegate =  [[AppDelegate alloc] init];
        NSApplication.sharedApplication.delegate = delegate;
    
       return NSApplicationMain(argc, argv);

}`