1

デバイスの向きが変わると、UIDeviceOrientationDidChangeNotification が複数回呼び出されます。これがなぜ起こるのか、またはそれを修正する方法がわかりません。

私がやろうとしているのは、スクロールビューの 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 を呼び出してビューのサイズを変更します。次に、適切な contentoffset を取得するために viewdidload を呼び出します

- (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 の別のインスタンスを作成することです。このビューを破棄して再初期化する簡単な方法はありますか?

EDIT2:

修正が見つかりました。jsds の指示に従って、loadview と viewdidload の呼び出しを停止しました。代わりに、ロードビュー内のすべてのコードを、ロードビューから呼び出した別の関数に移動しました。このコードは、UI (initview) オブジェクトをインスタンス化し、向きに応じて正しい場所に配置するだけです。

次に、ビューからすべてのサブビューを削除する別の関数を作成します。次に、方向の変更時に、この関数と initview を呼び出してすべてのサブビューを破棄し、方向の変更時にそれらを再作成します。

4

2 に答える 2

1

UIDeviceOrientation には、基本的に 6 つの異なる状態 (縦 2 つ、横 2 つ、上向きと下向き) があります。つまり、デバイスを平らな位置から垂直な位置に持ち上げると、通知がトリガーされるとしましょう。マクロを使用して、上向き、下向き、および不明な状態をフィルター処理できます。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 メソッドは、方向が新しい有効な値に変更された場合にのみコードがトリガーされるようにします。

于 2016-05-31T04:28:30.557 に答える
0

自分で loadView または viewDidLoad を呼び出さないでください。それは、管理するフレームワーク次第です。

viewDidLoad のビュー境界に基づいてビューを配置またはサイズ変更している場合は、そうしないでください。それをviewWillLayoutSubviewsに移動します。これは、デバイスの向きが変わると自動的に呼び出されます。

または、autolayout 制約を使用すると、何もする必要がなくなります。

于 2014-02-21T19:47:26.127 に答える