viewDidLayoutSubviews在touchesBegan之后被反复调用

4
一个iPhone文字游戏中,我有一个UIScrollView(包含UIImageView),并且最初放置在底部(并且在滚动视图之外)的7个可拖动的自定义UIView

app screenshot

在单个ViewController.m文件中,我覆盖了viewDidLayoutSubviews方法,以便它始终设置滚动视图的zoomScale值,使UIImageView恰好填充屏幕宽度的100%。
这很有效 - 无论是纵向还是横向模式。当应用程序刚启动时也是如此。

portrait

landscape

我的问题是,当我第一次对滚动视图进行缩放/放大手势操作(pinch/zoom/double-tap),然后移动其中一个七个Tile.m视图之一时:
有时会突然调用touchesBegan后的viewDidLayoutSubviews
这会意外地重置滚动视图的缩放,给用户带来不便。
我的问题是,是否有任何方法可以禁用此行为?
是否可能在触摸/拖动其子UIView时防止父级调用viewDidLayoutSubviews
更新:
我已将zoomScale设置代码从viewDidLayoutSubviews移动到didRotateFromInterfaceOrientation,现在滚动视图的缩放正常了,但是它的contentOffset被重置为{0,0},当我拖动Tile时(不总是)-即滚动视图突然跳动,应用程序无法使用。

将以下代码添加到viewDidLoad并没有起到帮助作用:

if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)])
   self.automaticallyAdjustsScrollViewInsets = NO;
1个回答

11

viewDidLayoutSubviews会在视图(layoutSubviews)进行布局时被调用。这可能会因为很多原因而被调用; 你可以子类化你的视图,实现一个空的layoutSubviews方法(不要忘记调用super实现!),并在那里设置断点以查看是谁导致了布局。你也可能想实现setNeedsLayoutlayoutIfNeeded,并在这些地方设置断点以便于调试,因为这些会在后续runloop上触发布局。

但你永远无法防止布局。系统会在许多你无法控制的情况下执行布局。例如,如果用户进行通话,退出电话应用程序并返回到你的应用程序;布局会被触发,因为窗口的边界和框架已经改变。通话结束后;布局再次被触发,因为此时窗口已恢复到先前的大小。

你应该负责确定何时设置缩放比例。例如,如果用户开始手势操作,则应该通知你的代码不要执行更改,即使已执行布局。


+1 谢谢。我已经将 zoomScale 设置代码移动到 didRotateFromInterfaceOrientation 中,现在滚动视图缩放正常了,但是当(不总是)我拖动一个 Tile 时,contentOffset 会被重置为 {0,0},也就是说滚动视图会突然跳动,应用程序无法使用。 - Alexander Farber
1
@AlexanderFarber 子类化滚动视图并查看是谁将其设置为 {0,0}。我甚至不得不锁定我的滚动视图以忽略来自不需要的系统决策的滚动。但你必须找出是谁在这样做。 - Léo Natan
1
@AlexanderFarber 那是什么导致的? - Léo Natan
1
@AlexanderFarber 如果您有其他问题,请告诉我。 - Léo Natan
@AlexanderFarber 你可以在我的页面上找到我的领英详细信息。 - Léo Natan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接