每当UIView对用户可见时(例如,当UIScrollview是某些UIView的 super View 时,是否有一种方法可以获取通知,回调或其他方法来调用方法),并且在以下情况下应通知该UIView的ViewController:用户现在可以看到其 View 了吗?

我知道检查ScrollView滚动到哪个位置(通过UIScrollViewDelegate方法)并计算 subview 中的任何一个是否可见的可能但不是那么优雅的解决方案...
但我正在寻找一种更通用的方法。

最佳答案

我设法通过这种方式解决了这个问题:

首先,使用以下方法为UIView添加类别:

// retrieve an array containing all super views

-(NSArray *)getAllSuperviews
{
    NSMutableArray *superviews = [[NSMutableArray alloc] init];

    if(self.superview == nil) return nil;

    [superviews addObject:self.superview];
    [superviews addObjectsFromArray:[self.superview getAllSuperviews]];

    return superviews;
}

然后,在您的 View 中,检查是否设置了窗口属性:
-(void)didMoveToWindow
{
    if(self.window != nil)
        [self observeSuperviewsOnOffsetChange];
    else
        [self removeAsSuperviewObserver];
}

如果已设置,我们将观察任何更改的每个 super View 的“contentOffset”。如果窗口为零,我们将停止观察。您可以将keyPath更改为任何其他属性,如果 super View 中没有UIScrollView,则可以更改为“frame”:
-(void)observeSuperviewsOnOffsetChange
{
    NSArray *superviews = [self getAllSuperviews];
    for (UIView *superview in superviews)
    {
        if([superview respondsToSelector:@selector(contentOffset)])
            [superview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    }
}

-(void)removeAsSuperviewObserver
{
    NSArray *superviews = [self getAllSuperviews];
    for (UIView *superview in superviews)
    {
        @try
        {
            [superview removeObserver:self forKeyPath:@"contentOffset"];
        }
        @catch(id exception) { }
    }
}

现在实现“observeValueForKeyPath”方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualToString:@"contentOffset"])
    {
        [self checkIfFrameIsVisible];
    }
}

最后,检查 View 的框架是否在窗口的框架内可见:
-(void)checkIfFrameIsVisible
{
    CGRect myFrameToWindow = [self.window convertRect:self.frame fromView:self];
    if(myFrameToWindow.size.width == 0 || myFrameToWindow.size.height == 0) return;
    if(CGRectContainsRect(self.window.frame, myFrameToWindow))
    {
        // We are visible, do stuff now
    }
}

关于cocoa-touch - 当UIView可见时,如何获得通知?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2453457/

10-12 00:18
查看更多