拆分视图控制器错误?

Posted

技术标签:

【中文标题】拆分视图控制器错误?【英文标题】:SplitViewController BUG? 【发布时间】:2013-04-30 17:05:35 【问题描述】:

我建立了一个非常简单的 ios splitView Controller 项目,它有一个非常奇怪的错误。如果您在横向模式下启动应用程序,单击一个按钮以打开另一个视图,旋转到纵向,然后返回到起始视图 - 左侧的表格菜单不应该是可见的,但它是......奇怪的是你不能与它互动,这让我相信它不是真的在那里,而是某种人工制品。

请注意,这只会在您第一次执行此操作时发生,然后再也不会发生,直到您以横向方式重新启动应用程序。

MasterViewController:

#import "MasterViewController.h"

#import "DetailViewController.h"


@interface MasterViewController () 
    NSMutableArray *_objects;


@property (nonatomic, strong)UITableView *menu;

@end

@implementation MasterViewController

- (void)awakeFromNib

    self.clearsSelectionOnViewWillAppear = NO;
    self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
    [super awakeFromNib];


- (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;
    self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];




- (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 _objects.count;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

    NSDate *object = _objects[indexPath.row];
    cell.textLabel.text = [object description];
    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

DetailViewController:

#import "DetailViewController.h"
#import "StandardViewViewController.h"


@interface DetailViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;

-(IBAction)buttonTapped:(id)sender;

- (void)configureView;
@end

@implementation DetailViewController

#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.


#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;


-(IBAction)buttonTapped:(id)sender

    StandardViewViewController *sv = [[StandardViewViewController alloc]initWithNibName:@"StandardViewViewController" bundle:nil];
    [self.splitViewController presentViewController:sv animated:YES completion:nil];



@end

这是一个已知的错误吗?有解决办法吗?

【问题讨论】:

【参考方案1】:

虽然不漂亮,但建议的解决方案 here 有效。 这就是您实施解决方案的方式:

-(IBAction)buttonTapped:(id)sender

    StandardViewViewController *sv = [[StandardViewViewController alloc] initWithNibName:nil bundle:nil];
    sv.modalPresentationStyle = UIModalPresentationPageSheet; // <-- Add this
    [self.splitViewController presentViewController:sv animated:YES completion:nil];

在 StandardViewController.m 中添加:

-(void)viewWillLayoutSubviews 
    self.view.bounds = [StandardViewViewController screenBoundsForCurrentOrientation];
    [super viewWillLayoutSubviews];


+(CGRect)screenBoundsForCurrentOrientation 
    return [self screenBoundsForOrientation:[UIApplication sharedApplication].statusBarOrientation];


+(CGRect)screenBoundsForOrientation:(UIInterfaceOrientation)orientation 

    UIScreen *screen = [UIScreen mainScreen];
    CGRect fullScreenRect = screen.bounds; //implicitly in Portrait orientation.

    if(orientation == UIInterfaceOrientationLandscapeRight || orientation ==  UIInterfaceOrientationLandscapeLeft)
        CGRect temp = CGRectZero;
        temp.size.width = fullScreenRect.size.height;
        temp.size.height = fullScreenRect.size.width;
        fullScreenRect = temp;
    

    return fullScreenRect;

为了让它更漂亮,您可以将 StandardViewController 的代码放入一个新的类中,StandardViewController 可以在该类上进行扩展。

而且,是的,这看起来像一个错误。

【讨论】:

以上是关于拆分视图控制器错误?的主要内容,如果未能解决你的问题,请参考以下文章

拆分视图控制器仅显示一个视图(Xcode 6)

如何为拆分视图控制器创建启动页面

应用程序尝试以模态方式呈现拆分视图控制器(我的应用程序中没有拆分视图)

简单视图拆分视图ios编程

从拆分视图控制器的详细视图中调用主视图控制器

拆分视图控制器 - 将表视图设置为初始视图控制器