当设备更改方向时,UIDeviceOrientationDidChangeNotification会多次调用。我不确定为什么会发生这种情况或如何解决它。
我要做的是保持scrollview的contentoffset相同,所以当用户旋转屏幕时,app会保留他们所在的页面。
奇怪的是当我第一次按照我想要的方式执行代码时旋转屏幕。但每次在此之后代码执行多次并最终将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实例而不是覆盖这个实例。是否有一种简单的方法来销毁此视图并重新初始化它?
EDIT2:
找到了解决办法。我按照jsds的说明停止调用loadview和viewdidload。而是将我的loadview中的所有代码移动到我从loadview调用的另一个函数。所有这些代码都会实例化UI(initview)对象,并根据方向将它们放在正确的位置。
然后我创建另一个从视图中删除所有子视图的函数。然后在方向改变时,我调用此函数和我的initview来销毁所有子视图,然后在方向更改时重新创建它们。
答案 0 :(得分: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方法确保仅在方向更改为新的有效值时才触发代码。
答案 1 :(得分:0)
您永远不应该自己调用loadView或viewDidLoad。这取决于管理框架。
如果要根据viewDidLoad中的视图边界定位或调整视图大小,请不要这样做。将其移至viewWillLayoutSubviews。当设备方向改变时,将自动调用它。
或者,使用自动布局约束,然后您根本不需要做任何事情。