iOS 6: ฉันจะ จำกัด มุมมองบางส่วนเป็นแนวตั้งและอนุญาตให้ผู้อื่นหมุนได้อย่างไร


99

ฉันมีแอพ iPhone ที่ใช้UINavigationControllerเพื่อนำเสนออินเทอร์เฟซแบบเจาะลึก: มุมมองแรกหนึ่งมุมมองจากนั้นอีกมุมมองหนึ่งลึกถึงสี่ระดับ ฉันต้องการให้สามมุมมองแรก จำกัด เฉพาะการวางแนวตั้งและเฉพาะมุมมองสุดท้ายเท่านั้นที่ควรได้รับอนุญาตให้หมุนเป็นแนวนอน เมื่อกลับจากมุมมองที่สี่ไปยังมุมมองที่สามและมุมมองที่สี่อยู่ในแนวนอนฉันต้องการให้ทุกอย่างหมุนกลับเป็นแนวตั้ง

ใน iOS 5 ฉันเพียงกำหนดshouldAutorotateToInterfaceOrientation:ในตัวควบคุมมุมมองแต่ละตัวของฉันให้ส่งคืนใช่สำหรับการวางแนวที่อนุญาต ทุกอย่างทำงานตามที่อธิบายไว้ข้างต้นรวมถึงการกลับสู่แนวตั้งแม้ว่าอุปกรณ์จะอยู่ในแนวนอนเมื่อกลับจากตัวควบคุมมุมมอง # 4 ถึง # 3

ใน iOS 6 ตัวควบคุมมุมมองทั้งหมดจะหมุนเป็นแนวนอนโดยทำลายสิ่งที่ไม่ได้ตั้งใจไว้ บันทึกประจำรุ่น iOS 6 กล่าวว่า

ความรับผิดชอบมากขึ้นกำลังย้ายไปที่แอปและผู้แทนของแอป ตอนนี้คอนเทนเนอร์ iOS (เช่นUINavigationController) ไม่ได้ปรึกษาบุตรหลานเพื่อพิจารณาว่าพวกเขาควรหมุนอัตโนมัติหรือไม่ [... ] ระบบจะขอตัวควบคุมมุมมองแบบเต็มหน้าจอที่อยู่ด้านบนสุด (โดยทั่วไปคือตัวควบคุมมุมมองรูท) สำหรับการวางแนวอินเทอร์เฟซที่รองรับเมื่อใดก็ตามที่อุปกรณ์หมุนหรือเมื่อใดก็ตามที่ตัวควบคุมมุมมองถูกนำเสนอด้วยรูปแบบการนำเสนอแบบเต็มหน้าจอ ยิ่งไปกว่านั้นการวางแนวที่รองรับจะถูกดึงออกมาก็ต่อเมื่อตัวควบคุมมุมมองนี้ส่งคืน YES จากshouldAutorotateวิธีการเท่านั้น [... ] ระบบจะพิจารณาว่าการวางแนวได้รับการสนับสนุนหรือไม่โดยการตัดกันค่าที่ส่งคืนโดยsupportedInterfaceOrientationsForWindow:วิธีการของแอปด้วยค่าที่ส่งคืนโดยsupportedInterfaceOrientationsวิธีการของตัวควบคุมแบบเต็มหน้าจอด้านบนสุด

ดังนั้นฉันจึงจัดคลาสย่อยUINavigationControllerให้MainNavigationControllerคุณสมบัติบูลีนของฉันlandscapeOKและใช้สิ่งนี้เพื่อส่งคืนการวางแนวที่อนุญาตในsupportedInterfaceOrientations. จากนั้นในแต่ละviewWillAppear:วิธีการควบคุมมุมมองของฉันฉันมีบรรทัดแบบนี้

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

เพื่อบอกMainNavigationControllerพฤติกรรมที่ฉันต้องการ

คำถามมาที่นี่:ถ้าตอนนี้ฉันไปที่มุมมองที่สี่ของฉันในโหมดแนวตั้งและพลิกโทรศัพท์จะหมุนเป็นแนวนอน ตอนนี้ฉันกดปุ่มย้อนกลับเพื่อกลับไปที่มุมมองที่สามของฉันซึ่งควรจะใช้งานได้ในแนวตั้งเท่านั้น แต่มันไม่หมุนกลับ. ฉันจะทำมันได้อย่างไร?

ฉันเหนื่อย

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]

ในviewWillAppearวิธีการของตัวควบคุมมุมมองที่สามของฉัน แต่มันไม่ทำอะไรเลย นี่เป็นวิธีการโทรที่ไม่ถูกต้องหรืออาจจะเรียกผิดหรือฉันควรจะใช้วิธีที่แตกต่างออกไปโดยสิ้นเชิง?

คำตอบ:


95

ฉันมีปัญหาเดียวกันและพบวิธีแก้ปัญหาที่เหมาะกับฉัน เพื่อให้ใช้งานได้จึงไม่เพียงพอที่จะนำไปใช้- (NSUInteger)supportedInterfaceOrientationsใน UINavigationController ของคุณ คุณต้องใช้วิธีนี้ในคอนโทรลเลอร์ # 3 ซึ่งเป็นวิธีแรกที่เป็นแนวตั้งเท่านั้นหลังจาก popping controller # 4 ดังนั้นฉันจึงมีรหัสต่อไปนี้ใน UINavigationController ของฉัน:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}

ในมุมมองตัวควบคุม # 3 ให้เพิ่มสิ่งต่อไปนี้:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

คุณไม่จำเป็นต้องเพิ่มอะไรลงในตัวควบคุมมุมมอง # 1, # 2 และ # 4 สิ่งนี้ได้ผลสำหรับฉันฉันหวังว่ามันจะช่วยคุณได้


8
คุณแก้ไขบางสิ่งที่ผู้คนพยายามแก้ไขมาหลายเดือนแล้ว! คุณสมควรได้รับเครดิตมากสำหรับสิ่งนี้! ฉันได้เพิ่ม SupportInterfaceOrientations ลงในหมวดหมู่บน UIViewController และทำงานได้อย่างสมบูรณ์แบบเป็นค่าเริ่มต้นสำหรับคอนโทรลเลอร์แนวตั้งเท่านั้น
dwery

3
ในบรรดา 100 คำตอบที่แตกต่างกันเกี่ยวกับ SO นี่คือคำตอบที่ได้ผลจริง ขอบคุณ :-)
Christer Nordvik

16
ฉันตั้งค่านี้แล้วและยังคงวางแนวไม่ถูกต้องเมื่อย้อนกลับจากแนวตั้งไปยังตัวควบคุมมุมมองที่ จำกัด เฉพาะแนวนอน มันไม่อัตโนมัติไปที่แนวนอน - มีใครยังเห็นอยู่ไหม
Oded Ben Dov

1
จะเกิดอะไรขึ้นหากมีการนำเสนอตัวควบคุมมุมมองแนวนอนที่ต้องการจากการต่อและไม่มีตัวควบคุมการนำทาง
jesses.co.tt

1
แก้ไขอันสุดท้ายเป็น NSUInteger เป็นประเภทการส่งคืน
ขาด

68

เพิ่มCustomNavigationController

แทนที่วิธีการเหล่านี้ในนั้น:

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

ตอนนี้เพิ่มการวางแนวทั้งหมดใน plist

ป้อนคำอธิบายภาพที่นี่

ในตัวควบคุมมุมมองให้เพิ่มเฉพาะสิ่งที่จำเป็น:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

วิธีการเหล่านี้จะแทนที่วิธีการควบคุมการนำทาง


5
คุณตอกด้วยคำตอบนี้จริงๆ! ขอบคุณมาก. คุณช่วยได้มากจริงๆ นี่เป็นปัญหาใหญ่สำหรับฉันมาระยะหนึ่งแล้ว เยี่ยมมาก
K2Digital

ขอบคุณ! สิ่งนี้ทำให้ฉันต้องใช้เวลาและแรงมากในการคิดออก!
bkbeachlabs

คุณคือผู้ช่วยชีวิต .... สิ่งนี้ใช้ได้ในแอปของฉันเช่นกัน จริงๆแล้วสิ่งที่ฉันต้องการในแอพของฉันคือฉันมีทั้งหมดViewControllerอยู่ในโหมดแนวตั้งและอันที่ฉันViewControllerอยู่ในโหมดแลนด์สเคปและแนวตั้ง ฉันยังให้การสนับสนุนทั้งใน iOS 5.0 และ iOS 6.0 นั่นเป็นเหตุผลที่ฉันสับสนในการแก้ไข แต่นี่เป็นทางออกที่ยอดเยี่ยม ฉันเพิ่มCustomNavigationControllerในตัวควบคุมมุมมองรูทของฉันและให้การสนับสนุนตามความต้องการของฉัน ขอบคุณอีกครั้ง
Bhavin_m

ยอดเยี่ยม. สิ่งที่ฉันต้องการ ขอบคุณ.
mszaro

จะเกิดอะไรขึ้นหากมีการนำเสนอตัวควบคุมมุมมองแนวนอนที่ต้องการจากการต่อและไม่มีตัวควบคุมการนำทาง
jesses.co.tt

9

หลังจากดูทุกคำตอบในคำถามที่คล้ายกันนับไม่ถ้วนใน SO ไม่มีคำตอบใดที่เหมาะกับฉัน แต่พวกเขาให้ความคิดกับฉัน นี่คือวิธีการแก้ปัญหา:

ขั้นแรกตรวจสอบให้แน่ใจว่าการวางแนวอินเทอร์เฟซที่รองรับในเป้าหมายโครงการของคุณมีการวางแนวทั้งหมดที่คุณต้องการสำหรับมุมมองแบบหมุนของคุณ

ป้อนคำอธิบายภาพที่นี่

จากนั้นสร้างหมวดหมู่UINavigationController(เนื่องจาก Apple บอกว่าไม่ให้ subclass):

@implementation UINavigationController (iOS6AutorotationFix)

-(BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

@end

นำเข้าหมวดหมู่นั้นและตัวควบคุมมุมมองที่คุณต้องการให้สามารถหมุนได้ (ซึ่งฉันจะเรียกRotatingViewController) ไปยังตัวควบคุมมุมมองระดับสูงสุดของคุณซึ่งควรมีตัวควบคุมการนำทางของคุณ ในตัวควบคุมมุมมองนั้นให้ดำเนินการshouldAutorotateดังนี้ โปรดทราบว่าสิ่งนี้ไม่ควรเป็นตัวควบคุมมุมมองเดียวกับที่คุณต้องการหมุน

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

    if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
        shouldRotate = [navigationController.topViewController shouldAutorotate];
    }

    return shouldRotate;
}

สุดท้ายในRotatingViewControllerการดำเนินการของคุณshouldAutorotateและsupportedInterfaceOrientationsดังต่อไปนี้:

-(BOOL)shouldAutorotate {
    // Preparations to rotate view go here
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}

เหตุผลที่คุณต้องทำเช่นนี้เนื่องจาก iOS 6 ให้การควบคุมการหมุนไปยังตัวควบคุมมุมมองรูทแทนตัวควบคุมมุมมองด้านบน หากคุณต้องการให้การหมุนของแต่ละมุมมองทำงานแตกต่างจากมุมมองอื่น ๆ ในสแต็กคุณต้องเขียนกรณีเฉพาะสำหรับมุมมองนั้นในตัวควบคุมมุมมองรูท


2
นี่เป็นคำตอบที่ยอดเยี่ยมที่สมควรได้รับความรักมากขึ้น นี่คือข้อมูลที่มีอยู่ซึ่งฉันไม่สามารถหาได้จากที่อื่นและที่สำคัญ: หากคุณต้องการให้การหมุนเวียนของแต่ละมุมมองทำงานแตกต่างจากมุมมองอื่น ๆ ในสแต็กคุณต้องเขียนกรณีเฉพาะสำหรับมันในรูท ดูคอนโทรลเลอร์
shmim

ฉันคิดว่าสิ่งนี้จะใช้งานได้หากคุณมี navigationController เป็นสมาชิกตัวแรกของสตอรีบอร์ดของแอปของคุณเป็นตัวควบคุมเริ่มต้น แต่จะเกิดอะไรขึ้นเมื่อคอนโทรลเลอร์เริ่มต้นเป็นเพียง ViewController?
เป็ด

4

ฉันไม่มีชื่อเสียงมากพอที่จะแสดงความคิดเห็นเกี่ยวกับคำตอบของ @ Brian ดังนั้นฉันจะเพิ่มบันทึกของฉันที่นี่

Brian กล่าวว่า iOS6 ให้การควบคุมการหมุนไปยัง rootViewController - สิ่งนี้ไม่เพียง แต่เป็น UINavigationController ตามที่กล่าวไว้ แต่ยังรวมถึง UITabBarController ด้วยซึ่งสำหรับฉัน โครงสร้างของฉันมีลักษณะดังนี้:

  • UITabBarController
    • UINavigationController
      • UIViewControllers ...
    • UINavigationController
      • UIViewControllers ...

ดังนั้นฉันจึงเพิ่มวิธีการก่อนใน UITabBarController ที่กำหนดเองจากนั้นใน UINavigationController ที่กำหนดเองและสุดท้ายใน UIViewController เฉพาะ

ตัวอย่างจาก UITabBarController และ UINavigationController:

- (BOOL)shouldAutorotate {
    return [self.viewControllers.lastObject shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.viewControllers.lastObject supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}

จริงๆแล้วฉันใช้ UITabBarController เป็นตัวแปรอินสแตนซ์ในตัวควบคุมมุมมองรูทของฉันเพราะคุณไม่ควรซับคลาส UITabBarController ใน iOS เวอร์ชันก่อน 6.0 และฉันจำเป็นต้องสนับสนุนกลับไปที่ iOS 5.0
Brian

@micmdk ฉันมีปัญหาเดียวกัน โปรดแนะนำวิธีแก้ไขฉันได้คัดลอกโค้ดของคุณและใส่ลงใน Navigation Controller และ customUabbarController และตั้งค่าตัวควบคุมมุมมองอื่น ๆ เป็นคำแนะนำของ Brian แต่ยังไม่ได้รับตัวควบคุมมุมมองคงที่ในแนวตั้ง
ราม

@ ไบรอันฉันมีปัญหาเดียวกัน โปรดแนะนำวิธีแก้ไขฉันได้คัดลอกโค้ดของคุณและใส่ลงใน Navigation Controller และ customUabbarController และตั้งค่าตัวควบคุมมุมมองอื่นเป็นคำแนะนำของ Micmdk แต่ยังไม่ได้รับตัวควบคุมมุมมองคงที่ในแนวตั้งใน ios8
ราม

3

ฉันต้องการให้คำตอบบางส่วนสำหรับคำถามของฉันเอง ฉันพบบรรทัดของรหัสต่อไปนี้ซึ่งใช้ในviewWillAppearวิธีที่สามของฉันUIViewControllerในการทำงาน:

[[UIDevice currentDevice] 
      performSelector:NSSelectorFromString(@"setOrientation:") 
           withObject:(id)UIInterfaceOrientationPortrait];

แต่ฉันไม่ชอบวิธีแก้ปัญหานี้จริงๆ กำลังใช้เคล็ดลับในการกำหนดให้กับคุณสมบัติอ่านอย่างเดียวซึ่งตามเอกสารของ Apple แสดงถึงการวางแนวจริงของอุปกรณ์ เหมือนกับการบอกให้ iPhone กระโดดไปยังทิศทางที่ถูกต้องในมือของผู้ใช้

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


4
แอปของคุณจะถูกปฏิเสธมากที่สุดหากคุณปล่อยไว้ที่นั่น ฉันกำลังหาวิธีแก้ปัญหานี้เช่นกัน แต่ดูเหมือนจะเป็นไปไม่ได้ สิ่งที่ฉันหาได้คือคำตอบสำหรับคำถามนี้: stackoverflow.com/questions/7196300/…มันใช้งานได้ดี แต่ด้วยเหตุผลบางอย่างมันทำให้การจัดการการสัมผัสปุ่มหยุดในหนึ่งในตัวควบคุมมุมมองของฉัน
Lope

ฉันได้รับโอกาสและส่งไปยัง Apple ยังรอการตรวจสอบ ... ฉันจะโพสต์ให้คุณ
Harald Bögeholz

Apple เพิ่งอนุมัติแอปของฉันด้วยการแฮ็กนี้ใช่! ฉันหวังว่ามันจะไม่ย้อนกลับมาหาฉันในการอัปเดต iOS ในอนาคต ในระหว่างนี้ฉันยังคงเปิดรับคำแนะนำสำหรับวิธีแก้ปัญหาที่สะอาด!
Harald Bögeholz

1
กินเก่ง แต่เมื่อฉันทำงานใน xCode ใหม่กับ ARC ฉันไม่สามารถใช้ ans ได้ ฉันได้รับ "Cast of NSInteger (aka int) เป็น id ไม่ได้รับอนุญาตด้วย ARC PerformSelector อาจทำให้เกิดการรั่วไหลเนื่องจากไม่รู้จักตัวเลือก" ฉันจะแก้ไขปัญหานี้ได้อย่างไร ฉันรู้สึกยินดีกับคุณมากถ้าเรามีทางออก เมื่อฉันปิด ARC สำหรับมุมมองที่ชัดเจนกว่าแอปขัดข้องเนื่องจากข้อมูลรั่วไหล โปรดแนะนำฉัน
Hitarth

4
การใช้ API ส่วนตัวไม่ใช่วิธีแก้ปัญหา
Javier Soto

1

นี่คือฉันใช้สำหรับการสนับสนุนการวางแนวใน ios 6.0

-(BOOL)shouldAutorotate{
    return YES;
}  

 - (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAll;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{  
  return UIInterfaceOrientationPortrait;
}

1

เนื่องจากว่านี่เป็นกระทู้ที่มีผู้ชมมาก ฉันคิดว่าฉันจะเพิ่มสิ่งที่ฉันเชื่อว่าเป็นคำตอบที่ง่ายที่สุด สิ่งนี้ใช้ได้กับ ios8 ขึ้นไป

-(BOOL)shouldAutorotate
{
    return YES;
}

และ

-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

แค่นั้นแหละ. สนุก!

โอ้และ ViewControllers ของฉันฝังอยู่ในตัวควบคุมการนำทางซึ่งฉันไม่จำเป็นต้องคลาสย่อยหรือกำหนดค่า แต่อย่างใด


0

สิ่งนี้อาจไม่ได้ผลสำหรับทุกคน แต่ก็ใช้ได้ผลดีสำหรับฉัน แทนที่จะดำเนินการ ...

[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

ใน viewWillAppear ในคอนโทรลเลอร์ทั้งหมดของฉันฉันตัดสินใจที่จะรวมศูนย์กระบวนการนี้ไว้ในคลาสย่อย UINavigationController ของฉันโดยการแทนที่เมธอดUINavigationControllerDelegatenavigationController:willShowViewController:animated:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    self.previousVCLandscapeOK = self.isLandscapeOK; // Store the current VC's orientation preference before pushing on the new VC so we can set this again from within the custom "back" method
    self.isLandscapeOK = NO; // Set NO as default for all VC's
    if ([viewController isKindOfClass:[YourViewController class]]) {
        self.isLandscapeOK = YES;
    }
}

ฉันพบว่าวิธีการมอบสิทธิ์นี้ไม่ได้รับการเรียกเมื่อดึง VC ออกจากสแต็ก nav นี่ไม่ใช่ปัญหาสำหรับฉันเพราะฉันกำลังจัดการฟังก์ชันการทำงานด้านหลังจากภายในคลาสย่อย UINavigationController ของฉันเพื่อให้ฉันสามารถตั้งค่าปุ่มแถบนำทางที่เหมาะสมและการดำเนินการสำหรับ VC เฉพาะเช่นนี้ ...

if ([viewController isKindOfClass:[ShareViewController class]]) {

    UIButton* backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 57, 30)];
    [backButton setImage:[UIImage imageNamed:@"back-arrow"] forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem* backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    viewController.navigationItem.leftBarButtonItem = backButtonItem;

    UIImageView* shareTitle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"share-title"]];
    [shareTitle setContentMode:UIViewContentModeScaleAspectFit];
    [shareTitle setFrame:CGRectMake(0, 0, shareTitle.frame.size.width - 10, shareTitle.frame.size.height - 10)];
    viewController.navigationItem.titleView = shareTitle;

} else if(...) {
    ...
}

นี่คือสิ่งที่backวิธีการของฉันดูเหมือนจะจัดการกับการเปิด VC ออกจากสแต็กและตั้งค่าการหมุนที่เหมาะสม ...

- (void)back {
    self.isLandscapeOK = self.previousVCLandscapeOK;
    self.previousVCLandscapeOK = NO;
    [self popViewControllerAnimated:YES];
}

อย่างที่คุณเห็นโดยพื้นฐานแล้วสิ่งที่เกิดขึ้นคือฉันตั้งค่าคุณสมบัติสองอย่างให้ฉันก่อน ...

@property (nonatomic) BOOL isLandscapeOK;
@property (nonatomic) BOOL previousVCLandscapeOK;

ในการnavigationController:willShowViewController:animated:ที่จะเป็นตัวกำหนดทิศทางการสนับสนุนอยู่ภายใน VC ว่าเป็นเรื่องเกี่ยวกับที่จะนำเสนอ เมื่อเปิด VC เมธอด "back" ที่กำหนดเองของฉันกำลังถูกเรียกจากนั้นฉันก็ตั้งค่า isLandscapeOK เป็นสิ่งที่เก็บไว้ผ่านค่า VCLandscapeOK ก่อนหน้า

อย่างที่ฉันได้กล่าวไปสิ่งนี้อาจไม่ได้ผลสำหรับทุกคน แต่มันใช้งานได้ดีสำหรับฉันและฉันไม่ต้องกังวลเกี่ยวกับการเพิ่มโค้ดให้กับตัวควบคุมมุมมองแต่ละตัวของฉันฉันสามารถเก็บมันทั้งหมดไว้ที่ส่วนกลางในคลาสย่อย UINavigationController

หวังว่านี่จะช่วยใครบางคนเหมือนที่ฉันเคยทำ ขอบคุณ Jeremy



0

คุณต้องการบังคับให้แอป iOS 6 เป็นแนวตั้งเท่านั้นจากนั้นคุณสามารถเพิ่มลงในคลาสย่อย UIViewController ด้านล่างวิธีการ

- (BOOL)shouldAutorotate {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return YES;
    } else {
        return NO;
    }
}


- (NSUInteger)supportedInterfaceOrientations {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}

2
ปัญหาคือเว้นแต่ว่ามุมมองนั้นจะเป็นมุมมองราก (ซึ่งไม่ได้อยู่ในคำถามนี้) ก็ไม่ได้รับการเรียกใช้ shouldAutorotate
Brian

ไม่ว่าจะด้วยเหตุผลใดก็ตามประเภทการส่งคืนNSUIntegerคำเตือนแม้ว่าจะเป็นประเภท var ที่ถูกต้องก็ตาม หากคุณมี OCD ให้ใช้UIInterfaceOrientationMaskแทน
Chris J

นอกจากนี้โซลูชันนี้ยังทำงานได้อย่างสมบูรณ์แบบสำหรับตัวควบคุมมุมมองแบบโมดอล (มุมมองกล้อง) ที่ฉันมีโดยไม่จำเป็นต้องมี UINavigationController subclassing ฉันเดาว่าวิธีการได้รับการปฏิบัติโดยอิสระ ไม่เกี่ยวข้องกับคำถามเดิม แต่เป็นข้อมูลที่มีประโยชน์ในการออกแบบอย่างชาญฉลาด
Chris J

0

ฉันต้องการให้ VC ทั้งหมดของฉันล็อกเป็นแนวตั้งยกเว้นอย่างใดอย่างหนึ่ง นี่คือสิ่งที่ได้ผลสำหรับฉัน

  1. เพิ่มการรองรับสำหรับการวางแนวทั้งหมดในไฟล์ plist
  2. ในตัวควบคุมมุมมองรูทตรวจหาชนิดของตัวควบคุมมุมมองที่อยู่ด้านบนของหน้าต่างและตั้งค่าการวางแนวของแอปตามในเมธอดsupportedInterfaceOrientations ตัวอย่างเช่นฉันต้องการให้แอปของฉันหมุนเฉพาะเมื่อมุมมองเว็บอยู่ด้านบนของสแต็ก นี่คือสิ่งที่ฉันเพิ่มใน rootVC ของฉัน:

    -(NSUInteger)supportedInterfaceOrientations
    {
        UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController;
        if ([topMostViewController isKindOfClass:[SVWebViewController class]]) {
            return UIInterfaceOrientationMaskAllButUpsideDown;
        }
        return UIInterfaceOrientationMaskPortrait;
    }

Trunal อายุไม่กี่เดือน แต่คุณสามารถให้รายละเอียดเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีตรวจจับชนิดของตัวควบคุมมุมมองที่อยู่ด้านบน [[Utils getAppDelegate] appNavigationController]โดยเฉพาะผมไม่แน่ใจว่าสิ่งที่คุณได้ไปที่นี่ เครื่องใช้ฉันเดาว่าเป็นคลาสบางอย่างที่คุณมี แต่ฉันสูญเสียสิ่งที่คุณทำในนั้น ความช่วยเหลือใด ๆ จะดีมาก!
เบ็น

0

ฉันไม่มีชื่อเสียงเพียงพอที่จะตอบคำถาม @Ram S ภายใต้การตอบกลับ @micmdk ดังนั้นฉันจะเพิ่มบันทึกของฉันที่นี่

เมื่อคุณใช้UITabbarControllerให้ลองเปลี่ยนself.viewControllers.lastObjectในโค้ดของ @ micmdk เป็นself.selectedViewControllerดังนี้:

- (BOOL)shouldAutorotate {
    return [self.selectedViewController shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.selectedViewController supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}

0

คุณสามารถใช้งานและลบล้าง shouldAutorotate () และได้รับการสนับสนุนอินเทอร์เฟซโอริเอนเตชันที่หลากหลายในคลาส View Controller ทั้งหมดของคุณซึ่งควรนำเสนอในทิศทางที่แตกต่างจากที่กำหนดไว้ใน PLIST ของแอปของคุณ

อย่างไรก็ตามในอินเทอร์เฟซผู้ใช้ที่ไม่สำคัญคุณอาจประสบปัญหาในการเพิ่มในคลาสหลายสิบคลาสและคุณไม่ต้องการสร้างคลาสย่อยทั้งหมดของคลาสย่อยหลาย ๆ คลาสที่รองรับ (MyBaseTableViewController, MyBaseNavigationController และ MyBaseTabBarController)

เนื่องจากคุณไม่สามารถแทนที่ method / var เหล่านั้นบน UIViewController ได้โดยตรงคุณอาจทำเช่นนั้นกับคลาสย่อยซึ่งโดยปกติแล้วจะเป็นคลาสพื้นฐานของคุณเช่น UITableViewController, UINavigationController และ UITabBarController

ดังนั้นคุณสามารถใช้ส่วนขยายบางส่วนและยังคงตั้งค่า MyPreciousViewController เพื่อแสดงในทิศทางที่แตกต่างจากส่วนขยายอื่น ๆ เช่นข้อมูลโค้ด Swift 4 นี้:

extension UITableViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    if let last = self.navigationController?.childViewControllers.last,
        last != self {
            return last.supportedInterfaceOrientations
    } else {
        return [.portrait]
    }
    }
}

extension MyPreciousViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    return [.portrait,.landscape]
    }
}


extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}


extension UITabBarController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}

0

ฉันได้แก้ไขปัญหาประเภทเดียวกันแล้ว

หากคุณใช้ปุ่มUINavigationControllerเพื่อดันตัวควบคุมมุมมองคุณต้องตั้งค่าวิธีการด้านล่าง

extension UINavigationController{

    override open var shouldAutorotate: Bool {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return true
        }
        return false
    }

    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight

    }
    override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight
    }
}

แทนการLoginViewControllerใช้งานที่UIViewControllerคุณต้องการแสดง ในกรณีของฉันฉันต้องการแสดงLoginViewControllerในPortraitโหมดอื่นViewControllersในlandscapeโหมด


-1

โปรดใช้วิธีการต่อไปนี้เพื่อแก้ปัญหานี้

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

คืนเฉพาะแนวที่คุณต้องการ !!!


3
ฉันทำอย่างนั้นตามที่ฉันเขียน สิ่งนี้ป้องกันไม่ให้ตัวควบคุมมุมมองของฉันหมุน แต่ไม่ได้บังคับให้กลับไปที่การวางแนวที่รองรับเมื่อฉันกลับไปที่มัน
Harald Bögeholz

สิ่งนี้ไม่ได้ผลสำหรับฉัน แม้ว่าจะรวมสิ่งนี้ไว้ในตัวควบคุมมุมมองของฉันแล้วมุมมองก็ยังคงหมุนอยู่ สิ่งที่ช่วยให้?
ชิม

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