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方向”的值,然后调用 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 来销毁所有子视图,然后在方向改变时重新创建它们。

4

2 回答 2

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 方法确保仅在方向更改为新的有效值时触发代码。

于 2016-05-31T04:28:30.557 回答
0

你永远不应该自己调用 loadView 或 viewDidLoad。这取决于要管理的框架。

如果您根据 viewDidLoad 中的视图边界定位或调整视图大小,请不要这样做。将其移至 viewWillLayoutSubviews。当设备方向改变时会自动调用。

或者,使用自动布局约束,然后您根本不需要做任何事情。

于 2014-02-21T19:47:26.127 回答