2011-11-08 25 views
13

Như đã có been reported trong các câu hỏi khác ở đây trên SO, iOS 5 thay đổi cách quay vòng cuộc gọi cho bộ điều khiển chế độ xem chia được gửi theo ghi chú phát hành này. Đây không phải là một dupe (tôi nghĩ), như tôi không thể tìm thấy một câu hỏi trên SO mà đề với cách điều chỉnh sử dụng bộ điều khiển chia xem trong iOS 5 để đối phó với sự thay đổi:iOS5 ngắt cuộc gọi quay vòng UISplitViewController, cách gọi thủ công?

Quay lại cuộc gọi trong iOS 5 không được áp dụng để xem bộ điều khiển mà được hiển thị trên toàn màn hình. Điều này có nghĩa là nếu mã của bạn trình bày bộ điều khiển chế độ xem trên một bộ điều khiển chế độ xem khác, sau đó người dùng sau đó quay thiết bị theo một hướng khác, khi loại bỏ, bộ điều khiển cơ bản (tức là bộ điều khiển trình bày) sẽ không nhận bất kỳ vòng quay nào callbacks. Tuy nhiên, lưu ý rằng trình điều khiển trình bày sẽ nhận được cuộc gọi viewWillLayoutSubviews khi nó là được hiển thị lại và thuộc tính interfaceOrientation có thể được truy vấn từ phương pháp này và được sử dụng để đặt bộ điều khiển chính xác.

Tôi gặp sự cố khi định cấu hình nút bật lên trong bộ điều khiển chế độ xem chia tách gốc của tôi (trình điều khiển được hiển thị để hiển thị khung bên trái trong cửa sổ bật lên khi bạn ở chế độ dọc). Đây là cách tự khởi động ứng dụng của tôi đã từng làm việc trong iOS 4.x khi điện thoại đang ở chế độ nằm ngang:

  1. Cài đặt bộ điều khiển xem chia thành cửa sổ với [window addSubview:splitViewController.view]; [window makeKeyAndVisible];. Điều này dẫn đến việc gọi số splitViewController:willHideViewController:withBarButtonItem:forPopoverController: trên đại biểu (ví dụ: mô phỏng cảnh quan -> xoay dọc) ngay cả khi thiết bị đã ở chế độ ngang.

  2. Trình bày phương thức toàn màn hình (màn hình tải của tôi) bao phủ hoàn toàn chế độ xem chia nhỏ bên dưới.

  3. Hoàn tất tải và loại bỏ phương thức tải màn hình. Vì thiết bị ở chế độ nằm ngang, khi bộ điều khiển chia tách được tiết lộ, điều này sẽ khiến cho splitViewController:willShowViewController:invalidatingBarButtonItem: được gọi trên đại biểu (ví dụ mô phỏng chân dung -> xoay ngang), do đó làm mất hiệu lực mục nút thanh, xóa nó khỏi bên phải của chế độ xem chia tách và để lại cho chúng tôi nơi chúng tôi muốn. Hoan hô!

Vì vậy, vấn đề là vì sự thay đổi mô tả trong đó phát hành lưu ý, bất cứ điều gì xảy ra trong nội bộ trong iOS 4.3 có kết quả trong splitViewController:willShowViewController:invalidatingBarButtonItem: được gọi là không còn xảy ra trong iOS 5. Tôi cố gắng subclassing UISplitViewController vì vậy tôi có thể cung cấp triển khai tùy chỉnh viewWillLayoutSubviews như được đề xuất bởi ghi chú phát hành, nhưng tôi không biết cách tạo lại chuỗi sự kiện nội bộ mong muốn mà iOS 4 kích hoạt. Tôi đã thử điều này:

- (void) viewWillLayoutSubviews 
{ 
    [super viewWillLayoutSubviews]; 

    UINavigationController *rightStack = [[self viewControllers] objectAtIndex:1]; 
    UIViewController *rightRoot = [[rightStack viewControllers] objectAtIndex:0]; 
    BOOL rightRootHasButton = ... // determine if bar button item for portrait mode is there 

    // iOS 4 never goes inside this 'if' branch 
    if (UIInterfaceOrientationIsLandscape([self interfaceOrientation]) && 
     rightRootHasButton) 
    { 
     // Manually invoke the delegate method to hide the popover bar button item 
     [self.delegate splitViewController:self 
        willShowViewController:[[self viewControllers] objectAtIndex:0] 
       invalidatingBarButtonItem:rightRoot.navigationItem.leftBarButtonItem]; 
    } 
} 

Điều này chủ yếu hoạt động, nhưng không phải 100%. Vấn đề là tự gọi phương thức ủy nhiệm không thực sự làm mất hiệu lực mục nút thanh, vì vậy lần đầu tiên bạn xoay sang dọc, hệ thống cho rằng mục nút thanh vẫn được cài đặt đúng cách và không thử cài đặt lại. Nó chỉ sau khi bạn xoay một lần nữa để cảnh quan và sau đó trở lại chân dung có hệ thống đã trở lại vào đúng nhà nước và thực sự sẽ cài đặt các mục thanh popover trong chế độ chân dung.

Dựa trên this question, tôi cũng đã thử gọi tất cả các cuộc gọi lại theo cách thủ công thay vì kích hoạt phương thức ủy nhiệm, ví dụ::

// iOS 4 never goes inside this 'if' branch 
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation]) && 
    rightRootHasButton) 
{ 
    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0]; 
    [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0]; 
    [self didRotateFromInterfaceOrientation:self.interfaceOrientation]; 
} 

Tuy nhiên điều này chỉ dường như gây ra một vòng lặp vô hạn trở lại vào viewWillLayoutSubviews :(

Có ai biết những gì cách chính xác để mô phỏng các sự kiện xoay iOS4 kiểu là cho một bộ điều khiển chia điểm cho rằng xuất hiện từ đằng sau một phương thức toàn màn hình? Hay bạn không nên mô phỏng chúng hoàn toàn và có cách tiếp cận thực hành tốt nhất đã trở thành tiêu chuẩn cho iOS5 không?

Bất kỳ trợ giúp nào thực sự đánh giá cao vì vấn đề này đang khiến chúng tôi không thể gửi iOS5 của mình phát hành bugfix cho App Store.

Trả lời

11

Tôi không biết đúng cách để xử lý tình huống này. Tuy nhiên, sau đây dường như được làm việc cho tôi trong iOS 5.

  1. Trong splitViewController:willHideViewController:withBarButtonItem:forPopoverController:, lưu trữ một tham chiếu đến barButtonItem trong một cái gì đó giống như self.barButtonItem. Di chuyển mã để hiển thị nút thành một phương thức riêng biệt, giả sử ShowRootPopoverButtonItem.

  2. Trong splitViewController:willShowViewController:invalidatingBarButtonItem:, hãy xóa tham chiếu self.barButtonItem. Di chuyển mã để hiển thị nút thành một phương thức riêng biệt, giả sử InvalidateRootPopoverButtonItem.

  3. Trong viewWillLayoutSubviews, tự hiển thị hoặc ẩn các nút tuỳ theo định hướng giao diện

Dưới đây là thực hiện của tôi viewWillLayoutSubviews. Lưu ý rằng việc gọi self.interfaceOrientation luôn quay trở lại chân dung, do đó việc sử dụng của tôi là statusBarOrientation.

- (void)viewWillLayoutSubviews 
{ 
    if (UIInterfaceOrientationIsPortrait(
     [UIApplication sharedApplication].statusBarOrientation)) 
    { 
     [self ShowRootPopoverButtonItem:self.barButtonItem]; 
    } 
    else 
    { 
     [self InvalidateRootPopoverButtonItem:self.barButtonItem]; 
    } 
} 
+1

Hey Noah - cảm ơn vì giải pháp - nó cũng làm việc cho tôi. Đó là một chút không may bởi vì viewWillLayoutSubviews được gọi là cách thường xuyên hơn so với các sự kiện quay, vì vậy nhồi nhét tất cả các nút ẩn/hiển thị logic trong đó có nghĩa là nó được chạy rất nhiều thường xuyên hơn, nhưng có vẻ như đây là cách iOS5-ish để làm công cụ này ngay bây giờ. – glenc

Các vấn đề liên quan