IKImageBrowserView ленивая загрузка? - PullRequest
6 голосов
/ 28 января 2012

Для работы с IKImageBrowserView необходимо реализовать источник данных следующими методами

– numberOfItemsInImageBrowser:
– imageBrowser:itemAtIndex:

Это не отличается от NSTableView, который имеет следующие методы источника данных

– numberOfRowsInTableView:
– tableView:objectValueForTableColumn:row:

Однако тревожная разница заключается в том, что, хотя NSTableView учитывает то, что в данный момент видно перед вызовом – tableView:objectValueForTableColumn:row:, IKImageBrowserView, кажется, выполняет итерацию по всему диапазону, указанному в – numberOfItemsInImageBrowser:, и запрашивает imageBrowser:itemAtIndex:. К сожалению, источник данных иногда поддерживается сотнями тысяч элементов, а загрузка всех ненужных является ужасной тратой. Есть ли способ заставить IKImageBrowserView загружать только видимые элементы (+, конечно, предварительную загрузку), как это делает NSTableView?

Обновление

Я попытался написать подкласс NSProxy, и это действительно сработало. (ну, об этом чуть позже) Это выглядит так

// .h file

#import <Foundation/Foundation.h>

@interface ILArrayItemProxy : NSProxy

- (id)initWithArray:(id)array index:(NSUInteger)index;

+ (id)proxyWithArray:(id)array index:(NSUInteger)index;

@end

// .m file

#import "ILArrayItemProxy.h"

@interface ILArrayItemProxy() {
    id _array;
    NSUInteger _index;
}

@property (readonly) id target;

@end

@implementation ILArrayItemProxy

- (id)initWithArray:(id)array index:(NSUInteger)index {
    _array = array;
    _index = index;
    return self;
}

- (id)target {
    return [_array objectAtIndex:_index];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}
+ (id)proxyWithArray:(id)array index:(NSUInteger)index {
    return [[ILArrayItemProxy alloc] initWithArray:array index:index];
}

@end

Теперь, когда imageBrowser запрашивает – imageBrowser:itemAtIndex:, я бы вернул

[ILArrayItemProxy proxyWithArray:self.arrangedObjects index:index];

Это работает очень хорошо! Ленивая загрузка действительно достигнута, и я больше не извлекаю все объекты из магазина одновременно. Однако при вызове reloadData на любом из представлений возникают проблемы.

Вот сообщение об ошибке от NSTableView

Cannot update for observer <NSAutounbinderObservance 0x105889dd0> for the key path 
"objectValue.status" from <NSTableCellView 0x105886a80>, most likely because the value
 for the key "objectValue" has changed without an appropriate KVO notification being sent.
 Check the KVO-compliance of the NSTableCellView class.
2012-01-29 11:48:01.304 [62895:707] (
    0   CoreFoundation                      0x00007fff92bf6286 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff91d3ad5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff92bf60ba +[NSException raise:format:arguments:] + 106
    3   CoreFoundation                      0x00007fff92bf6044 +[NSException raise:format:] + 116
    4   Foundation                          0x00007fff9154b519 -[NSKeyValueNestedProperty object:withObservance:didChangeValueForKeyOrKeys:recurse:forwardingValues:] + 689
    5   Foundation                          0x00007fff9154986f NSKeyValueDidChange + 186
    6   Foundation                          0x00007fff914f60fb -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 130
    7   AppKit                              0x00007fff90a2c26d -[NSTableRowData _addViewToRowView:atColumn:row:] + 434
    8   AppKit                              0x00007fff90a2bf81 -[NSTableRowData _addViewsToRowView:atRow:] + 200
    9   AppKit                              0x00007fff90a2abe3 -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] + 404
    10  AppKit                              0x00007fff90a2a9e2 -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] + 184
    11  AppKit                              0x00007fff90a2a928 -[NSTableRowData _addRowViewForVisibleRow:] + 38
    12  AppKit                              0x00007fff90a2a06c -[NSTableRowData _unsafeUpdateVisibleRowEntries] + 448
    13  AppKit                              0x00007fff90a29e87 -[NSTableRowData updateVisibleRowViews] + 95
    14  AppKit                              0x00007fff909c1c56 -[NSTableView viewWillDraw] + 156
    15  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    16  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    17  AppKit                              0x00007fff909254a2 -[NSScrollView viewWillDraw] + 43
    18  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    19  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    20  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    21  AppKit                              0x00007fff90924f7b -[NSSplitView viewWillDraw] + 67
    22  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    23  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    24  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    25  AppKit                              0x00007fff90924f7b -[NSSplitView viewWillDraw] + 67
    26  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    27  AppKit                              0x00007fff90924c11 -[NSView viewWillDraw] + 666
    28  AppKit                              0x00007fff90923952 -[NSView _sendViewWillDrawInRect:clipRootView:suppressRecursion:] + 1358
    29  AppKit                              0x00007fff909226c1 -[NSView displayIfNeeded] + 1039
    30  AppKit                              0x00007fff9091e6fa -[NSAnimationManager animationTimerFired:] + 2593
    31  Foundation                          0x00007fff91537014 __NSFireTimer + 102
    32  CoreFoundation                      0x00007fff92baaf84 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
    33  CoreFoundation                      0x00007fff92baaad6 __CFRunLoopDoTimer + 534
    34  CoreFoundation                      0x00007fff92b8b471 __CFRunLoopRun + 1617
    35  CoreFoundation                      0x00007fff92b8aae6 CFRunLoopRunSpecific + 230
    36  HIToolbox                           0x00007fff8cdf63d3 RunCurrentEventLoopInMode + 277
    37  HIToolbox                           0x00007fff8cdfd58f ReceiveNextEventCommon + 181
    38  HIToolbox                           0x00007fff8cdfd4ca BlockUntilNextEventMatchingListInMode + 62
    39  AppKit                              0x00007fff908e63f1 _DPSNextEvent + 659
    40  AppKit                              0x00007fff908e5cf5 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
    41  AppKit                              0x00007fff908e262d -[NSApplication run] + 470
    42  AppKit                              0x00007fff90b6180c NSApplicationMain + 867

IKImageBrowserView, с другой стороны, просто висел бы на мне без какого-либо сообщения об ошибке, если бы я назвал его reloadData.

Так, да, мне удалось заменить одну проблему другой, c'est la vie?

...