如何在UIView可见时收到通知?

时间:2010-03-16 10:12:37

标签: cocoa-touch uiview uiscrollview

当UIView对用户可见时,有没有办法获得通知,回调或其他方法来调用方法,即当UIScrollview是某些UIViews的超级视图时,这样的UIView的ViewController应该是当其视图现在对用户可见时会收到通知吗?

我知道可能的,但不是那么优雅的解决方案,检查ScrollView滚动的位置(通过UIScrollViewDelegate方法)并计算其中一个子视图是否可见...
但我正在寻找一种更普遍的做法。

4 个答案:

答案 0 :(得分:8)

我设法以这种方式解决问题:

首先,使用以下方法为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;
}

然后,在您的视图中,检查是否设置了window-property:

-(void)didMoveToWindow
{
    if(self.window != nil)
        [self observeSuperviewsOnOffsetChange];
    else
        [self removeAsSuperviewObserver];
}

如果已设置,我们将观察" contentOffset"每个超级视图的任何变化。如果窗口为零,我们将停止观察。您可以将keyPath更改为任何其他属性,也许" frame"如果您的超级浏览中没有UIScrollView:

-(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" -method:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualToString:@"contentOffset"])
    {
        [self checkIfFrameIsVisible];
    }
}

最后,检查视图框架在窗口框架内是否可见:

-(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
    }
}

答案 1 :(得分:7)

如果您的观点表现出行为,则应该在视图控制器中。在视图控制器上,每次出现视图时都会调用viewDidAppear方法。

- (void)viewDidAppear:(BOOL)animated

答案 2 :(得分:1)

我认为没有一种通用的方法可以为视图做到这一点。听起来像你被scrollViewDidEndScrolling和其他ScrollViewDelegate方法所困扰。但我不确定你为什么说它优雅,它们非常简单。

答案 3 :(得分:0)

view的图层属性应告诉我们该视图是否可见

[view.layer visibleRect];

但这对我不起作用。

因此,可以使用UiScrollView contentOffset属性来计算特定视图是否可见。