เลิกใช้งาน ModalViewController


103

ฉันเพิ่งอัปเกรดเป็น XCode 4.5 เพื่ออัปเดตแอป iOS ของฉันให้ทำงานบนจอแสดงผล 4 นิ้วสำหรับ iPhone 5 แต่ฉันได้รับข้อผิดพลาดในการสร้างโดยแจ้งdismissModalViewControllerAnimated:' is deprecatedในบรรทัด:

[self dismissModalViewControllerAnimated:NO];

ฉันได้ลองอัปเดตเป็นโอเวอร์โหลดที่แนะนำด้วยตัวจัดการที่สมบูรณ์ (แต่ตั้งค่าเป็น NULL) ดังนี้:

[self dismissModalViewControllerAnimated:NO completion:NULL];

แต่บรรทัดนี้ทำให้เกิดข้อผิดพลาดสองประการ:

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

ขอบคุณ!

คำตอบ:


307

วิธีใหม่คือ:

[self dismissViewControllerAnimated:NO completion:nil];

คำกิริยาถูกลบออก ตามที่เคยเป็นมาสำหรับการเรียก API ที่นำเสนอ:

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

เหตุผลถูกกล่าวถึงในเซสชัน WWDC 236 ปี 2555 - วิวัฒนาการของ View Controllers บนวิดีโอiOS โดยพื้นฐานแล้วตัวควบคุมมุมมองที่นำเสนอโดย API นี้ไม่ได้เป็นโมดอลเสมอไปและเนื่องจากพวกเขากำลังเพิ่มตัวจัดการที่สมบูรณ์จึงเป็นช่วงเวลาที่ดีที่จะเปลี่ยนชื่อ

ในการตอบกลับความคิดเห็นจาก Marc:

วิธีใดดีที่สุดในการรองรับอุปกรณ์ 4.3 ขึ้นไป วิธีใหม่นี้ใช้ไม่ได้ใน iOS4 แต่วิธีการเดิมเลิกใช้แล้วใน iOS6

ฉันรู้ว่านี่เป็นคำถามที่แยกจากกัน แต่ฉันคิดว่ามันคุ้มค่าที่จะกล่าวถึงเนื่องจากไม่ใช่ทุกคนที่มีเงินในการอัพเกรดอุปกรณ์ทั้งหมดทุกๆ 3 ปีดังนั้นพวกเราหลายคนจึงมีอุปกรณ์รุ่นเก่า (ก่อน 5.0) ถึงกระนั้นเท่าที่ฉันเจ็บปวดที่จะพูดคุณต้องพิจารณาว่าควรกำหนดเป้าหมายที่ต่ำกว่า 5.0 หรือไม่ มี API ใหม่และเจ๋ง ๆ มากมายที่ไม่พร้อมใช้งานต่ำกว่า 5.0 และ Apple ทำให้การกำหนดเป้าหมายยากขึ้นอย่างต่อเนื่อง การสนับสนุน armv6 หลุดจาก Xcode 4.5 เช่น

หากต้องการกำหนดเป้าหมายให้ต่ำกว่า 5.0 (ตราบใดที่บล็อกการทำให้เสร็จสมบูรณ์เป็นศูนย์) เพียงแค่ใช้วิธีที่มีประโยชน์respondsToSelector:

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

ในการตอบกลับความคิดเห็นอื่นจาก Marc:

นั่นอาจเป็นคำสั่ง If จำนวนมากในแอปพลิเคชันของฉัน! ... ฉันกำลังคิดที่จะสร้างหมวดหมู่ที่ห่อหุ้มรหัสนี้จะสร้างหมวดหมู่บน UIViewControler ทำให้ฉันถูกปฏิเสธหรือไม่

และอีกหนึ่งจาก Full Decent:

... มีวิธีทำให้ไม่แสดงคำเตือนคอมไพเลอร์ด้วยตนเองหรือไม่?

ประการแรกไม่สร้างหมวดหมู่บน UIViewControllerในและของตัวเองจะไม่ทำให้แอปของคุณถูกปฏิเสธ เว้นแต่วิธีการหมวดหมู่นั้นเรียกว่า API ส่วนตัวหรือสิ่งที่คล้ายกัน

วิธีการหมวดหมู่เป็นสถานที่ที่ดีมากสำหรับรหัสดังกล่าว นอกจากนี้เนื่องจากจะมีการเรียก API ที่เลิกใช้งานเพียงครั้งเดียวจึงมีคำเตือนคอมไพเลอร์เพียงรายการเดียว

เพื่อจัดการกับความคิดเห็น (คำถาม) ของ Full Decent ใช่คุณสามารถระงับคำเตือนของคอมไพเลอร์ได้ด้วยตนเอง นี่คือลิงค์ไปยังคำตอบของ SO ในเรื่องนั้น ๆๆ วิธีการจัดหมวดหมู่ยังเป็นจุดที่ดีเยี่ยมในการระงับคำเตือนของคอมไพเลอร์เนื่องจากคุณจะระงับคำเตือนไว้ที่เดียวเท่านั้น แน่นอนคุณไม่ต้องการที่จะปิดเสียงคอมไพเลอร์จำใจ

ถ้าฉันจะเขียนวิธีการหมวดหมู่ง่ายๆสำหรับสิ่งนี้อาจเป็นดังนี้:

@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
วิธีใดดีที่สุดในการรองรับอุปกรณ์ 4.3 ขึ้นไป วิธีใหม่นี้ใช้ไม่ได้ใน iOS4 แต่วิธีการเดิมเลิกใช้แล้วใน iOS6 หินและสถานที่ยาก?
Marc

@Marc ฉันได้เพิ่มคำตอบเพื่อตอบข้อกังวลของคุณ
NJones

ขอบคุณ. นั่นอาจเป็นคำสั่ง If ที่ค่อนข้างมากในแอปพลิเคชันของฉัน! ฉันเดาว่าวิธีการเดียวกันนี้สามารถใช้ได้เมื่อใช้คุณสมบัติ 'modalViewController' ฉันกำลังคิดที่จะสร้างหมวดหมู่ที่ห่อหุ้มรหัสนี้การสร้างหมวดหมู่บน UIViewControler จะทำให้ฉันถูกปฏิเสธหรือไม่
Marc

สำหรับโค้ดif ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }มีวิธีที่ทำให้ไม่แสดงคำเตือนคอมไพเลอร์ด้วยตนเองหรือไม่?
William Entriken

@FullDecent ใช่คุณทำได้ ฉันแก้ไขคำตอบด้วยข้อมูลบางอย่าง
NJones

6

ตอนนี้ใน iOS 6 ขึ้นไปคุณสามารถใช้:

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

แทน:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... และคุณสามารถใช้:

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

แทน

[self presentModalViewController:picker animated:YES];    



3

คำเตือนยังมีอยู่ ในการกำจัดมันฉันใส่ลงในตัวเลือกดังนี้:

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

เป็นประโยชน์ต่อคนที่มี OCD เหมือนตัวเอง;)


คุณควรเปลี่ยนคำสั่ง if เพราะฉันเชื่อว่าเมธอดที่เลิกใช้แล้วจะไม่ทำให้respondsToSelectorคืนค่าเป็นเท็จ ดังนั้นdismissViewControllerAnimated:จะไม่มีการเรียกใหม่จนกว่าจะมีการอัปเดตในอนาคตซึ่งอาจถูกลบออกdismissModalViewControllerAnimated:ทั้งหมด
Jsdodgers

0

นี่คือเวอร์ชัน presentViewController ที่เกี่ยวข้องซึ่งฉันใช้ถ้ามันช่วยมือใหม่คนอื่น ๆ เช่นตัวฉันเอง:

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

ฉันใช้ ViewController 'โดยทั่วไป' และสามารถทำให้ Modal View ปรากฏแตกต่างกันไปตามสิ่งที่เรียกให้ทำ (โดยใช้ setHidden และ setImage) และสิ่งต่าง ๆ ก็ทำงานได้ดีมาก่อน แต่ performSelector ไม่สนใจสิ่งที่ 'ตั้งค่า' ดังนั้นในท้ายที่สุดดูเหมือนว่าจะเป็นทางออกที่ไม่ดีถ้าคุณพยายามมีประสิทธิภาพเหมือนที่ฉันพยายามจะเป็น ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.