Подтвердить что ты не робот

Как я могу получить уведомление, когда UIView станет видимым?

Есть ли способ получить уведомление, обратный вызов или какие-либо другие способы вызова метода всякий раз, когда UIView становится видимым для пользователя, то есть когда UIScrollview является просмотром некоторых UIView, а ViewController такого UIView получать уведомление, когда его вид теперь отображается пользователю?

Мне известно о возможном, но не очень элегантном решении проверить, в какой позиции прокручивается ScrollView (через UIScrollViewDelegate-методы) и вычислять, видно ли одно из подзонов... Но я ищу более универсальный способ сделать это.

4b9b3361

Ответ 1

Если ваше представление демонстрирует поведение, оно должно находиться в контроллере представления. На контроллере вида метод viewDidAppear будет вызываться каждый раз, когда появляется представление.

- (void)viewDidAppear:(BOOL)animated

Ответ 2

Мне удалось решить проблему следующим образом:

Сначала добавьте категорию для 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;
}

Затем в вашем представлении проверьте, установлено ли свойство окна:

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

Если он установлен, мы будем наблюдать "contentOffset" каждого надзора при любых изменениях. Если окно ничтожно, мы перестанем наблюдать. Вы можете изменить keyPath на любое другое свойство, возможно, "фрейм", если в ваших супервизорах нет 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) { }
    }
}

Теперь реализуем метод "observValueForKeyPath":

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

Ответ 3

Я не думаю, что существует универсальный способ сделать это для просмотров. Похоже, вы застряли в scrollViewDidEndScrolling и других методах ScrollViewDelegate. Но я не уверен, почему вы говорите это элегантно, они довольно просты.

Ответ 4

Свойства свойства слоя должны сообщать нам, является ли это представление видимым или нет

[view.layer visibleRect];

но это не работает для меня.

Таким образом, работа может состоять в том, чтобы использовать свойство contentOffset UiScrollView для вычисления видимости определенного вида или нет.