I'm getting back in to Cocoa development on the Mac after a long stint doing iPhone work. My previous experience with Cocoa on the Mac has just been dinky little tools. I'm looking to build something serious.
Looking at a modern Cocoa application like iPhoto (or Mail or Things or....) many apps use the Single-Window, Source-List based approach. I'm trying to wrap my head around that as best I can because it seems to provide a good experience. However, I'm having a little trouble. Here's how I think it should look, but I'm wondering how others are doing it, and what's really the best way:
Starting point of the app is an AppDelegate object which, after launching, creates a Window[Controller?] from a nib, along with setting up its data (from, say CoreData)
WindowController loads a window which essentially just has an NSSplitView in it.
Left side of the splitview has an NSTableView or NSOutlineView which is set to have the SourceList style.
Right side has the main content of the app, depending on which item of the table view is selected.
I would assume somewhere (where?) there are NSViewControllers managing each of the different views which will appear in the right side (think how iPhoto has All Photos, Events, Faces, Places, etc. and I imagine they could all appear in different nibs... is this correct?).
Those view controllers are probably bound to the source list on the left.. how does that work (source list is backed by an NSArrayController of NSViewControllers maybe?).
Anyway, those are my thoughts, am I completely off-base or...? I've looked around the web, found this post here, and I've looked at some Apple source code but I can't seem to wrap my head around it. Any guidance would be welcome.
Breaking the views up into separate nibs is mainly good if you're going to swap out some views for others, since you can load them lazily. And yes, in a modern app, you would use NSViewController, or perhaps KTViewController from KTUIKit (see the posts she co-wrote about NSViewController)
Don't just go running into the arms of the source list, however. A single-window interface can be good for simple apps, but it can quickly become unwieldy when you have many things going on, as they may be better served by breaking them into separate windows; iTunes and Xcode both provide many examples of this (especially the latter, since you can switch it between SWI and MWI).
You need to think about whether a multiple-window or single-window interface would be better for your app. There is no one answer for all apps; it depends entirely on your app, and what you want it to do, and how you want it to look—you (plus the rest of your team, if you have one) are the only one who can answer this question. You may want to do some paper prototyping to do quick experiments in each direction so that you can hold at least fake examples of both UIs up against each other.
One easy way to get a feel for the way nibs are split up is to just go into the iPhoto directory and start opening up nibs
If you want to explore a little more into the class structure you can try browsing around using F-Script
Related
This is a best-practices question.
When one makes a new Swift application for OSX, it builds a Main.storyboard and places that physically in the Base.lproj folder, but logically within the app's main "group".
I decided to separate different parts of the UI into different storyboards, so I added a Document.storyboard and Preferences.storyboard.
In retrospect it's not clear if this was the correct way to do this - for items that consist of a single window or view, should I use storyboards or just use XIBs? I've read the Apple documents but I'm not clear on the practical differences. Are storyboards "replacing" XIBs, are they the new hotness that I should use from now on?
Now I will be expanding the project with additional views, specifically a series of sheets used for editing certain features of the document. Should I put these all in a single storyboard, one XIB, or individual XIBs? Is there any strong reason to select one over the others?
And finally, when I added my storyboards, it placed them in the root of the project folder. Should these really be moved to Base.lprog?
This is something I've been thinking about, too. I've recently gotten into OS X development, so I'll share my amateur view of XIBs vs storyboards. To those of you that are more familiar with this, feel free to correct me if I'm mistaken.
Interface Builder inside Xcode seems to do a pretty good job of allowing you to put a skeleton in place, but doesn't always provide all the necessary customization options for a view. When using storyboards, I frequently end up with projects that are half visually based, and half code. It's like working on a cyborg.
Nibs/Xibs suffer from the same problem, but they don't even try to implement transitions. From what I can tell, they represent single windows, views, or menu items. This makes them simpler and more modular. You get to write the code that handles the wiring of them together, and, at first, it may seem like more trouble, but it actually feels like a benefit to me because of the level of control gained. Storyboards can do a lot of this for you, but I personally tend to prefer having it all together in the code.
The ideal solution, to me, would be for Apple to implement a more abstract form of user interface design: where each window (or iOS view, depending on the platform) was contained in a nib, and a Storyboard was only a transition mapping between the nibs. For example: You create all your windows and menus, and then use the storyboard to connect them all, but the storyboard can't edit any of the views details, only transitions and connections.
That being said, I'm quickly getting to the point where I prefer nibs and do all the other coding myself. If nothing else, I'm becoming a better programmer for it. Hope this helps!
Just last week I decided to dive into the world of Swift and Xcode development, and as of yesterday I am actively working on a new application. I have a lot of experience with Java Swing, but working with that is obviously a lot different than working with Apple's fancy interface builders and storyboards.
I am trying to develop a single-window application that has many different views that can be navigated by buttons. I tried to wrap my head around the way the storyboard works, but even after all my reading of the documentation I don't know really what I'm doing - I'm so used to working in hard code. It came to the point where I wrote my app's entire network layer just to avoid working with the interface.
Basically I have a set of different NSViewControllers, each with references to a few of their components (buttons, labels, etc) and I want certain buttons to be able to change the current view controller (preferably with a segue animation) to a different one. How can I approach this? I would guess that this isn't hard to achieve, but I am lost. Any help would be appreciated!
Let me know if I need to submit any code - I do have the basic classes written but nothing relating to this.
Thanks,
-Aidan
I’m risking this question getting closed as “not constructive / argumentative”, as there is no single definitive answer that I’m looking for… but I hope we can make this work. Bear with me.
So. Let’s talk about Mac apps. Cocoa and AppKit are the workhorses on Mac desktop, that can be used to construct classic-looking Mac UI-s. Here’s an example.
The iTunes preferences dialog is a classic-looking Mac UI. Standard toolbar, checkboxes, sliders, separators, buttons. Mac engineers know how to make these, and it’s easy and fun these days with AutoLayout & co.
More recently, though, another style of Mac apps is emerging, that I’d call “modern” apps. In particular, I’m interested in document-based apps, where the document is single-window, decorated with crisp-looking sidebars and other components. Here are two examples (Sketch and Pages).
I’m interested in ideas about how these UI-s are constructed, and what kind of components are used. Is AppKit sufficient to achieve this? I read somewhere, but can’t recall the reference, that iWork these days largely forgoes AppKit and the UI just consists of a bunch of hand-drawn CALayers. I’m not so much interested in the document canvas (a whole another subject) as I am in the sidebar, toolbar and their contents.
OK, let’s try to salvage this question with some specific subquestions…
General window composition for both apps—is it NSToolbar on top, and NSSplitView in the body area, or something more?
Sketch tree view on the left—can I achieve this with NSOutlineView, or is there something more going on?
Pages sidebar—what kind of AppKit components are used here, vs custom drawing? (One curious fact that tells me that custom drawing is going on—when I expand/collapse the “Spacing” or “Bullets & Lists” sections, there is no animation.)
Don't be fooled by current design choices. IMHO we're building apps the same way we always did it, albeit single window interfaces became more popular in recent years.
But that's just a matter of whether you stuff your NSView subclasses in subviews or dedicated windows.
The views themselves shouldn't care at all - in a good application design.
The apps you've mentioned use a mixture of custom and standard controls.
Like apps always did - back to the days of NextStep (or System 7).
I'm from a Windows programming background when writing tools, but have been programming using Carbon and Cocoa for the past year. I have introduced myself to Mac by, I admit it, hiding from UI programming. I've been basically wapping my OpenGL code in a view, then staying in my comfort zone using my platform agnostic OpenGL C++ code as usual.
However, now I want to start porting one of my more sophisticated applications to Mac OS.
Typically I use the standard Visual Studio dockable MDI approach, which is excellent, but very Windows-like. From using a Mac primarily now for a while, I don't tend to see this sort of method used for Mac UIs. Even Xcode doesn't support the idea of drag and drop/dockable views, unfortunately. I see docked views with splitter panels, but that's about it.
The closest thing I've seen to the Visual Studio approach is Photoshop CS4, which is pretty nice.
So what is the general consensus on this? Is there are more Mac-like way of achieving the same thing that I haven't seen? If not, I'm happy to write a window manager in Cocoa myself, so that I can finally delve in an learn what looks like an excellent API.
Note, I don't want to use QT or any other cross-platform libraries. The whole point is that I want to make a Mac app look like a Mac app, leave the Windows app looking like a Windows app. I always find the cross-platform libraries tend to lose this effect, and when I see a native Mac UI, with fancy Cocoa transitions and animations, I always smile. It's also a good excuse for me to learn Cocoa.
That being said, if there is an Open Source Cocoa library to do this, I'd love to know about it! I'd love to see how someone else achieves this, and would help smooth the Cocoa learning curve.
Cheers,
Shane
UPDATE: I forgot to mention a critical point. I support plugins, which can have their own UI to display various plugin specific information. I don't know which plugins will be loaded and I don't know where their UI will live, if I don't support docking. I'd love to hear people's thoughts on this, specifically: How do I support a plugin view architecture, if the UI can't change? Where do I put the plugin views?
Coming from a Windows background, you feel the need to have docking windows, but is it really essential to the app? Apple's philosophy (in my opinion) is that the designer knows better than the user how things should look and work. For example, iTunes is a pretty sophisticated app, but it doesn't let you change the UI around, change the skin, etc., because Apple wants to keep it consistent. They offer the full view, the mini player, and a handful of different viewing options, but they don't let you pull the source list off into a separate window, or dock it in other positions. They think it should be on the left, so there it stays...
You said you "want to make a Mac app look like a Mac app", and as you pointed out, Mac apps don't tend to have docking windows. Therefore, implementing your own docking windows is probably a step in the wrong direction ;)
+1 to Ken's answer.
From a user perspective unless its integral to the app like it is in Adobe CS or Eclipse i want everything as concise as possible and all the different options and displays out of my way so i can focus on the document.
I think you will find with mac users that those who have the "user skill" to make use of rearranging panels will in most cases opt for hot key bindings instead, and those who dont have that level of "skill" youre just going to confuse.
I would recommend keeping it as simple as possible.
One thing that's common among many Mac apps is the ability to hide all the chrome and focus on your content. That's the point behind the "tic tac" toolbar control in the top right corner of many windows. A serious weakness of many docking UIs is that they expect you to have the window take up most of the screen, because the docked panels can obscure content. Even if docked panels are collapsable, the space left by them is often just wasted and filled with white space. So, if you build a docking panel into your interface, you should expect it to be visible most of the time. For example, iTunes' source list is clearly designed to be visible all the time, but you can double-click a playlist to open it in a new window.
To get used to the range of Mac controls, I'd suggest you try doing some serious work with some apps that don't have a cross-platform UI; for example, the iWork apps, Interface Builder or Preview. Take note of where controls appear and why—in toolbars, in bottom bars, in inspectors, in source lists/sidebars, in panels such as IB's Library or the Font and Color panels, in contextual HUDs. Don't forget the menu bar either. Get an idea of the feel of controls—their responsiveness, modality, sizing, grouping and consistency. Try to develop some taste—not everything is perfect; just try iCal if you want to have something to make fun of.
Note that there's no "one size fits all" for controls, which can be an issue with docking UIs. It's important to think about workflow: how commonly used the control would be, whether you can replace it with direct manipulation, whether a visible indication of its state is necessary, whether it's operable from the keyboard and mouse where appropriate, and so forth. Figure out how the control's placement and behavior lets the user work more efficiently.
As a simple example of example of a good versus bad control placement and behavior in otherwise-decent applications, compare image masking in OmniGraffle and Keynote. In OmniGraffle, this uses the Image inspector where you have to first click on an unlabeled button ("Natural size") in order to enable the appropriate controls, then adjust size and position away in a low-fidelity fashion with an image thumbnail or by typing percentages into fields. Trying to resize the frame directly behaves in a bizarre and counterintuitive fashion.
In Keynote, masking starts with a sensibly named menu item or toolbar item, uses a HUD which pops up the instant you click on a masked image and allows for direct manipulation including a sensible display of the extent of the image you're masking. While you're dragging a masked image around, it even follows the guides. Advanced users can ignore the HUD entirely, just double-clicking the image to toggle mask editing and using the handles for sizing. It should be easy to see, with a few caveats (e.g. the state of "Edit Mask" mode should be visible in the HUD rather than just from the image; the outer border of the image you're masking should be more effectively used) Keynote is substantially better at this, in part because it doesn't use an inspector.
That said, if you do have a huge number of options and the standard tabbed inspector layout doesn't work for you, check out the Omni Group's OmniInspector framework. Try to use it for good, and hopefully you'll figure out how to obsess over UI as much as you do over graphics now :-)
(running in slow motion, reaching out in panic) Nnnnnoooooooo!!!!!
:-) Seriously, as I mentioned in reply to Ken's excellent answer, trying to force a "Windowsism" on an OS X UI is definitely a bad idea. In my opinion, the biggest problem with Windows UI is third-party developers inventing new and inconsistent ways of presenting UI, rather than being consistent and following established conventions. To a Mac user, that's the sign of a terrible application. It's that way for a reason.
I encourage you to rethink your UI app's implementation from the ground up with the Mac OS in mind. If you've done your job well, the architecture and model (sans platform-specific implementation) should clearly translate to any platform.
In terms of UI, you've been using a Mac for a year, so you should have a pretty good idea of "the norm". If you have doubts, it's best to post a question specifically detailing what you need to present and your thoughts on how you might do it (or asking how if you have no idea).
Just don't whack your app with the ugly stick by forcing it to behave as if it were running in Windows when it's clearly not. That's the kiss of death for an app to Mac users.
It seems like there is a lot of online information regarding switching between views in Cocoa Touch, but not that many in "desktop" Cocoa. For an app I am creating, I am wondering the pros/cons of the methods (and please list the methods if you could), and which one people personally use/suggest. I don't think that using an invisible border NSTabView will do the trick for this specific app, but I value all your options. I will be changing the view with some buttons at the side as show in iPhoto, iTunes, and generally most Mac apps out there.
Thanks for any help.
EDIT: I have looked into using NSViewController, but am wondering what advice anyone has about how to use this/why not to use this.
Cathy Shive has created a framework called KTUIKit which was designed with single window applications modeled after iPhoto/iTunes/etc. The KTTabViewController class in particular may be of interest, as it provides a way of switching between an arbitrary number of subviews. They provide a formal way of dealing with nesting views, keeping the responder chain intact, and keeping various notifications properly observed/unobserved. There are also a series of blog posts describing some of the reasoning behind the design and how the classes work (the blog posts refer to them with an "XS" prefix instead of "KT", but they're basically the same thing).
Check out Brandon Walkin's excellent BWToolkit
NSViewController will work fine. I've used it for a very similar situation without any problems.