UISplitView

Discussion in 'iPhone/iPad Programming' started by RagingGoat, Jan 15, 2013.

  1. macrumors 6502

    Joined:
    Jun 21, 2010
    #1
    I am playing with a UISplitView and I'm having trouble getting anything to appear in the detail view. I have an array in my master view controller.

    Code:
    menu = [NSMutableArray arrayWithObjects:@"Home", @"Public Affairs", @"Action Alerts", @"Market Updates", @"Ag Stories", @"KFB News", @"Member Benefits", @"Monthly Video", @"Photos", @"Social Media", @"About Us", @"Contact Us", @"KYFB.com", nil];
    
    When a row is tapped it should show another view corresponding to the row in the detail view of the split view. I tried putting code into the didSelectRowAtIndexPath method but it just changes the master view and does nothing to the detail view.

    Any suggestions?
     
  2. macrumors demi-god

    KoolStar

    Joined:
    Oct 16, 2006
    Location:
    Kentucky
    #2
    Do you have a reference to the detailView in your masterview? You will need it in order to change out the views.

    Once you have that reference you can then change out the view/viewcontroller (not sure how you are setting your app up) on the didSelectRowAtIndex.
     
  3. macrumors 68030

    MattInOz

    Joined:
    Jan 19, 2006
    Location:
    Sydney
    #3
    The other way is to have a property on the DetailViewController that can be set to the detail Item selected by the user.

    Either way you still to get a reference to the detail view controller.
    If you have a reference to the splitViewController then you can get the detailViewController from there.
     
  4. macrumors demi-god

    KoolStar

    Joined:
    Oct 16, 2006
    Location:
    Kentucky
    #4
    This is also true, you would want that property to either be a uiviewcontroller so you can use UIViewContainment to add it as a childview or you can replace self.view of the detail view controller, i would not recommend the later of the two. The UIViewContainmentProtocols are vary handy and allow your controllers to coexist in one view.
     
  5. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #5
    Here is what I currently have. Right now I'm wanting it so that when I select social media from the master view, it will go to the social networks table view in the detail view.

    Code:
    //
    //  KFBAppDelegate.m
    //  KYFB
    //
    //  Created by KFB on 1/15/13.
    //  Copyright (c) 2013 com.kfb. All rights reserved.
    //
    
    #import "KFBAppDelegate.h"
    #import "KFBMasterViewController.h"
    #import "KFBDetailViewController.h"
    
    @implementation KFBAppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
    
        KFBMasterViewController *masterViewController = [[KFBMasterViewController alloc] initWithNibName:@"KFBMasterViewController" bundle:nil];
        UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
    
        KFBDetailViewController *detailViewController = [[KFBDetailViewController alloc] initWithNibName:@"KFBDetailViewController" bundle:nil];
        UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
    
        masterViewController.detailViewController = detailViewController;
    
        self.splitViewController = [[UISplitViewController alloc] init];
        self.splitViewController.delegate = detailViewController;
        self.splitViewController.viewControllers = @[masterNavigationController, detailNavigationController];
        self.window.rootViewController = self.splitViewController;
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    
    @end
    
    Code:
    //
    //  KFBMasterViewController.h
    //  KYFB
    //
    //  Created by KFB on 1/15/13.
    //  Copyright (c) 2013 com.kfb. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @class KFBDetailViewController;
    
    @interface KFBMasterViewController : UITableViewController
    
    @property (strong, nonatomic) KFBDetailViewController *detailViewController;
    
    @end
    
    Code:
    //
    //  KFBMasterViewController.m
    //  KYFB
    //
    //  Created by KFB on 1/15/13.
    //  Copyright (c) 2013 com.kfb. All rights reserved.
    //
    
    #import "KFBMasterViewController.h"
    #import "KFBDetailViewController.h"
    #import "SocialNetworks.h"
    
    @interface KFBMasterViewController () {
        NSMutableArray *_objects;
        NSMutableArray *menu;
    }
    @end
    
    @implementation KFBMasterViewController
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            self.title = NSLocalizedString(@"Master", @"Master");
            self.clearsSelectionOnViewWillAppear = NO;
            self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
        }
        return self;
    }
    							
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        // self.navigationItem.leftBarButtonItem = self.editButtonItem;
    
        // UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
        // self.navigationItem.rightBarButtonItem = addButton;
        
        menu = [NSMutableArray arrayWithObjects:@"Home", @"Public Affairs", @"Action Alerts", @"Market Updates", @"Ag Stories", @"KFB News", @"Member Benefits", @"Monthly Video", @"Photos", @"Social Media", @"About Us", @"Contact Us", @"KYFB.com", nil];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void)insertNewObject:(id)sender
    {
        if (!_objects) {
            _objects = [[NSMutableArray alloc] init];
        }
        [_objects insertObject:[NSDate date] atIndex:0];
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
    
    #pragma mark - Table View
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return menu.count;
    }
    
    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    
    
        // NSDate *object = _objects[indexPath.row];
        // cell.textLabel.text = [object description];
        cell.textLabel.text = [menu objectAtIndex:indexPath.row];
        return cell;
    }
    
    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // Return NO if you do not want the specified item to be editable.
        return YES;
    }
    
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            [_objects removeObjectAtIndex:indexPath.row];
            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
        } else if (editingStyle == UITableViewCellEditingStyleInsert) {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
        }
    }
    
    /*
    // Override to support rearranging the table view.
    - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
    {
    }
    */
    
    /*
    // Override to support conditional rearranging of the table view.
    - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // Return NO if you do not want the item to be re-orderable.
        return YES;
    }
    */
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // NSDate *object = _objects[indexPath.row];
        // self.detailViewController.detailItem = object;
    }
    
    @end
    
    Code:
    //
    //  KFBDetailViewController.h
    //  KYFB
    //
    //  Created by KFB on 1/15/13.
    //  Copyright (c) 2013 com.kfb. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface KFBDetailViewController : UIViewController <UISplitViewControllerDelegate>
    
    @property (strong, nonatomic) id detailItem;
    
    @property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
    @end
    
    Code:
    //
    //  KFBDetailViewController.m
    //  KYFB
    //
    //  Created by KFB on 1/15/13.
    //  Copyright (c) 2013 com.kfb. All rights reserved.
    //
    
    #import "KFBDetailViewController.h"
    
    @interface KFBDetailViewController ()
    @property (strong, nonatomic) UIPopoverController *masterPopoverController;
    - (void)configureView;
    @end
    
    @implementation KFBDetailViewController
    
    #pragma mark - Managing the detail item
    
    - (void)setDetailItem:(id)newDetailItem
    {
        if (_detailItem != newDetailItem) {
            _detailItem = newDetailItem;
            
            // Update the view.
            [self configureView];
        }
    
        if (self.masterPopoverController != nil) {
            [self.masterPopoverController dismissPopoverAnimated:YES];
        }        
    }
    
    - (void)configureView
    {
        // Update the user interface for the detail item.
    
        if (self.detailItem) {
            self.detailDescriptionLabel.text = [self.detailItem description];
        }
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        [self configureView];
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            self.title = NSLocalizedString(@"Detail", @"Detail");
        }
        return self;
    }
    							
    #pragma mark - Split view
    
    - (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
    {
        barButtonItem.title = NSLocalizedString(@"Master", @"Master");
        [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
        self.masterPopoverController = popoverController;
    }
    
    - (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {
        // Called when the view is shown again in the split view, invalidating the button and popover controller.
        [self.navigationItem setLeftBarButtonItem:nil animated:YES];
        self.masterPopoverController = nil;
    }
    
    @end
    
    Code:
    //
    //  SocialNetworks.m
    //  KFBNewsroom
    //
    //  Created by Adam Rayborn on 10/18/12.
    //  Copyright (c) 2012 com.kfb. All rights reserved.
    //
    
    #import "SocialNetworks.h"
    
    @interface SocialNetworks ()
    
    @end
    
    @implementation SocialNetworks
    {
        NSMutableArray *mbTableData;
    }
    
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
    {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
        mbTableData = [NSMutableArray arrayWithObjects:@"Facebook", @"Twitter", @"YouTube", nil];
        self.title = @"Social Networks";
    }
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return [mbTableData count];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *mbTableIdentifier = @"SimpleTableItem";
        
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:mbTableIdentifier];
        
        if (cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:mbTableIdentifier];
            cell.textLabel.font=[UIFont systemFontOfSize:16.0];
        }
        
        // cell.backgroundView = [[CustomCellBackground alloc] init];
        // cell.selectedBackgroundView = [[CustomCellBackground alloc] init];
        cell.textLabel.backgroundColor = [UIColor clearColor];
        cell.textLabel.highlightedTextColor = [UIColor darkGrayColor];
        
        cell.textLabel.text = [mbTableData objectAtIndex:indexPath.row];
        return cell;
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        /*
        if (indexPath.row == 0)
        {
            Facebook *facebook = [[Facebook alloc] initWithNibName:@"Facebook" bundle:[NSBundle  mainBundle]];
            [self.navigationController pushViewController:facebook animated:YES];
        }
        else if (indexPath.row == 1)
        {
            Twitter *twitter = [[Twitter alloc] initWithNibName:@"Twitter" bundle:[NSBundle  mainBundle]];
            [self.navigationController pushViewController:twitter animated:YES];
        }
        else if (indexPath.row == 2)
        {
            YouTube *youTube = [[YouTube alloc] initWithNibName:@"YouTube" bundle:[NSBundle  mainBundle]];
            [self.navigationController pushViewController:youTube animated:YES];
        }
        */
        
    }
    
    
    @end
    
     
  6. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    Code:
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // NSDate *object = _objects[indexPath.row];
        // self.detailViewController.detailItem = object;
    }
    Your KFBMasterViewController's didSelectRowAtIndexPath: is not doing anything. What do you think it should be doing?
     
  7. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #7
    I tried something like this (which is what I'm doing in an iPhone version of my app), but it just changes the Master view. I'm not sure how to connect it to the detail view.

    Code:
    if (indexPath.row == 0)
        {
            Facebook *facebook = [[Facebook alloc] initWithNibName:@"Facebook" bundle:[NSBundle  mainBundle]];
            [self.navigationController pushViewController:facebook animated:YES];
        }
    
     
  8. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #8
    The code you had before, that was commented out, should give you some idea how to handle the detail view.
     
  9. macrumors 68030

    MattInOz

    Joined:
    Jan 19, 2006
    Location:
    Sydney
    #9
    It changes the masterView because that's what you told it do.
    If this code was in the DetailViewController it would then do what you want.
    If you un-comment the lines Dejo pointed to then walk them though what that code triggers. Hopefully from there you'll find where these lines need to go too get what you want.

    Hint: your if test is going to be very different.
     
  10. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #10
    In looking into this some more, I'm seeing a lot of examples doing it like this:

    Code:
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // NSDate *object = _objects[indexPath.row];
        // self.detailViewController.detailItem = object;
        
        UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
        
        if (indexPath.row == 9)
        {
            SocialNetworks *social = [[SocialNetworks alloc] initWithNibName:@"SocialNetworks" bundle:nil];
            detailViewController = social;
        }
    }
    
    but I can't seem to get this working either.
     
  11. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #11
    How is the detailViewController from your code snippet different from self.detailViewController?
     
  12. macrumors demi-god

    KoolStar

    Joined:
    Oct 16, 2006
    Location:
    Kentucky
    #12
    In his case detailViewController shouldn't work. It should be self.detailViewController or _detailViewController depending on how it was compiled.
     
  13. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #13
    Nice. :p

    You pretty much gave him the solution to that issue; I was hoping he would discover it on his own. I find self-discovery holds so much more weight than just being told the answer.
     
  14. macrumors demi-god

    KoolStar

    Joined:
    Oct 16, 2006
    Location:
    Kentucky
    #14
    Three days later and no reply. More of a lets hopefully close up the thread. So if anyone else was looking for the answer it was out there, but I understand what you mean.
     
  15. macrumors 68030

    MattInOz

    Joined:
    Jan 19, 2006
    Location:
    Sydney
    #15
    Isn't just replacing the detailViewController going to stuff up the splitView.
    The new controller isn't going to get set as splitView delegate.

    It'll work until the first time the user changes the detailView while in protrait.
     
  16. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #16
    Here is how I ultimately got it working.

    Code:
    [((UINavigationController *)[self.splitViewController.viewControllers lastObject]) pushViewController:[[SocialNetworks alloc]initWithNibName:@"SocialNetworks" bundle:nil] animated:YES];
    
     
  17. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #17
    Did you take note of MattInOz's warnings?
     
  18. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #18
    I guess i missed his post. I just read it and with my solution I'm seeing what he is talking about. With my implementation, when in portrait, you have to go back through your views in order to be able to tap the master button to open the master table view. I guess it's back to the drawing board.
     
  19. macrumors 68030

    MattInOz

    Joined:
    Jan 19, 2006
    Location:
    Sydney
    #19
    This is a new one for me, same result but different cause.
    Couple of questions.
    Do you want the user to be able to navigate detailViews without going back to the masterview or should they always go back to the masterView?

    If yes then you could pop off all the previous Views in the navigation controller, before you push the new one.

    The other question I had are all your detailViews Tableviews?
     
  20. thread starter macrumors 6502

    Joined:
    Jun 21, 2010
    #20
    I would like them to be able to navigate the individual detail views without going back to the master view. For example, in the social networks table view in the code I posted, the user will select a row and go to another view. I would like the user to be able to go back to the initial table view without using the master view.

    And no, not all of my detail views are table views.
     
  21. macrumors demi-god

    KoolStar

    Joined:
    Oct 16, 2006
    Location:
    Kentucky
    #21
    Wrap your detail view in a uinavigationcontroller, that way you can just push and pop views while in the detail view.
     

Share This Page