ios - UIDeviceOrientationDidChangeNotification 多次调用

标签 ios objective-c orientation uideviceorientation

当设备改变方向时,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;
    }


}

在方向更改时,我更改“intorientation”的值,然后调用loadview来更改 View 的大小。然后我调用 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 的另一个实例,而不是覆盖这个实例。有没有一种简单的方法可以销毁此 View 并重新初始化它?

编辑2:

已找到修复方法。我按照 jsds 的指示停止调用 loadview 和 viewdidload 。相反,我将 loadview 中的所有代码移至我从 loadview 调用的另一个函数中。所有这些代码所做的就是实例化 UI (initview) 对象并根据方向将它们放置在正确的位置。

然后我创建另一个函数来从 View 中删除所有 subview 。然后,在方向更改时,我调用此函数和 initview 来销毁所有 subview ,然后在方向更改时重新创建它们。

最佳答案

UIDeviceOrientation 基本上有 6 种不同的状态,即两种纵向、两种横向、以及面朝上和面朝下。因此,假设当您将设备从水平位置拿起到垂直位置时,将触发通知。 可以使用宏 UIDeviceOrientationIsValidInterfaceOrientation 过滤faceup、facedown和未知状态

UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];

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

如果您仍然发现通知被多次触发,恐怕您可能需要使用带有标志的自定义逻辑来检查之前和当前的值。

就我而言,由于我使用响应式(Reactive) cocoa 框架,因此以下代码适用于我:

如果 (IS_IPAD) { @weakify( self ); [[[[[[[NSNotificationCenter defaultCenter]] rac_addObserverForName:UIDeviceOrientationDidChangeNotification 对象:nil] takeUntil:[self rac_willDeallocSignal]] map :^id(NSNotification *通知){ return @([[UIDevice currentDevice] 方向]); }] 过滤器:^BOOL(NSNumber *deviceOrientationNumber) { UIDeviceOrientation currentOrientation = [deviceOrientationNumber 整数值]; //我们忽略UIDeviceOrientationUnknown、UIDeviceOrientationFaceUp和UIDeviceOrientationFaceDown 返回 UIDeviceOrientationIsValidInterfaceOrientation(currentOrientation); }] 不同直到更改] 订阅下一个:^(id x) { @strongify( self ); //在这里做点什么... }]; }

此处的 uniqueUntilChanged 方法确保仅当方向更改为新的有效值时才触发代码。

关于ios - UIDeviceOrientationDidChangeNotification 多次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21943767/

相关文章:

ios - Firebase 检查用户是否已经存在

ios - 如何设置表格 View 单元格之间的空间并删除背景内容 View 的白色

ios - 为表单标题解析 PDF

objective-c - 将带有 NSTextAttachment 的 NSAttributedString 保存到文件中。如何?

objective-c - AVPlayer类事件

android - 如何处理在 VirtualBox 上的 android-x86 中强制屏幕方向的应用程序?

coldfusion - 使用 Coldfusion cfspreadsheet 格式化电子表格页面属性

iOS8 方向 : supportedInterfaceOrientations called but no orientation change

ios - UICollectionView 在滚动时重新加载错误的图像

android - 在 App Store 和 Play Store 上更新 Flutter 应用时,SharedPreference 丢失数据