2016-03-04 13 views
6

Po naciśnięciu określonego przycisku w mojej aplikacji widok powinien zmienić orientację z pionowej na krajobraz . Gdy użytkownik wróci, kontroler widoku powinien wrócić do portretu. Ale czasami orientacja się nie zmienia lub używana jest niewłaściwa ramka widoku.Wymuszona zmiana orientacji czasami nie działa

Oto mój kod

-(void)btnSignClicked:(CustomSignButton *)btn { 
    isSignButtonClicked = true; 
    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0) { 
     NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; 
     [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 
    } 
    else 
    { 
     [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES]; 
    } 
    selectedWaiverId = btn.customTag; 

    SignatureView *obj = [[SignatureView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) delegate:self]; // Most of time got size (568,320) but some time i got (320,568), Don't know why 
    [self.view addSubview:obj]; 
} 

#pragma mark - SIGNATUREVIEW DELEGATE 
-(void)removeSignatureView:(SignatureView *)signatureView { 
    isSignButtonClicked = false; 

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_0) 
    { 
     NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; 
     [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; // Some time not changed the orientation are view remaining in landscape 
    } 
    else 
    { 
     [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES]; 
    } 

    [signatureView removeFromSuperview]; 
    signatureView = nil; 

} 
#pragma mark 
#pragma mark - Rotate screen 
-(UIInterfaceOrientationMask)supportedInterfaceOrientations 
{ 
    if (isSignButtonClicked == true) 
    { 
     return UIInterfaceOrientationMaskLandscapeRight|UIInterfaceOrientationMaskLandscape; 
    } 
    else 
    { 
     return UIInterfaceOrientationMaskPortrait; 
    } 
} 
- (BOOL)shouldAutorotate 
{ 
    return YES; 
} 
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    if (isSignButtonClicked == true) 
    { 
     return (interfaceOrientation == UIInterfaceOrientationLandscapeRight); 
    } 
    else 
    { 
     return (interfaceOrientation == UIInterfaceOrientationPortrait); 
    } 

} 

UPDATE

Czasami viewWillTransitionToSize metoda ta nazywa się więc również zintegrować to powiadomienie

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; 
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 

Ale czasami to też nie działa.

+1

Czy ta metoda zmiany orientacji jest nawet udokumentowana, czy jest to hakowanie? – Sulthan

+1

Prawie pewne "wiarygodne i/lub oficjalne źródła" zalecają by tego nie robić. – beyowulf

+0

znajduje się w dokumencie @Sulthan. –

Odpowiedz

0

Zobacz ten link, w szczególności, myślę, że należy sprawdzić warunki Pana zdaniem kontrolerów, które spełniają zaleceń firmy Apple

np sprawdzić metodę supportedInterfaceOrientations kontrolera widoku najwyższej najbardziej pełnoekranowym

+0

Już postawiłem cały warunek. –

0

warto dodać wszystkie swoje rotacji zmieniających kod wewnątrz tego bloku

dispatch_async(dispatch_get_main_queue(), 
{ 
    //changing orientation code + isSignButtonClicked = true (or false) 
}); 

Nie musisz używać shouldAutorotate i shouldAutorotateToInterfaceOrientation.

Jak na widok klatek coraz źle, trzeba użyć autolayout ograniczeń dla każdego wyświetlenia używasz w tym viewController nawet jeśli tworzysz widoki programmativally

+0

jest to bardzo stary kod, więc autolayout nie implementuje w nim. Użyłem już wysyłki w kodzie, ale nie udało mi się osiągnąć sukcesu. –

+0

Ja też miałem stary kod, ale id musiał zmienić go na autolayout, aby uzyskać poprawne ramki. To nie jest dużo bólu. Możesz programowo zaprogramować miejsce, w którym ustawiasz ramki w kodzie. Również musisz dodać ViewControllerBasedOrientation w info.plist do YES – shinoys222

+0

Nie ma opcji "ViewControllerBasedOrientation" w info.plist –

2

Dodaj w pliku AppDelegate.m lub dowolnego sterownika bazowego plik

Teraz umieść obiekt ViewController w obiekcie UINavigationController i naciśnij kontroler widoku.

EX.

UINavigationController *obj=[[UINavigationController alloc] initWithRootViewController:_yourViewCtrlObj]; 

[self presentViewController:obj.....]; 

or 
[self.navigationController pushViewController:obj animated:YES]; 

Ustaw żądaną orientację we wszystkich kontrolerach widoku.

+0

Zrobiłem już to wszystko z wyjątkiem obecnego i odrzucić VC, ponieważ nie używam nowego VC dla niego i tylko obecne the View –

1

Jeśli aplikacja używa UINavigationViewController następnie utworzyć klasę niestandardową UINAvigationController odczuwalna:

//CustomNavViewController.h

#import <UIKit/UIKit.h> 
@interface CustomNavViewController : UINavigationController <UINavigationControllerDelegate> 

@end 

//CustomNavViewController.m

#import "CustomNavViewController.h" 
@interface CustomNavViewController() 
@end 

@implementation CustomNavViewController 
- (void)viewDidLoad { 
[super viewDidLoad]; 
// Do any additional setup after loading the view. 
} 
- (void)didReceiveMemoryWarning { 
[super didReceiveMemoryWarning]; 
// Dispose of any resources that can be recreated. 
} 
- (BOOL)shouldAutorotate { 
return [self.visibleViewController shouldAutorotate]; 
} 

- (UIInterfaceOrientationMask)supportedInterfaceOrientations { 
return [self.visibleViewController supportedInterfaceOrientations]; 
} 
@end 

a teraz w twojej AppDelegate deklaruje właściwość podobną do:

//AppDelegate.h

@property (assign, nonatomic) BOOL shouldRotate; 

// AppDelegate.m

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 
{ 
if (self.shouldRotate) { 
    return UIInterfaceOrientationMaskLandscapeLeft|UIInterfaceOrientationMaskLandscapeRight; 
} 
return UIInterfaceOrientationMaskPortrait; 
} 

Teraz można wywołać metody orientacji ViewController wymagające orientacji fix odczuwalna:

//YourViewController.m

-(BOOL)shouldAutorotate{ 
return NO; 
} 

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ 
    return UIInterfaceOrientationMaskLandscape; 
} 

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{ 
return UIInterfaceOrientationLandscapeLeft; 
} 

Teraz tutaj jest trick ustawić właściwość AppDelegate shouldRotate true i false dla pożądanej orientacji

jeśli używasz Prezentacja domyślna dla ViewController następnie

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; 
[appDelegate setShouldRotate:true];// Remember first update the value then present the ViewController 
[self presentViewController:yourViewController animated:YES completion:nil]; 

samo jak wtedy, gdy odwołuje

AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; 
[appDelegate setShouldRotate:false]; 
[self dismissViewControllerAnimated:YES completion:nil]; 

Jeśli używasz storyboardy następnie dodać CustomNavViewController bezpośrednio na Identity Inspector niestandardowej sekcji klasy

customNav A potem wykonaj powyższe kroki. Mam nadzieję, że działa

+0

Zrobiłem to już wszystko poza obecnym i odrzuciłem VC, ponieważ nie używam do tego nowego VC prezentuję tylko widok –

1

Kiedy mówisz "Kiedy użytkownik wróci, kontroler powinien powrócić do portretu", czy masz na myśli, że użytkownik naciska przycisk wstecz na kontrolerze nawigacyjnym? Jeśli tak, zobaczyłem ten problem wcześniej i opublikowałem rozwiązanie, które działało dla mnie w innym poście SO: A: Locking device orientation on a view fails when going back in NavBar. Pamiętam, że przejście było surowe, ale działało.

Napisałem też chwilę o numerze blog post, który dotyczy innych sytuacji związanych z blokowaniem orientacji kontrolera widoku.

Powiązane problemy