📜 ⬆️ ⬇️

We write the analog of UISplitViewController

UISplitViewController turned out to be a great and beautiful thing, but it has one major drawback: “The split view controller is not always available. You should never see a tab bar interface. ”The UISplitViewController view should always be the main view of the application, so you cannot cram a new UISplitViewController into the navigation or tab bar.


Therefore, we will write our analogue UISplitViewController'a with blackjack and whores for use in conjunction with the navigation or tab bar.
Create a Window-based application and call it ipad_split_view.

Create a class MySplitViewController:
@ interface MySplitViewController : UIViewController
{
UIViewController * detailViewController;
UIViewController * masterViewController;
UIPopoverController * popoverController;

UINavigationBar* navigationBar;
}
@property (nonatomic, retain) IBOutlet UINavigationBar* navigationBar;
@property (nonatomic, retain) IBOutlet UIViewController * detailViewController;
@property (nonatomic, retain) IBOutlet UIViewController * masterViewController;

-( void ) layoutViewsToInterfaceOrientation:(UIInterfaceOrientation)newInterfaceOrientation;
-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
-(IBAction) showRootPopup: (id) sender;

@end


* This source code was highlighted with Source Code Highlighter .

Add a couple of defaults to the implementation:
#define BAR_HEIGHT 49.f
#define SCREEN_HEIGHT 1024.f
#define SCREEN_WIDTH 768.f
#define MASTER_WIDTH 320.f


* This source code was highlighted with Source Code Highlighter .

')
Override the setMasterViewController and setDetailViewController methods:
-( void ) setDetailViewController:(UIViewController *) aDetailViewController
{
detailViewController = [aDetailViewController retain];
[self.view addSubview:detailViewController.view];
[self layoutViewsToInterfaceOrientation:self.interfaceOrientation];
}

-( void ) setMasterViewController:(UIViewController *) aMasterViewController
{
masterViewController = [aMasterViewController retain];
[self.view addSubview:masterViewController.view];
if (popoverController)
{
[popoverController release];
}
popoverController = [[UIPopoverController alloc] initWithContentViewController:masterViewController];
[self layoutViewsToInterfaceOrientation:self.interfaceOrientation];
}

* This source code was highlighted with Source Code Highlighter .


And create a layoutViewsToInterfaceOrientation method. It will be called when the orientation changes:
-( void ) layoutViewsToInterfaceOrientation:(UIInterfaceOrientation)newInterfaceOrientation
{
if ((newInterfaceOrientation == UIInterfaceOrientationPortrait ||
newInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))
{
[self.view addSubview:navigationBar];
navigationBar.frame = CGRectMake(0, 0, SCREEN_WIDTH, BAR_HEIGHT);
[masterViewController.view removeFromSuperview];
detailViewController.view.frame = CGRectMake(0, BAR_HEIGHT, SCREEN_WIDTH, self.view.frame.size.height-BAR_HEIGHT);
}
else
{
[navigationBar removeFromSuperview];
[self.view addSubview:masterViewController.view];
masterViewController.view.frame = CGRectMake(0, 0, MASTER_WIDTH, self.view.frame.size.height);
detailViewController.view.frame = CGRectMake(MASTER_WIDTH, 0, SCREEN_HEIGHT-MASTER_WIDTH, self.view.frame.size.height);
}
}

* This source code was highlighted with Source Code Highlighter .


Let's override the method shouldAutorotateToInterfaceOrientation - let it return YES to support all orientations.
Also, override the didRotateFromInterfaceOrientation method:
-( void )didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
if ([popoverController isPopoverVisible])
{
[popoverController dismissPopoverAnimated:YES];
}
[masterViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[detailViewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self layoutViewsToInterfaceOrientation:self.interfaceOrientation];
}

* This source code was highlighted with Source Code Highlighter .


Create a showRootPopup method - it will be called when you click on the “More” button in the portrait orientation:
-(IBAction) showRootPopup: (id) sender
{
[popoverController setContentViewController:masterViewController];
[popoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionUp
animated:YES];
}

* This source code was highlighted with Source Code Highlighter .


We will create XIB for this class and link interface elements and events — this is rather trivial and does not require an explanation.

Next, create the RootViewController class:
@ interface RootViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource>
{
DetailViewController *detailViewController;
NSArray * someArray;
}

@property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;

@end

* This source code was highlighted with Source Code Highlighter .


In the implementation of this class, everything is very simple and ordinary. Of interest is only the following code:
- ( void )tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

/*
When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
*/
detailViewController.detailItem = [someArray objectAtIndex:indexPath.row];
}


* This source code was highlighted with Source Code Highlighter .

Also create for this class XIB.

Let's proceed to the creation of the class DetailViewController:
@ interface DetailViewController : UIViewController
{
id detailItem;
UIWebView *webView;
}

@property (nonatomic, retain) id detailItem;
@property (nonatomic, retain) IBOutlet UIWebView *webView;;

@end

* This source code was highlighted with Source Code Highlighter .


In the implementation, we turn our attention to 2 methods:
- ( void )setDetailItem:(id)newDetailItem
{
if (detailItem != newDetailItem)
{
[detailItem release];
detailItem = [newDetailItem retain];

// Update the view.
[self configureView];
}
}

- ( void )configureView {
// Update the user interface for the detail item.
NSURL * url = [NSURL URLWithString:detailItem];
NSURLRequest * urlRequest = [NSURLRequest requestWithURL:url];
[webView loadRequest:urlRequest];
}

* This source code was highlighted with Source Code Highlighter .


As usual, we create XIB and links in it.

It remains only to svzyat everything written. The ipad_split_viewAppDelegate class will look like this:
@ class MySplitViewController;

@ interface ipad_split_viewAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
MySplitViewController *splitViewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet MySplitViewController *splitViewController;

@end

* This source code was highlighted with Source Code Highlighter .


In the implementation, override the initialization:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RootViewController *rootViewController = [[[RootViewController alloc] initWithNibName: @"RootViewController" bundle:nil] autorelease];
DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName: @"DetailViewController" bundle:nil] autorelease];

rootViewController.detailViewController = detailViewController;

splitViewController.masterViewController = rootViewController;
splitViewController.detailViewController = detailViewController;

[window addSubview:splitViewController.view];
[window makeKeyAndVisible];

return YES;
}

* This source code was highlighted with Source Code Highlighter .


It remains only to connect interface elements in MainWindow.xib.

Little advice. If a class is not available for selection in Interface Builder, simply drag the header file onto the Document window.

Source code can be downloaded here.
The final view of our homemade split view: image
image

Source: https://habr.com/ru/post/92928/


All Articles