Split view controller rotation on iPhone 6 Plus - ios8

I have a split view controller in landscape mode with two navigation controllers.
This collapses to a single navigation controller in portrait and the detail view controller is pushed from the master.
If I rotate back to landscape when the detail view controller is pushed in portrait I don't understand how to put the detail view controller back into it's own navigation controller.

You should implement UISplitViewControllerDelegate. Simplest way may be to have your own MySplitViewController class and set itself as a delegate in viewDidLoad:
self.delegate = self;
First, you may want showDetailViewController to look something like:
- (BOOL) splitViewController:(UISplitViewController*)splitViewController showDetailViewController:(UIViewController*)vc sender:(id)sender
{
if (splitViewController.collapsed)
{
[(UINavigationController*)splitViewController.viewControllers[0]) pushViewController:vc animated:YES];
}
else
{
self.viewControllers = #[ self.viewControllers.firstObject, vc ];
}
return YES;
}
That should take care of proper showing of details view in both orientations.
Next, you should implement following delegate method similar to this:
- (UIViewController*) splitViewController:(UISplitViewController*)splitViewController
separateSecondaryViewControllerFromPrimaryViewController:(UIViewController*)primaryViewController
{
UINavigationController* nc = primaryViewController;
UIViewController* detailVC = nc.viewControllers.lastObject;
return detailVC;
}
This method is your chance to take whatever you want from primary controller and return that as detail view controller. The example code above is rather simple one, you may need to traverse through navigation viewControllers and pick all starting from specific view controller (assuming you had pushes from details view).
Anyways, it would really payoff to take some time and read: UISplitViewController class reference and especially UISplitViewControllerDelegate Protocol Reference
This will be much clearer.
If you want a shortcut, take a look at Xcode split view controller template project. That one should also contain hint or exact solution for your problem.

Make the detail have its own navigation controller, like in the Master Detail template. When the split view collapses it calls showViewController on the master navigation controller and when it detects a controller of class UINavigationController it sets allow nested navigation controllers true and hides the navigation bar. This way you get to keep the detail navigation so when you rotate to landscape and separate it can use the existing navigation again.

Related

Draw manual segue to myself

I have a view controller contains a table view that displays list of items. Each item could contains list of items (or could be a leaf).
To drilldow the list items, I would like to create a show/push segue, kinda in recursively way, but I seem not able to draw the manual segue to the view controller itself?
Is it supported?
I was playing around with it just after leaving that first comment - I don't think you can have a manual segue to the same view controller!
The best thing to do would be to give that view controller a storyboard identifier (e.g Selection and then create an instance of that view controller with (in Swift):
let subCategoryVC = storyboard.instantiateViewControllerWithIdentifier("Selection") as! SelectionViewController
or in Objective-C:
SelectionViewController *subCategoryVC = (SelectionViewController *) [self.storyboard instantiateViewControllerWithIdentifier:#"Selection"];
(Docs for UIStoryboard.instantiateViewControllerWithIdentifier:)
You could put that in your table view section method along with a manual segue to the leaf view controller.
(The code above assumes the view controller with the table view is called SelectionViewController!)
As Rich mentioned, this is probably not doable as for today. There are two workaround/solutions I can think of:
Instaniate the vc programatically from storyboard and programatically
use navigationController to push it. (I think this is what Rich was
talking about.)
Embed the View Controller in another Navigation Controller and draw
the manual segue to the Navigation Controller.
I choose the 2nd one just because it is very easy and more visual in storyboard. The first one should just work, too.

What is the best way to develop applications using the auto layout in Xcode?

So I guess this is going to be closed for being too subjective and too opinion based but if anyone can help me I would appreciate it.
I got a question. If I have a few controllers that all have almost the same thing For example they have the same background, have a menu going around the edge but the actual content is different. I had a couple of ideas. 1) Just have one view controller and just kill the objects for that current view if the user chooses a different option on the menu and spawn the new objects for that menu. My issue with this way was that I could't find a way to use the auto layout with this.
Second way would to be have a function in a .swift file that I can call and it creates an image view and sets up the menu an everything like that. I have the opposite issue here though, now the auto layout won't work.
App devs must have a way of doing this, I'm just probably thinking of this completely the wrong way.
Is there a better way to be doing this - I am sure there is? I would appreciate it if someone could point me in the correct direction.
Thanks
EDIT:
I should make it clear that the language I am using is swift.
You can create custom container view controller and swap the view controllers for the part that change according to the user selection.
--Adding Example--
e.g iPad's Settings app. The left side is a table view and right side is detail view which changes on user selection. So Tableview can be wrapped in a view controller let's say ListViewController. This will not change. The right side will be DetailViewController which would be swapped according to user selection. Your ContainerViewController will have 2 view controllers at all times.
Here is how to add view controllers as child and set their views in objective-c.
- (void) setupContentViewControllerWith: (DetailViewController*) detailViewController andListViewController:(ListViewController*)listViewController {
[self addChildViewController:listViewController];
[self addChildViewController:detailViewController];
listViewController.view.frame = CGRectMake(kListView_X, kListView_Y, kListView_Width, kListView_Height);
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[self.scrollContainer addSubview:listViewController.view];
[self.scrollContainer addSubview:detailViewController.view];
[self.scrollContainer setContentSize:CGSizeMake(kListView_Width+self.view.bounds.size.width, self.view.bounds.size.height)];
}
When user selects new item from the list, you can swap DetailViewControllers as below
- (void) replaceEpisodeControllerWith:(DetailViewController *)detailViewController {
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[UIView transitionFromView:currentDetailViewController.view
toView:detailViewController.view
duration:0.0
options:UIViewAnimationOptionTransitionNone
completion:^(BOOL finished)
{
[currentDetailViewController.view removeFromSuperview];
[currentDetailViewController removeFromParentViewController];
[currentDetailViewController release];
currentDetailViewController = detailViewController;
}];
}
I don't have swift version of this.

How to embed a storyboard view controller in an NSScrollView OS X (10.10) to make a complex inspector view?

I'm looking at WWDC 2014 video, "212: Storyboards and controllers on OS X". In this video they claim that Pages UI does/could be arranged using Storyboards on OS X (see below).
However, in Pages UI the inspector view is very long and is embedded in a scroll view (you can verify this my two-finger scrolling in Page.app inspector view), also some inspector items are themselves contained in (some type of custom) disclosure view. It doesn't seem to be possible to embed a storyboard view controller in scroll view because there is no corresponding to "scroll view controller" class. Is that right?
How can a storyboard view controller's view be embedded in a scroll view on a storyboard?
I have tried direct embedding at run time, however, this is very hackish and does't work reliably (problems with auto-layout). This route still might be possible, but I wanted to get advice before going too far. For real UI it might be the case of falling back to XIBs.
- (void)viewDidLoad {
[super viewDidLoad];
// Swap the view controllers' view for a scroll view
NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame:self.view.frame];
scrollView.documentView = self.view;
scrollView.drawsBackground = NO;
self.view = scrollView;
}
I think this answer is not really solving your problem but maybe helps understanding what is up with storyboards and scrollviews. I think Apple still has to fix some storyboard issues. I tried to use a collection view with storyboards, but it's impossible to connect the collectionViewItem in interface builder (which is happening automatically with xibs).
Here is an example with collection views:
Drag and Drop the collection view to a viewController. You will see a collection view and a collectionViewItem appearing. But the collection view item is NOT connected to the collection view. If you try this using IB, nothing happens.
In Identity inspector of IB assign a Soryboard ID. It's a random name which will be used in the code later. Here I am using "MyCollectionView"
If using swift, select your projects name in Module. The code is mostly the same for objC
Connect the collection view to the ViewController, containing the collection view
Do some coding to connect the Collection View item
class IVMyCollectionViewController: NSViewController, NSCollectionViewDelegate {
// manual connections to collection view (which is not working in IB)
#IBOutlet weak var collectionView: NSCollectionView!
class var sharedInstance : IVMyCollectionViewController {
struct Static {
static var instance:IVMyCollectionViewController? = nil
}
if Static.instance != nil {
return Static.instance!
} else {
let bundle = NSBundle.mainBundle()
let infoDict = bundle.infoDictionary!
let sbName = infoDict["NSMainStoryboardFile"] as String
let storyboard = NSStoryboard(name:sbName, bundle:bundle)!
let vcName = "MyCollectionView"
let sbInstance = storyboard.instantiateControllerWithIdentifier(vcName) as IVMyCollectionViewController
Static.instance = sbInstance
return sbInstance
}
}
// implement your controller
}
That means that some UI elements are not properly implemented yet. I would send a bug report to apple. There is still lots of things missing in interface builder.
Right now I would use a mixture of storyboard and xibs to abuse the storyboard in a way like above, by instantiating the connection in the constructor of the controller. You can use the storyboardID to launch views and other views or load from xibs. You can place viewControllers inside a storyboard without connections (segues) to create a pool of views that can be used like xibs. (A viewController is more or less the same like a xib)
// objC
DetailViewController* controller = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
or instantiate using the storyboardID like above.
Try to create a scroll view in storyboard. Create the views which you like to be shown in viewControllers for each view. Your scrollviews view controller should have a connection to the scroll view itself. In the following example the scroll view's outlet is named "self.contentView":
// instantiate a view controller for your scrolling view
self.scrollingViewController = [[ScrollingViewController alloc] initWithNibName:#"ScrollingView" bundle:nil];
// or do the same with storyboards by instantiating view controllers by ID
self.scrollingViewController = [myStoryboard instantiateControllerWithIdentifier:#"MyScrollingViewID"];
// Then set the view from the controller as content view
[self.contentView setDocumentView:self.scrollingViewController.view];
[self.contentView.contentView scrollPoint:NSMakePoint(0., self.scrollingViewController.view.frame.size.height)];
It's exactly like mixing up objective C and swift code. Apple seems to have entered a transition path which was not walked to the end.
In general you should think of View- or WindowControllers in storyboards is the same like a complete xib file. If you would like to use more views, use container views in storyboards. The FilesOwner in xibs is the viewController in storyboards. Container views offer you the ability to create a couple of views attached to a view controller. The segue mechanism is available for containers. I think the scroll view mechanism of OS X is not elegant. I struggled a lot with it, too.
Good luck!
Create the view that will be the document view of the scroll view.
Select that view
Go to Editor > Embed In > Scroll View
Based on this page of Scroll View Programming Guide for Mac.

What is the pattern of navigating between UIViewControllers in iOS?

I have a bunch of UIViewControllers subclasses (let's call them MainForm, DetailForm, MoreMinorDetails). Basically the idea is that AppDelegate class instantiates MainForm, user presses some type of button on MainForm and DetailForm comes up. Then on a button on the DetailForm launches MoreMinorDetails. And of course, I should be able to go back down to the MainForm.
Note that there aren't any UINavigationController objects anywhere in sight.
What is the accepted pattern to move between UIViewControllers in a manner described above?
Or am I going about it in the wrong way?
I'll be happy with either XCode or MonoTouch based explanation.
You can use a UINavigationController and hide the navigation bar:
self.navigationController.navigationBar.hidden = YES;
Then in your button's action just push the next view controller:
-(void)buttonAction:(id)sender
{
NextViewController *nextViewController = [[NextViewController alloc] init];
[self.navigationController pushViewController:nextViewController animated:YES];
}
To go back, use
-(void)goBack
{
[self.navigationController popViewControllerAnimated:YES];
}
To go to a certain view controller (you have to know exactly when it was pushed onto the navigation controller's stack):
-(void)goToViewController
{
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
}
Or to pop to your root view controller
[self.navigationController popToRootViewControllerAnimated:YES];
This way, you will obtain the UINavigationController's functionality and keep all the space in the view.
AngryHacker,
My simple suggestion is to follow zoul one. I think the simplest way to achieve what you want it' to create a UINavigationController and use it as a containment controller for other controllers.
So, the way could be create a UINavigationController in the AppDelegate and set it as the rootViewController for your window. When you create a UINavigationController you can pass to it a root controller (in this case MainForm).
In MT it looks like the following (do not trust the code because I've written it by hand)
private UINavigationController navController;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
navController = new UINavigationController(new MainForm());
window.RootViewController = navController;
window.MakeKeyAndVisible ();
return true;
}
Now, when you launch the app you will see the MainForm's view and will able to allow navigation among different controllers.
For example, within MainForm you can go to DetailForm like:
this.NavigationController.PushViewController(new DetailForm(), true);
The same applies within DetailForm to MoreMinorDetails.
To go one step back, for example from MoreMinorDetails to DetailForm use
this.NavigationController.PopViewControllerAnimated(false);
To go to the the root controller (MainForm) within DetailForm or MoreMinorDetails use
this.NavigationController.PopToRootViewControllerAnimated(false);
About the space, it's not a problem. I guess you have two ways. The first is to move the bar items you have created within the navigation controller bar. In each controller you can decide what buttons make visible or not. The second is to hide completely the navigation bar and use the button you've already created.
In both ways you can attach actions to these buttons and allow the navigation between controllers. Furthermore, if you choose the first you can also hide the back button for your navigation bar.
A simple note to take in mind is the following:
Since the navigation bar is unique for a UINavigationController, the bar will maintains its state for all the controllers you push in the navigation controller. To explain the concept suppose you have two controllers, say A and B. You first push A and in its ViewWillAppear method you hide a button. When you push B, the button still remains not visible. If you want to unhide the button in B, you can play with its ViewWillAppear method (like before) and so on...
If you don't want to play with UINavigationController you should take a look to new view controller containment functionality provided by UIViewController class. This applies only from iOS >= 5. You can obtain the same effect of UINavigationController mechanism but it could be more difficult to achieve.
Hope that helps.

Monotouch addsubview animation

I have my navigation controller and my view controller. I can't seem to get a simple transition between those views when I push a button in the navigation bar. It now just pops up.
When I push the button in the navigation controller, it calls the code below in the main file.
public void GoToViewController()
{
window.AddSubview(theViewController.View);
}
I have been calling:
UIView.SetAnimationTransition(UIViewAnimationTransition.None, spct.View, true);
which works, but I would like to let this view simple appear from the right, over the other view (just like the navigation controller does with its views).
You should just use UINavigationController.
Making the transition should be fairly easy, and is worth it over trying to recreate what Apple has already built.
For each of your view controllers, you should be able to change their base class to UINavigationController--or just change their type to UINavigationController if you did not subclass them. After that, you should just have to replace your custom transition code to use PushViewController(), PopViewControllerAnimated(), etc.
Using UINavigationController is fairly simple in general.

Resources