XCode/Cocoa Mac Changing Views - objective-c

I'm having trouble figuring out how to change between different custom views in my XCode project.
I have my Main nib file, consisting of 1 main window, and 5 custom views. The main window consists of 5 buttons, all which need to connect to the different views. So for example I click on button 1 and it closes the current menu and loads custom view 1.
I'm having trouble figuring out how this would be done.
I guess I would create IBOutlets for the 5 different buttons and the 5 custom views, and connect them to different methods such as openView1, openView2, where each method would close the current menu and load the custom view?
Could anyone help me code-wise how I would achieve this?
Any help greatly appreciated.
Thanks

So essentially you want a tab view?
You can make an NSTabView in Interface Builder. Set the number of tabs to 5. Then lay out the contents of the views you want inside that.
If you are happy using the standard system provided visual look for your tabs, then you're done. If however you want to have custom buttons that switch tabs, read on.
With your tab view selected, set its style to Tabless:
This makes the tab buttons disappear. That means that switching between views needs to be done through code. First you'll need an IBOutlet that represents your tab view itself: connect that up. Then write an IBAction method for openView1:, that might look something like this:
- (IBAction)openView1:(id)sender
{
[tabView selectTabViewItemAtIndex:0];
}
Make yourself a button (that sits in your window somewhere outside the tab view, otherwise you'd only be able to access it from one tab!) and connect it to this action.
This is probably the easiest way to get going with an interface like this. There's a whole bunch of ways to improve on it depending on how you want to structure your code. For instance, it sounds like you're coming from iOS development, where you'd make a UIViewController for each tab. Well, on the Mac there exists NSViewController, so you can use a similar pattern: but if you do you'll need to write some code that handles getting your view controllers' views into your tab view. It doesn't happen automatically through Interface Builder like it does on iOS. This tutorial should get you started if you choose to go that route.

Related

Using multiple windows with Storyboards (Mac OS X development)

I have two window controllers (with their own view controllers) on a storyboard.
In one window, I have the main program, a basic text editor with an NSTextView. In the other window, I have a single button.
I found out how to get the window to display by linking it to a menu item. It works.
The main window is linked to my ViewController class by default. The second window is also linked to the ViewController class and has its button linked to an IBAction in the ViewController class.
I have some simple code in the IBAction that basically tells the NSTextView to change its font size to a much bigger font. I have confirmed that the code itself works when called in other methods.
The button works, BUT it is using an entirely different instance of my ViewController class. So in result: the text size doesn't change.
So my main question here is how do I get an IBAction in one window to affect an object in another window.
I hope I did an alright job at explaining myself. Keep in mind this is my first Stack Overflow question:) I tried my best to research this question but mostly found information on iOS development and using XIB files.
It sounds like you have two windows with the same controller class but want what happens in one window to affect the other window. The easiest way is going to be with notifications. When the button is clicked in one window a notification gets posted that all instances of ViewController receive and respond to by changing the font size as needed. You could also look into setting a user default when the button is clicked and using bindings to keep the text field's font size tied to the current default.

Cocoa app design recommendation

I have a Mac app that needs to be based on multiple modules. That is, a single window with multiple views, and the default view with a menu. That menu should open one module on the default window and then if I select another module, the contents of the window should change with another view. Those views also have different states, so I made multiple views for each module.
In a nutshell, my app is a single AppDelegate.h/.m, a single xib file, with one NSWindow object and multiple NSView views. Those views have different states, so I load different other related NSViews.
To load a view, I use [window setContentView:viewNameView]; which I know that causes the old NSView to lose state, so I need to keep them all in memory for each module.
Is this the right approach?
Thank you!
You don't describe how and where you want the menu but a widely used method is to have a sourcelist on the left and the content on the right. You see this everywhere including Apples own apps.
If you create a sourcelist on the left of your window and place an NSBox on the right side.
Set up the sourcelist (NSOutlineView) to react to - outlineViewSelectionDidChange: which is an NSOutlineView delegate method.
Here you can check the identifier on the selected item in the menu and set the content view for the NSBox accordingly with - setContentView:
Here's a great introduction to using NSOutlineViews for anyone interested.
Edit: Depending on how many views you have it might be easier to have an NSTabView (in tabless mode) and just switch tabs in the - outlineViewSelectionDidChange: method. This is also widely used and the user won't see the difference.
You will want to look up NSWindowController for managing your window and xib, and NSViewController for managing views. The app delegate shouldn't do much (in fact you probably could remove the header file and merge it with .m).
Some references to look at:
https://www.mikeash.com/pyblog/friday-qa-2013-04-05-windows-and-window-controllers.html
https://developer.apple.com/library/mac/samplecode/ViewController/Introduction/Intro.html
Yes that will work. What you may end up needing as well, is a custom Navigation Controller. Unfortunately Cocoa doesn't have an NSNavigationController, so you'll have to write something on your own. But basically yeah what you'll do is swap out the contentView with the next view you want to display-- and keep a stack of views you've navigated to so you can support going back (or you could use a dictionary to add transition keys to create strongly linked transitions)
Here's an good example somebody posted in a previous thread-- if you just search for Cocoa Mac Navigation Controller you should find some helpful results :)
Mac OS X Cocoa multiview application navigation
Another thing that you may want to keep in mind, which came up for me, is if your views are of different sizes. If they are, and you are using auto-layout, you will need to update the constraints to resize the window appropriately as views are swapped out

Working with storyboards in Xcode, how to handle massive Storyboard in iOS

I have been using the storyboard to make an application and currently there are many segues and several components. This is causing a ton of lag when I try to do anything inside the storyboard. Is there a way to hide components inside the storyboard? thanks.
+1, For the potentially features to improve Xcode. Now, there is no way you can hide those views (Not that I know). But I would suggest you to,
Hide the debug areas you don't need.
Hide the document outline while working with segues.
Why?
I think in this way whenever you are making changes, system does not have to repaint those unwanted views and long document outline. Probably this will be less laggy(I don't think there is a word like this)!
Work around
Divide your segue into different meta segues and then you can call those segues from your main segue. In that way you don't have to put each connection on one file but you condense it!
And here we go the documentation for it! Now you can get the story board by different file and then initiate with the UIViewController easily. Then you can just use old ways to segue between different ViewControllers.
Apple Documentation for UIStoryboard
Demo App.
In order to achieve this, I have made a quick demo application which will help any future visitors.
https://github.com/Krutarth/LargeStoryboardManagement
Visually something like this,
You can split one huge storyboard into multiple small storyboards.
Select the view controllers that you want to move to a smaller storyboard, then
In the top menu, click Editor -> Refactor to Storyboard
Save the new storyboard with the desired name. XCode will auto generate all the required storyboard links from your large storyboard to this newly created small one.

Can I use UITabBarController as a simple viewController switcher?

I'm creating an iPad app based on a UINavigationController (with the bar hidden) so I can push and pop other viewControllers for navigation around the app. However, I am now wanting to add a section in which there are two viewControllers that I want to be able to switch between, so in other words they are side-by-side, rather than hierarchical.
Is it okay to use a UITabBarController for this? I am aware that on the iPhone it is recommended they are used only at the root level of the app, but since this is an iPad app I wondered if I could use it? Also, I guess I need to create an empty viewController, create a UITabBarController within it and set the delegate to it, then add the two viewControllers to it... So in effect I will have a viewController within another viewController, and when I have done that in the past the results have been very flaky.
Can I do it this way? The only other way I can think of doing it is to have two plan UIViews within a UIViewController, but that also means I shouldn't really put any business logic in them (bad MVC!), and not being able to will be a right pain in the a**.
Any ideas?
Thanks!
:-Joe
EDIT: I also need to be able to swipe-animate between the two VCs within the TabBarController, AND have a menubar over the top which doesn't animate... Can I do this?
Sure.
I do this kind of thing all over the place in an app I'm working on. I actually have several different types of "toolbars" that can be optionally shown at different times.
What I do is create a "parent" member in my toolbar's class - and when a button is pressed, I have the toolbar call a method in the parent class to do whatever needs to be done - (i.e. display another view).
This avoids the whole mess of creating a view inside another view (or viewcontroller inside another viewcontroller - or whatever) - the toolbar can take the button hits, but all the views are opened by the root view/controller.
Hope this helps/makes sense!

Drawing an "NSView" to a Custom-View - How? Am I taking the right approach?

I'm using Objective-C and Cocoa, whilst developing for Mac OS X - so not the iPhone/Cocoa Touch. (That said, I'd be interested if it was the same procedure for the iPhone)
I'm working on a preferences window for a simple app. I have a NSWindow with a toolbar - there are 5 different items on the toolbar, all of which need to bring up a different set of options.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window. My plan is to work out the interface too each of the NSToolbarItems options, and then draw the corresponding view on to the custom view when the specified NSToolbarItem is clicked.
I'm guessing that I simply create a NSView sub-class for each view, an empty xib in Interface Builder - set the xib to my custom NSView, code it as usual... But here's a few problems;
1 - Just how can I get the xib file to appear on the custom-view then? I have looked around and most articles don't seem to have this situation, or a situation I can relate too.
2 - When the window comes up, I want the default view to appear on the custom view. Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal. It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
I'd be really grateful for any help!
Cheers in advance.
So I set the NSToolbar and its items in Interface Builder, and then placed a custom view underneath the menu - taking up the rest of the window.
You can't have a menu inside of a window. You can have a pop-up button, which has a menu, but not a menu directly. Did you mean “toolbar” here?
You don't need to create a custom view for this. Make a tab view and set it to be tabless. Give it as many tab view items as you have toolbar items. In your controller, write an action method for each of the toolbar items, and in each action method, switch the active tab of the tab view.
You can activate different tabs in IB to populate them with views in IB. The active tab is saved in the nib, so make sure you set it back to the first tab before saving, so that the first tab is the one that's initially active when your app runs.
Just how can I get the xib file to appear on the custom-view then?
That question doesn't make sense.
Once again, I'm guessing I just write that in the initialisation code for the NSWindow - its no big deal.
You would only be able to do that if you have your own initialization code for the window, which you would only have if you have subclassed NSWindow. There are very few reasons to do that; unless you're making the window itself look different (not making an Aqua or HUD window), you should move that initialization code elsewhere, probably to the aforementioned controller (which should be the File's Owner of the nib).
It just goes back to question 1 though - how do I draw my NSView to the custom-view specified in Interface Builder?
A custom view in Interface Builder is a plain NSView (unless you explicitly change it to a subclass of NSView you create). However, you do not need one for anything you have described in your question.