判断UIView是否对用户可见?
是否可以确定我的 UIView
对用户是否可见?
我的视图多次作为子视图
添加到UITabBarController
中。
此视图的每个实例都有一个用于更新视图的 NSTimer
。
但是,我不想更新用户不可见的视图。
这可能吗?
Is it possible to determine whether my UIView
is visible to the user or not?
My View is added as a subview
several times into a UITabBarController
.
Each instance of this view has an NSTimer
that updates the view.
However, I don't want to update a view which is not visible to the user.
Is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
对于最终到达这里的其他人:
要确定 UIView 是否在屏幕上的某个位置,最好检查
window != nil ,而不是检查
。在前一种情况下,视图可能有一个超级视图,但超级视图不在屏幕上:superview != nil
。 =零当然,您还应该检查它是否隐藏或是否有 alpha > ; 0 。
关于不希望您的
NSTimer
在视图不可见时运行,您应该尽可能手动隐藏这些视图,并在视图隐藏时停止计时器。但是,我完全不确定你在做什么。For anyone else that ends up here:
To determine if a UIView is onscreen somewhere, rather than checking
superview != nil
, it is better to check ifwindow != nil
. In the former case, it is possible that the view has a superview but that the superview is not on screen:Of course you should also check if it is
hidden
or if it has analpha > 0
.Regarding not wanting your
NSTimer
running while the view is not visible, you should hide these views manually if possible and have the timer stop when the view is hidden. However, I'm not at all sure of what you're doing.您可以检查是否:
view.superview != nil
我唯一能想到的另一件事是,如果您的视图被埋在其他人后面并且因此而无法被看到。您可能必须仔细检查随后出现的所有视图,看看它们是否遮挡了您的视图。
You can check if:
view.superview != nil
The only other thing I can think of is if your view is buried behind others and can't be seen for that reason. You may have to go through all the views that come after to see if they obscure your view.
这将确定视图的框架是否在其所有超级视图(直到根视图)的范围内。一个实际用例是确定子视图在滚动视图中是否(至少部分)可见。
Swift 5.x:
较旧的 swift 版本
潜在改进:
alpha
和hidden
。clipsToBounds
,因为如果为 false,视图可能会超出其父视图的边界。This will determine if a view's frame is within the bounds of all of its superviews (up to the root view). One practical use case is determining if a child view is (at least partially) visible within a scrollview.
Swift 5.x:
Older swift versions
Potential improvements:
alpha
andhidden
.clipsToBounds
, as a view may exceed the bounds of its superview if false.对我有用的解决方案是首先检查视图是否有窗口,然后迭代超级视图并检查是否:
到目前为止似乎运作良好。
斯威夫特3.0
The solution that worked for me was to first check if the view has a window, then to iterate over superviews and check if:
Seems to work well so far.
Swift 3.0
我对@Audrey M. 和@John Gibb 他们的解决方案进行了基准测试。
@Audrey M. 他的方式表现更好(10 倍)。
所以我用它来使其可观察。
我制作了一个 RxSwift Observable,以便在 UIView 可见时收到通知。
如果您想触发横幅“查看”事件,这可能很有用,
如下所示:
I benchmarked both @Audrey M. and @John Gibb their solutions.
And @Audrey M. his way performed better (times 10).
So I used that one to make it observable.
I made a RxSwift Observable, to get notified when the UIView became visible.
This could be useful if you want to trigger a banner 'view' event
Use it as like this:
经过测试的解决方案。
Tested solution.
我真的想知道视图是否对用户可见,您必须考虑以下事项:
特别是前面视图的透明背景颜色可能会造成以编程方式检查的问题。真正确定的唯一方法是制作视图的编程快照,以在其框架内与整个屏幕的快照进行检查和比较。然而,这对于不够独特的视图(例如全白)不起作用。
如需灵感,请参阅 中的 isViewVisible 方法iOS Calabash-服务器项目
I you truly want to know if a view is visible to the user you would have to take into account the following:
Especially the transparent background color of views in front may pose a problem to check programmatically. The only way to be truly sure is to make a programmatic snapshot of the view to check and diff it within its frame with the snapshot of the entire screen. This won't work however for views that are not distinctive enough (e.g. fully white).
For inspiration see the method isViewVisible in the iOS Calabash-server project
我能想到的最简单的 Swift 5 解决方案适合我的情况(我正在寻找嵌入在我的 tableViewFooter 中的按钮)。
约翰·吉布斯的解决方案也有效,但在我看来,我不需要所有的递归。
The simplest Swift 5 solution I could come up with that worked in my situation (I was looking for a button embedded in my tableViewFooter).
John Gibbs solution also worked but in my cause I did not need all the recursion.
在 viewWillAppear 中将值“isVisible”设置为 true,在 viewWillDisappear 中将其设置为 false。了解 UITabBarController 子视图的最佳方法也适用于导航控制器。
In viewWillAppear set a value "isVisible" to true, in viewWillDisappear set it to false. Best way to know for a UITabBarController subviews, also works for navigation controllers.
另一个有用的方法是
didMoveToWindow()
示例:当您推送视图控制器时,之前的视图控制器的视图将调用此方法。检查
didMoveToWindow()
内部的self.window != nil
有助于了解您的视图是在屏幕上出现还是消失。Another useful method is
didMoveToWindow()
Example: When you push view controller, views of your previous view controller will call this method. Checking
self.window != nil
inside ofdidMoveToWindow()
helps to know whether your view is appearing or disappearing from the screen.这可以帮助您确定您的 UIView 是否是最顶层的视图。可能有帮助:
This can help you figure out if your UIView is the top-most view. Can be helpful:
试试这个:
try this:
如果您使用视图的隐藏属性,则:
view.hidden(目标C)或view.isHidden(swift)是读/写属性。这样你就可以轻松地读取或写入
For swift 3.0
In case you are using hidden property of view then :
view.hidden (objective C) or view.isHidden(swift) is read/write property. So you can easily read or write
For swift 3.0