Best alternative to overlapping subviews - objective-c

I have a UIView containing a login form, however when the user is already logged in, I want to show a logout button instead of the form.
My current approach is creating a subview for both the login form and the login button, overlapping each other in Interface Builder.
I would then only show one of the subviews at a time.
Is there a better way of doing this so it is easier to design in Interface Builder, while still using the same UIViewController?
If it matters the view is a modal view.

You could tweak your UIViewController to actually be a UITabBarController, but tweak the tab bar so that it's not visible when the controller is pushed to the screen:
self.hidesBottomBarWhenPushed = YES;
This should allow you to:
Programmatically switch between views easily
Manage two (or more) separate UIViewController instances in IB easily, without overlapping

For optional / modal parts of a view controller, one approach I've used several times in the past is to create a view for each section as top level objects in the nib. You can arrange each view using interface builder more easily then, and then all you need to do in your code is conditionally add the appropriate view to the main view in your viewDidLoad method. Remember that, as top-level objects in the nib, they should have strong outlets, not weak outlets.

Related

Access windowController's button From subView

In my cocoa OS X application, I have a WindowController with a xib file, and Two ViewControllers with xib files, I have added a Custom View in the WindowController, Where I am swapping those two Sub Views by removing and adding those Views when clicked in continue or next button.
[[theViewController view] removeFromSuperview];
self.theViewController = [[WelcomeInstallViewController alloc] initWithNibName:newView bundle:nil];
[innerInstallerView addSubview:[theViewController view]];
[[theViewController view] setFrame:[innerInstallerView bounds]];
Now In one of those views i have a button which needs to disable the continue button in the WindowController.I have looked into NSNotificationCenter, this is my first mac,cocoa, objective c app. should i use NSNotificationCenter? i am confused, and didn't understand properly.
There are many ways to skin the cat..
The simplest approach would consist of adding an outlet to your NSWindowController and link the button to that outlet in Interface Builder, then handle the button enablement on whatever conditions you require.
Notifications are one good way of loosely coupling application components, e.g. in case the window controller doesn't initiate the state change that would trigger the button to disable/enable itself.
Other possibilities include NSUserInterfaceValidations, a dedicated mechanism (protocol) in Cocoa to..
allow the target of a user interface element such as a menu item or a toolbar item to decide whether or not the user interface element should be enabled.
Given a similar design requirement (multiple loadable XIBs), I have used the NSViewController paradigm to allow logic to be attached to the sub-views that I load into the main view. In this case, I would create an NSViewController subclass which has a bool property (let's call it canContinue), which I would bind from the main view's button to owner's subview.canContinue.
If you do this, the main view will have to load the view controller (which will take care of loading the XIB) when you bring in each of the individual subviews, and then make sure to assign the subview property in the owner to point to the NSViewController that you load.

Custom segue that 'finishes' early?

I'm looking to implement a custom segue that pushes to a UIViewController, but completes before the new UIViewController fully fills the screen, leaving some of the source view controller still in view and functional. (For example; new view controller covers half of the user interface).
I'm keen to use a segue rather than a view that is moved using CGRect, Quartz framework method, or similar, as constraints get messy really easily, unless a custom segue could utilise such methods(?)
Any pointers greatly welcomed! :)
For this task you would use a container view controller, which manages and displays the content of multiple other view controllers at a time while letting them interact with their views like normal. An example of this would be the UISplitViewController, which displays two view controllers' views at a time, one on each side of the screen. You can design segues that swap out one view controller of the multiple on display in a container view controller, similarly to the Replace Segue implemented by Apple to swap out a UISplitViewController's detail view controller (the one on the right hand side).

In Interface Builder, how can I add UIViews to a subview that is a part of a custom view I've created?

I am working to create a custom view for an iPhone app I'm creating. This custom view is a Popover dialog which is made up of a UIView which contains two images, a button to close the dialog, a label, and a UIScrollView. This view is named MDPopoverCard. I have these files as a part of my view:
MDPopoverCard.xib - The view as drawn up in Interface Builder.
MDPopoverCard.h - Defines a few IBActions and some other properties
MDPopoverCard.m - Implements some functions defined in the header
This is what it looks like in Interface Builder: http://cl.ly/2B0f2x3s1w1i0K2G0Q1r (sorry, I can't post an image yet as I'm new to stackoverflow)
There are a few properties defined in my .m and .h files that control whether the green button is displayed and what the text of the title label is.
I need to display a number of these dialogs in my app and I'd like to reuse this interface I've designed. I want to be able to add buttons and other form elements into the UIScrollView via Interface Builder. However, I have a problem:
Imagine that I have another view I'm drawing up in Interface Builder. I add a UIView to it and set its class to MDPopoverCard. I then drag a couple UIButton objects into my MDPopoverCard view. Here's an example of what it looks like in Interface Builder:
http://cl.ly/1X090h1t1q3f0i3E0917
This screenshot shows another view (the root view) that I've added my MDPopoverCard to. I've then added two buttons as subviews of MDPopoverCard.
These buttons do get properly nested in Interface Builder. However, when I run my app these buttons are added before any of the items that make up my MDPopoverCard view in the xib file. This means that the buttons are being added behind my popover dialog. That's the first problem.
The second problem is that I want these buttons and form elements to actually be added into the UIScrollView that's contained within the MDPopoverCard view, and not just right into the UIView's subviews array. Is there a way to specify this in Interface Builder? I'd really much rather draw buttons into my UIView and connect them to IBActions via Interface Builder than hand write every instance of these dialogs that I may need to display (several).
Any advice? Is there anything I can do to clarify the question?
Thanks for your help!
Formerly Xcode supported user-defined IB plugins for custom UI elements which you could just drag and drop into the XIBs the same way you do with built-in widgets. As of Xcode 4 this nice feature has been removed. (Thanks a lot, Apple.)
Currently I can only think of a hacky way to achieve what you described. What I would do is the following:
create an IBOutletCollection on your MDPopoverCard, e.g. embeddedControls
link it with every UI element (here: the buttons) you want to go inside the scroll view
implement the awakeFromNib in MDPopoverCard and explicitly reset the superview of all the views in embeddedControls to the scroll view in there
Hope this helps (although I haven't tried).

How to initiate display of one view from another?

Assume you do not have a UIController to do the job. From inside the UIView .. how would you replace self with another UIView?
It's not very clear what you are trying to do from your question. UIController is not a class, for instance.
Ideally your app should be structured something like this:
UIViewController subclass
Controls a set of objects that are all on screen at one time. For example, any number of UITextFields, UIButtons, UIViews and UILabels.
has methods (IBActions and other delegate methods) which are triggered by user interaction with the controls and inputs.
has IBOutlets which allow it to manipulate what the user sees on screen. For instance an IBOutlet attached to a UILabel allows changing the text when a user presses a button.
UIView is only generally subclassed if you need custom drawing code, or some kind of custom control. Don't put application logic here if you can help it, and you can usually help it.
You can have multiple UIViewControllers but they usually function very independently. Often View Controllers don't maintain references for other view controllers. If they do it's loose couplings like the delegate pattern.
Bottom line: if you have two views controllers that need to communicate with each-other, you need to have a reference to one from the other. This usually occurs in the form of a property on one or both of the view controllers, and is connected either by interface builder or at run time when you create them.
You can add another subview using self.addSubview: you may also want to check self.bringSubviewToFront:
For more information, check the docs:
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html

Programmatically change subviews from within subview's controller

In my iPhone application I've set up a default, blank view called Main View into which various child subviews will be loaded for different parts of the application. It's the same approach as if I was using a tool bar to switch between subviews. That case, in the MainView controller I could hook IBActions to buttons in the toolbar, so that when a button was pressed, MainView added different subviews to itself.
In my situation, though, I need to tell MainView to change its subview from within the subviews. So here are two sister subviews, each with their own controller and xib, that would be loaded as subviews of MainView:
- StartView
- FormView
In StartView, after some animations and welcome stuff, a button triggers the camera image picker. Once the image picker returns the image, I need to tell MainView to remove StartView and add FormView.
It may be the result of a long day or my newness to iPhone OS but I'm stuck getting my head around the right way to set up my objects/controllers.
You never have more than one view controller active at a time. (The nav and tabbar controllers don't control views, they control other controllers.) In this case, you will have a single controller that has the MainView as its view property. It will add StartView and formView as subviews of MainView.
However, this is not a good design. It will overload the MainView controller by forcing it to juggle many views. It would be better to use a hidden navigation controller or a tabbar. Hierarchies of controllers can create the illusion from the users point of view for almost any interface layout you can imagine. There is no need to create a logical structure that mimics the visual one.
From your description you may only need a single view/view-controller pair: Set the formView controller to open the camera view before it displays the formView. When the camera is dismissed it reverts to the formView automatically. No fuss, no muss.