2011-10-25 23 views
7

Bối cảnh & Mục tiêu: Tôi có một ứng dụng iPad dựa trên UISplitViewController - cho đến bây giờ nó hỗ trợ 4 định hướng nhưng bây giờ tôi muốn khóa nó xuống chỉ phong cảnh. Tôi đã thay đổi shouldAutorotateToInterfaceOrientation của bộ điều khiển chế độ xem trái để chỉ hỗ trợ chế độ nằm ngang, nhưng điều này sẽ dừng việc viewWillAppear khỏi bị gọi.ViewWillAppear không nhận được gọi với UISplitViewController

Chi tiết: My xem điều khiển iPad được tổ chức như sau:

window 
`-- splitVC (UISplitViewController) 
    `-- rootNav (UINavigationController) 
     `-- hvc (HostManagerViewController, derived from UIViewController) 
    `-- detailViewController (DetailViewController, derived from UIViewController) 

này được thực hiện trong App delegate như dưới đây:

- (BOOL)application:(UIApplication *)application 
     didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    HostManagerViewController *hvc = [[[HostManagerViewController alloc] 
             initWithNibName:nil bundle:nil] autorelease]; 
    self.detailViewController = [[[DetailViewController alloc] 
           initWithNibName:nil bundle:nil] autorelease]; 
    UINavigationController *rootNav = [[[UINavigationController alloc] 
             initWithRootViewController:hvc] autorelease]; 
    UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease]; 
    [splitVC setViewControllers:[NSArray arrayWithObjects:rootNav, 
           detailViewController, nil]]; 

    splitVC.delegate = detailViewController; 
    [window addSubview:splitVC.view]; 
    [window setRootViewController:splitVC]; 
    return YES; 
} 

viewWillAppear được gọi khi cả hai DetailViewController.mHostManagerViewController.m chứa

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; 
} 
Console output: 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Hostmanager: Viewdidload 
Should rotate called to hostmanager with 1 
Hostmanager: viewwillappear 

Nhưng khi tôi thay đổi mã của HostManagerViewController thành

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 

thì 'viewWillAppear` của HostManagerViewController không được gọi. Bảng điều khiển đầu ra

Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation) 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Hostmanager: Viewdidload 
Should rotate called to hostmanager with 1 

Chỉ chế độ Landscape được hỗ trợ trong Info.plist

EDIT: thông điệp chèn NSLog để theo dõi shouldAutorotateToInterfaceOrientation, viewWillAppearViewDidLoad

+0

bạn có thể tải lên mẫu của dự án này không? – ACBurk

+0

bạn đang chạy phiên bản iOS nào? – ACBurk

+0

Tôi đang sử dụng 4.3. Giảm nó vào một testcase nhỏ hơn có thể được thực hiện. Tôi tải nó lên ở đâu? –

Trả lời

8

Tôi hỏi những gì phiên bản iOS bạn đang sử dụng vì tôi đã cố gắng để tạo ra một bản tái tạo đơn giản của vấn đề của bạn và tìm thấy hành vi khác nhau giữa 4.3 và 5.0.Nó thực sự làm cho tất cả các cuộc gọi chính xác trong 5.0. Tôi tin rằng điều này chỉ đơn giản là một lỗi với UISplitviewController. Bộ điều khiển Splitview khá là lỗi. Câu trả lời của aopsfan không giải quyết được vấn đề (Tôi đã xác nhận điều này). Tôi sẽ đề nghị subclassing uisplitviewcontroller, và trọng viewWillAppear bộ điều khiển splitview của, viewDidAppear như vậy:

#import "testSplitViewController.h" 

@implementation testSplitViewController 

-(void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    NSString *reqSysVer = @"5.0"; 
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) 
     [[[self viewControllers] objectAtIndex:0] viewWillAppear:animated]; 
} 

-(void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 

    NSString *reqSysVer = @"5.0"; 
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) 
     [[[self viewControllers] objectAtIndex:0] viewDidAppear:animated]; 
} 
@end 

Bạn cần phải kiểm tra các số phiên bản để bạn không thực hiện cuộc gọi viewDidAppear hai lần.

Hoặc chỉ cần đi với 5.0 trở lên nếu bạn có thể, vì lỗi này có vẻ đã được sửa.

+0

Có, có và có! Dường như có lỗi trong bộ điều khiển chế độ xem chia tách - do đó việc buộc 'viewWillAppear' trên các chế độ xem trẻ em từ chế độ xem tách có vẻ là giải pháp thay thế. Cảm ơn nhiều, @ACBurk –

+0

Có cách nào tổng quát hơn kiểm tra phiên bản trước khi gọi 'viewDidAppear' không? Có 'isViewLoaded', nhưng cũng có một loại' hasViewAppeared' của một cuộc gọi? –

+0

Không phải là tôi biết ngoài đỉnh đầu của tôi, nhưng tôi sẽ xem xét nó – ACBurk

3

Về cơ bản, vì một UISplitViewController có hai phần, bạn cần một triển khai phổ biến của shouldAutorotate. Tôi cho rằng việc giải quyết vòng xoay của bộ điều khiển xem riêng lẻ có thể gây ra một số tác động phụ lạ - mặc dù xin lưu ý rằng tôi không thể sao chép vấn đề viewWillAppear của bạn, vì vậy giải pháp này thực sự là một sự đoán.

Tôi khuyên bạn nên tạo một lớp con chết đơn giản gồm UISplitViewController. Đặt tên cho nó là "SplitViewController", và trong đó là .m tập tin, xóa tất cả mọi thứ trừ shouldAutorotate, mà sẽ trông như thế này:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 

Bây giờ thay đổi mã shouldAutorotate của bạn trong HostManagerViewControllerDetailViewController trở lại:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; 
} 

Bây giờ , trong ủy quyền ứng dụng của bạn, hãy sử dụng lớp này thay vì UISplitViewController. Điều này nên (có thể) khắc phục vấn đề của bạn.

+0

Tôi cũng đồng ý với aopsfan, bạn không nên chặn điều này trên mỗi bộ điều khiển xem, bạn nên chặn nó trong bộ điều khiển gốc (UISplitViewController trong trường hợp của bạn). – alinoz

+0

+1 Cảm ơn bạn đã đề xuất điều này. Thật không may, nó không giải quyết được vấn đề –

0

Bạn đặt các đại biểu của UISplitViewControler đến detailViewController

splitVC.delegate = detailViewController; 

Tôi nghĩ rằng nơi tốt nhất để ngăn chặn việc quay sẽ được trong DetailViewController và không nằm trong HostManagerViewController. Tôi sẽ thay đổi - shouldAutorotateToInterfaceOrientation trong HostManagerViewController trở allways YES và trong DetailViewController tôi sẽ thêm:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return (UIInterfaceOrientationIsLandscape == interfaceOrientation); 
} 
Các vấn đề liên quan