2014-02-21 73 views
0

當設備更改方向時,UIDeviceOrientationDidChangeNotification正在多次調用。我不確定爲什麼會發生這種情況,或者如何解決這個問題。多次調用UIDeviceOrientationDidChangeNotification

我想要做的是保持scrollview的contentoffset相同,所以當用戶旋轉屏幕時,應用程序保持它們所在的頁面。

奇怪的是當我第一次旋轉屏幕時,屏幕會像我想要的那樣執行代碼。但每次後代碼執行多次,並最終contentoffset設置爲0.

這就是我所擁有的。

- (void)loadView { 

    //some code that sizes itself depending on the current orientation 
    //WILL BE CALLED AFTER EVERY ORIENTATION CHANGE 

} 

- (void)viewDidLoad { 

    //begin generating messages 
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 


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

    //if is portrait and was landscape 
    if (orientation==1 && temp==2) { 
     int cal = offsetHolder.x/screenframe.size.height; 
     offsetHolder.x = cal * screenframe.size.width; 
     ScrollView.contentOffset = offsetHolder; 
    } 

    //if is landscape and was portrait 
    if (orientation==2 && temp==1) { 
     int cal = offsetHolder.x/screenframe.size.width; 
     offsetHolder.x = cal * screenframe.size.height; 
     ScrollView.contentOffset = offsetHolder; 
    } 


} 

關於方向更改我更改'int orientation'的值,然後調用loadview更改視圖的大小。然後,我打電話viewDidLoad中得到適當的contentoffset

- (void) orientationChanged:(NSNotification *)note { 

    CGRect screenframe = [[UIScreen mainScreen] bounds]; 

    //holding the current offset 
    offsetHolder = ScrollView.contentOffset; 

    if ([[UIDevice currentDevice] orientation] == 1 || [[UIDevice currentDevice] orientation] == 0 || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) { 
     temp=orientation; 
     orientation = 1; 

     [self loadView]; 
     [self viewDidLoad]; 
    } 

    else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationFaceDown ||  [[UIDevice currentDevice] orientation] == UIDeviceOrientationFaceUp){ 

     temp=orientation; 
    } 

    else{ 
     temp=orientation; 
     orientation = 2; 
     [self loadView]; 
     [self viewDidLoad]; 
    } 
} 

編輯:

我已經找到了問題。我正在做的是創建self.view的另一個實例,而不是覆蓋這個。有沒有簡單的方法來銷燬這個視圖並重新初始化它?

編輯2:

已找到修復程序。按照jsds的說明,我停止調用loadview和viewdidload。而是將我的loadview中的所有代碼移到另一個我從loadview調用的函數中。所有這些代碼都會實例化UI(initview)對象,並根據方向將它們放在正確的位置。

然後我創建另一個功能,從視圖中刪除所有子視圖。然後在方向更改上,我調用此函數和我的initview來銷燬所有子視圖,然後根據方向更改重新創建它們。

回答

0

你不應該自己調用loadView或viewDidLoad。這取決於要管理的框架。

如果您基於viewDidLoad中的視圖邊界定位或調整視圖的大小,請不要。將其移至viewWillLayoutSubviews。這將在設備方向更改時自動調用。

另外,使用自動佈局約束,然後你將不必做任何事情。

+0

對不起,回覆遲了。哪裏可以找到這方面的文件?我在查找這方面的例子時遇到了一些困難。 – user3009729

+0

https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/Introduction/Introduction .html https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html – jsd

+0

謝謝,特別是關於不調用這些方法的參考。我在目標c方面有點沒有經驗。我已經解決了這個問題,並且會爲有此問題的任何人添加編輯。 – user3009729

1

UIDeviceOrientation基本上有6種不同的狀態,即兩個人像,兩個風景,並且正面朝下。因此,讓我們說,當你從平坦的位置拿起你的設備到垂直位置時,通知將被觸發。 您可以通過使用宏UIDeviceOrientationIsValidInterfaceOrientation

UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation]; 

    // Ignore changes in device orientation if unknown, face up, or face down. 
    if (!UIDeviceOrientationIsValidInterfaceOrientation(currentOrientation)) { 
     return; 
    } 

過濾面朝上,面朝下,和未知狀態如果仍然發現通知獲得多次觸發,恐怕你可能需要使用您的定製邏輯與標誌檢查以前和當前值。

在我的情況,因爲我用的活性可可框架,下面的代碼工作對我來說:

if (IS_IPAD) { @weakify(self); [[[[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIDeviceOrientationDidChangeNotification object:nil] takeUntil:[self rac_willDeallocSignal]] map:^id (NSNotification *notification) { return @([[UIDevice currentDevice] orientation]); }] filter:^BOOL(NSNumber *deviceOrientationNumber) { UIDeviceOrientation currentOrientation = [deviceOrientationNumber integerValue]; //We ignore the UIDeviceOrientationUnknown, UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown return UIDeviceOrientationIsValidInterfaceOrientation(currentOrientation); }] distinctUntilChanged] subscribeNext:^(id x) { @strongify(self); //do something here... }]; }

這裏distinctUntilChanged方法確保代碼被觸發,只有當方向將更改爲新的有效值。