Синхронизация представлений прокрутки

Пользовательский интерфейс приложения может потребовать, чтобы прокрутка причин представления прокрутки синхронизировала прокрутку в другом представлении прокрутки. Вы синхронизируете прокрутку двух представлений прокрутки при наличии регистра представлений для получения уведомлений об изменениях в довольном других границы представления.

Например, интерфейс имеет два смежных представления прокрутки: правые и левые представления прокрутки. Правильная прокрутка просматривает регистры для получения уведомлений границ, отправленных представлением содержания левого представления прокрутки. Точно так же оставленное представление прокрутки регистрируется для изменений уведомления границ, отправленных правильным представлением содержания представления прокрутки. Когда представление прокрутки получает, границы изменяют уведомление, оно определяет который представление содержания, измененное путем исследования объекта, возвращенного путем отправки уведомлению метода объекта. Это тогда проверяет, чтобы видеть, является ли его источник уже в источнике довольного границами представления и если это не, это прокручивает к тому расположению. Эта проверка гарантирует, что представление прокрутки не прокручивает, если это уже в корректном расположении, предотвращая уведомления, отправляемые в другое представление прокрутки и вызывающий бесконечный цикл.

Реализация этой синхронизации универсальным способом лучше всего сделана путем разделения на подклассы NSScrollView. SynchroScrollView пример класса синхронизирует прокрутку только в вертикальной плоскости и требует следующего:

SynchroScrollView реализация полагается на представление прокрутки, сохраняемое некоторым другим объектом, обычно сама иерархия представления. Это - ответственность приложения повредить синхронизацию между представлениями, прежде чем будут освобождены представления.

Перечисление 1 показывает объявление класса.

Перечисление 1  SynchroScrollView.h объявление класса

@interface SynchroScrollView : NSScrollView {
    NSScrollView* synchronizedScrollView; // not retained
}
 
- (void)setSynchronizedScrollView:(NSScrollView*)scrollview;
- (void)stopSynchronizing;
- (void)synchronizedViewContentBoundsDidChange:(NSNotification *)notification;
 
@end

synchronizedScrollView переменная используется для отслеживания синхронизируемого представления прокрутки. Оба синхронизирующиеся представления прокрутки установлены как друг друга synchronizedScrollView. В результате synchronizedScrollView слабая ссылка, и она не сохраняется.

Приложение инициирует синхронизацию путем отправки обоих a представления прокрутки setSynchronizedScrollView: сообщение, передавая другое представление прокрутки как параметр. Перечисление 2 показывает SynchroScrollView реализация setSynchronizedScrollView:.

Перечисление 2  SynchroScrollView.m реализация setSynchronizedScrollView:

- (void)setSynchronizedScrollView:(NSScrollView*)scrollview
{
    NSView *synchronizedContentView;
 
    // stop an existing scroll view synchronizing
    [self stopSynchronizing];
 
    // don't retain the watched view, because we assume that it will
    // be retained by the view hierarchy for as long as we're around.
    synchronizedScrollView = scrollview;
 
    // get the content view of the
    synchronizedContentView=[synchronizedScrollView contentView];
 
    // Make sure the watched view is sending bounds changed
    // notifications (which is probably does anyway, but calling
    // this again won't hurt).
    [synchronizedContentView setPostsBoundsChangedNotifications:YES];
 
    // a register for those notifications on the synchronized content view.
    [[NSNotificationCenter defaultCenter] addObserver:self
                         selector:@selector(synchronizedViewContentBoundsDidChange:)
                         name:NSViewBoundsDidChangeNotification
                           object:synchronizedContentView];
}

Этот метод сначала останавливает любую существующую синхронизацию путем вызова stopSynchronizing. Это тогда сохраняет ссылку на новое представление прокрутки в synchronizedScrollView. Наконец, это регистрируется для получения уведомлений изменения границ для представления содержания synchronizedScrollView. Уведомления изменения отправляются в synchronizedViewContentBoundsDidChange: метод, показанный в Перечислении 3.

Перечисление 3  SynchroScrollView.m реализация synchronizedViewContentBoundsDidChange:

- (void)synchronizedViewContentBoundsDidChange:(NSNotification *)notification
{
    // get the changed content view from the notification
    NSClipView *changedContentView=[notification object];
 
    // get the origin of the NSClipView of the scroll view that
    // we're watching
    NSPoint changedBoundsOrigin = [changedContentView documentVisibleRect].origin;;
 
    // get our current origin
    NSPoint curOffset = [[self contentView] bounds].origin;
    NSPoint newOffset = curOffset;
 
    // scrolling is synchronized in the vertical plane
    // so only modify the y component of the offset
    newOffset.y = changedBoundsOrigin.y;
 
    // if our synced position is different from our current
    // position, reposition our content view
    if (!NSEqualPoints(curOffset, changedBoundsOrigin))
    {
    // note that a scroll view watching this one will
    // get notified here
    [[self contentView] scrollToPoint:newOffset];
    // we have to tell the NSScrollView to update its
    // scrollers
    [self reflectScrolledClipView:[self contentView]];
    }
}

Представление, инициировавшее уведомление изменения, определяется путем отправки уведомления object сообщение. Источник того довольного представление определяется и новый источник, который должно отразить представление прокрутки получения, определяется. Если эти два расположения отличаются, получатель прокручивает к новому источнику. Этот тест необходим для предотвращения представления прокрутки, породившего действие прокрутки из действия на изменение в другом представлении содержания представления прокрутки, вызвав бесконечный цикл.

stopSynchronizing метод, показанный в Перечислении 4, заставляет получатель прекращать прислушиваться к уведомлениям изменения границ в синхронизируемом представлении содержания представления прокрутки и устанавливает synchronizedScrollView переменная экземпляра к nil.

Перечисление 4  SynchroScrollView.m реализация stopSynchronizing

- (void)stopSynchronizing
{
    if (synchronizedScrollView != nil) {
    NSView* synchronizedContentView = [synchronizedScrollView contentView];
 
    // remove any existing notification registration
    [[NSNotificationCenter defaultCenter] removeObserver:self
                            name:NSViewBoundsDidChangeNotification
                              object:synchronizedContentView];
 
    // set synchronizedScrollView to nil
    synchronizedScrollView=nil;
    }
}