To work with IKImageBrowserView , you need to implement a data source with the following methods.
โ numberOfItemsInImageBrowser: โ imageBrowser:itemAtIndex:
This is no different from NSTableView , which has the following data source methods
โ numberOfRowsInTableView: โ tableView:objectValueForTableColumn:row:
However, the alarming difference is that while the NSTableView takes into account what is currently visible before the call โ tableView:objectValueForTableColumn:row: IKImageBrowserView seems to IKImageBrowserView over the entire range specified in โ numberOfItemsInImageBrowser: and request imageBrowser:itemAtIndex: . Unfortunately, the data source is sometimes backed up by hundreds of thousands of items, downloading all unnecessary is a terrible waste. Is there a way to make IKImageBrowserView load only visible elements (+ preload, of course), as NSTableView does?
Update
I tried to write a subclass of NSProxy , and it really worked. (well, more on that in a second) It looks like it
// .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
Now when imageBrowser asks for โ imageBrowser:itemAtIndex: I'll be back
[ILArrayItemProxy proxyWithArray:self.arrangedObjects index:index]
It works very well! The lost load is really achieved, and I no longer retrieve all the objects from the store at once. However, calling reloadData for any of the views causes trouble.
Here is the error message from 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 , on the other hand, just hangs on me without any error message if I call it reloadData .
So, did I manage to replace one problem with another, c'est la vie?