bác bỏModalViewControllerAnimated không được dùng nữa


103

Tôi vừa nâng cấp lên XCode 4.5 để cập nhật ứng dụng iOS của mình để chạy trên màn hình 4 inch cho iPhone 5, nhưng tôi gặp lỗi bản dựng cho biết dismissModalViewControllerAnimated:' is deprecated:

[self dismissModalViewControllerAnimated:NO];

Tôi đã thử cập nhật lên mức quá tải được đề xuất bằng trình xử lý hoàn thành (nhưng được đặt thành NULL) như thế này:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Nhưng sau đó dòng này có hai lỗi:

warning: 'TabBarController' may not respond to '-presentModalViewController:animated:completion:'
Instance method '-presentModalViewController:animated:completion:' not found (return type defaults to 'id')

Cảm ơn!

Câu trả lời:


307

Phương pháp mới là:

[self dismissViewControllerAnimated:NO completion:nil];

Từ modal đã bị loại bỏ; Như đã từng xảy ra đối với lệnh gọi API trình bày:

[self presentViewController:vc animated:NO completion:nil];

Các lý do đã được thảo luận trong Phiên 236 WWDC 2012 - Sự phát triển của bộ điều khiển chế độ xem trên video iOS . Về cơ bản, các bộ điều khiển chế độ xem được trình bày bởi API này không còn luôn là phương thức nữa, và vì chúng đã thêm một trình xử lý hoàn thành, nên đã đến lúc đổi tên nó.

Đáp lại bình luận từ Marc:

Cách tốt nhất để hỗ trợ tất cả các thiết bị 4.3 trở lên là gì? Phương pháp mới không hoạt động trong iOS4, nhưng phương pháp cũ không được dùng trong iOS6.

Tôi nhận ra rằng đây gần như là một câu hỏi riêng biệt, nhưng tôi nghĩ nó đáng được đề cập vì không phải ai cũng có tiền để nâng cấp tất cả các thiết bị của họ 3 năm một lần nên nhiều người trong chúng ta có một số thiết bị cũ hơn (trước 5.0). Tuy nhiên, tôi thấy rất khó khi phải nói điều đó, bạn cần cân nhắc xem nó có đáng được nhắm mục tiêu dưới 5.0 hay không. Có nhiều API mới và thú vị không có sẵn dưới 5.0. Và Apple liên tục làm cho việc nhắm mục tiêu họ trở nên khó khăn hơn; Ví dụ: hỗ trợ armv6 bị loại bỏ khỏi Xcode 4.5.

Để nhắm mục tiêu dưới 5,0 (miễn là khối hoàn thành bằng không) chỉ cần sử dụng respondsToSelectorphương thức tiện dụng :.

if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
    [self presentViewController:test animated:YES completion:nil];
} else {
    [self presentModalViewController:test animated:YES];
}

Đáp lại một bình luận khác từ Marc:

Đó có thể là khá nhiều câu lệnh If trong ứng dụng của tôi! ... Tôi đang nghĩ đến việc tạo một danh mục đóng gói mã này, liệu việc tạo một danh mục trên UIViewControler có khiến tôi bị từ chối không?

và một từ Full Decent:

... có cách nào để khiến điều đó không hiển thị cảnh báo trình biên dịch theo cách thủ công không?

Thứ nhất, không, tạo một danh mục trên UIViewController trong và ngoài chính nó sẽ không khiến ứng dụng của bạn bị từ chối; trừ khi phương thức danh mục đó được gọi là các API riêng tư hoặc thứ gì đó tương tự.

Phương pháp danh mục là một nơi cực kỳ tốt cho mã như vậy. Ngoài ra, vì sẽ chỉ có một lệnh gọi tới API không dùng nữa, nên sẽ chỉ có một cảnh báo trình biên dịch.

Để giải quyết nhận xét (câu hỏi) của Full Decent, có, bạn có thể chặn cảnh báo trình biên dịch theo cách thủ công. Đây là một liên kết đến một câu trả lời trên SO về chủ đề đó . Phương thức danh mục cũng là một nơi tuyệt vời để ngăn chặn cảnh báo trình biên dịch, vì bạn chỉ ngăn cảnh báo ở một nơi. Bạn chắc chắn không muốn đi xung quanh để làm im lặng trình biên dịch willy-nilly.

Nếu tôi viết một phương thức danh mục đơn giản cho điều này, nó có thể giống như thế này:

@implementation UIViewController (NJ_ModalPresentation)
-(void)nj_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    NSAssert(completion == nil, @"You called %@ with a non-nil completion. Don't do that!",NSStringFromSelector(_cmd));
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
        [self presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [self presentModalViewController:viewControllerToPresent animated:flag];
#pragma clang diagnostic pop
    }
}
@end

2
Cách tốt nhất để hỗ trợ tất cả các thiết bị 4.3 trở lên là gì? Phương pháp mới không hoạt động trong iOS4, nhưng phương pháp cũ không được dùng trong iOS6. Đá và một nơi khó?
Marc

@Marc Tôi đã thêm vào câu trả lời của mình để giải quyết mối quan tâm của bạn.
NJones

Cảm ơn. Đó có thể là khá nhiều câu lệnh If trong ứng dụng của tôi! Tôi đoán cách tiếp cận tương tự có thể hoạt động khi sử dụng thuộc tính 'modalViewController'. Tôi đang nghĩ đến việc tạo một danh mục đóng gói mã này, liệu việc tạo một danh mục trên UIViewControler có khiến tôi bị từ chối không?
Marc

Đối với mã, if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }có cách nào để khiến điều đó không hiển thị cảnh báo trình biên dịch theo cách thủ công không?
William Entriken

@FullDecent Có bạn có thể. Tôi đã chỉnh sửa câu trả lời của mình với một số thông tin về điều đó.
NJones

6

Bây giờ trong iOS 6 trở lên, bạn có thể sử dụng:

[[Picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];

Thay vì:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... Và bạn có thể sử dụng:

[self presentViewController:picker animated:YES completion:nil];

Thay vì

[self presentModalViewController:picker animated:YES];    

4

[self dismissModalViewControllerAnimated:NO]; đã không được dùng nữa.

Sử dụng [self dismissViewControllerAnimated:NO completion:nil];thay thế.


4

Sử dụng

[self dismissViewControllerAnimated:NO completion:nil];

3

Cảnh báo vẫn còn đó. Để loại bỏ nó, tôi đặt nó vào một bộ chọn như sau:

if ([self respondsToSelector:@selector(dismissModalViewControllerAnimated:)]) {
    [self performSelector:@selector(dismissModalViewControllerAnimated:) withObject:[NSNumber numberWithBool:YES]];
} else {
    [self dismissViewControllerAnimated:YES completion:nil];
}

Nó có lợi cho những người bị OCD như tôi;)


Bạn nên chuyển câu lệnh if vì tôi tin rằng một phương thức không dùng nữa sẽ không khiến respondsToSelectortrả về false. Do đó, cái mới dismissViewControllerAnimated:sẽ không bao giờ được gọi cho đến khi có bản cập nhật trong tương lai, nơi chúng có thể xóa dismissModalViewControllerAnimated:hoàn toàn.
Jsdodgers,

0

Đây là phiên bản presentViewController tương ứng mà tôi đã sử dụng nếu nó giúp ích cho những người mới khác như tôi:

if ([self respondsToSelector:@selector(presentModalViewController:animated:)]) {
    [self performSelector:@selector(presentModalViewController:animated:) withObject:testView afterDelay:0];
} else {
    [self presentViewController:configView animated:YES completion:nil];
}
[testView.testFrame setImage:info]; //this doesn't work for performSelector
[testView.testText setHidden:YES];

Tôi đã sử dụng ViewController 'nói chung' và có thể làm cho Chế độ xem phương thức xuất hiện khác nhau tùy thuộc vào những gì nó được gọi để làm (sử dụng setHidden và setImage). và mọi thứ đã hoạt động tốt trước đây, nhưng performanceSelector bỏ qua nội dung 'set', vì vậy, cuối cùng nó có vẻ là một giải pháp tồi nếu bạn cố gắng trở nên hiệu quả như tôi đã cố gắng ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.