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