我的程序使用Coredata (SQLite)、NSPersistentDocument、NSTableView和一个(实体) NSArrayController。我希望将主线程中的NSTableView列绑定到我在辅助线程中填充的实体NSArrayController。
问题1:有没有可能?不幸的是,在我的例子中不起作用(当通过IB在同一线程中做所有的事情时)
目标是什么:让“抓取”(大文档平均需要2-4秒才能完成)在一个辅助线程中运行,这样我就可以在抓取时在UI上显示一个进度指示器。
问题2:在实体nsarraycontroller整理数据、获取数据等时,有没有其他推荐的方式来显示进度指示器?
提前谢谢。路易斯
// ------- ABCoredataController.h
@interface ABCoredataController : NSObject {
:
NSArrayController *ivArrayController;
}
@property (nonatomic, assign) NSArrayController *arrayController;
// ------- ABCoredataController.m
// This piece executes in Main thread...
- (void) init {
ivArrayController = [[NSArrayController alloc] init];
:
// Following is later executed in the Secondary Thread
- (void) secondaryThreadRun:(id)param {
:
// prepare everything to access coredata from a secondary thread...
[self setSecondaryThreadMOC: [[[NSManagedObjectContext alloc]init] autorelease] ];
[[self secondaryThreadMOC] setPersistentStoreCoordinator:[self mainThreadPSC]];
// prepare the (entity) array controller
[[self arrayController] setAvoidsEmptySelection:YES];
[[self arrayController] setPreservesSelection:YES];
[[self arrayController] setSelectsInsertedObjects:YES];
[[self arrayController] setClearsFilterPredicateOnInsertion:YES];
[[self arrayController] setAutomaticallyPreparesContent:YES];
[[self arrayController] setAutomaticallyRearrangesObjects:YES];
[[self arrayController] setAlwaysUsesMultipleValuesMarker:NO];
[[self arrayController] setUsesLazyFetching:NO];
[[self arrayController] setEditable:YES];
[[self arrayController] setEntityName:@"Transaction"];
// bind arrayController to the managedObjectContext
[[self arrayController] setManagedObjectContext:[self secondaryThreadMOC]];
[[self arrayController] setFilterPredicate:[self predicate]];
:然后在我控制我的XIB和所有UI的类中...
// ------- ABWindowController.m
:
// Start the secondaryThreadRun in previous class
[[self coredataCtrlTransaction] start];
// Get the pointer to the entity array controller !!! <== HERE!! is it right?
ivOut_CtEn_Transaction = [[self coredataCtrlTransaction]arrayController];
:
// Bind that entity array controller to the NSTableView columns...
if ( [self out_CtEn_Transaction] != nil ) {
for ( NSTableColumn *column in [[self out_Tableview_Transaction] tableColumns] ) {
if ( [column identifier] != nil ) {
if ( [column infoForBinding:@"value"] == nil ) {
NSString *theKeyPath=nil;
if ( [[column identifier] length] > 4 )
theKeyPath = [[column identifier] substringFromIndex:4];
else
theKeyPath = [column identifier];
[column bind: @"value" toObject: [self out_CtEn_Transaction]
withKeyPath:[NSString stringWithFormat:@"arrangedObjects.%@", theKeyPath] options:nil];
}
}
}
}发布于 2012-12-01 17:22:48
回答我自己,我发现KVO不适合线程间通信,我在MainThread中设置了观察者,但是观察者是在发起键值更改的线程( nsarraycontroller所在的辅助线程)上接收的。
因此,如果我的后台线程改变了一个值,我的后台线程将接收到关于它的KVO。这是我不想要的。
Found good comment about it here:
我找到了另一种实现目标的方法,简单得多。
我的目标是:当我的"nsarraycontroller正在获取或排列对象“时,让我展示一个旋转的轮子,在我的例子中,这意味着2-3秒。
// Last step in the preparation of the predicate
NSPredicate *predicadoFinal = nil;
predicadoFinal = [NSCompoundPredicate andPredicateWithSubpredicates:array_AND_Total];
// Use GCD (Grand Central Dispatch) to be able to show the spinning wheel
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// Do here my stuff of showing in the UI something...
[[self out_ABSpinning_DDBB] setHidden:NO];
[[self out_ABSpinning_DDBB] startAnimation:self];
});
// And here CPU consuming stuff.
// Apply the predicate to the nsarraycontroller.
// As the controller has both setAutomaticallyPreparesContent:YES
// and setAutomaticallyRearrangesObjects:YES so setting
// the predicate will automatically trigger the controller
// to process the predicate and fetch again...
[self setPredicateFINAL:predicadoFinal];
});我如何停止旋转的轮子。这也很简单,我在实体NSArrayController上设置了一个观察者,如下所示:
if (nil == ivObservableKeysABCtEn_Transaction ) {
ivObservableKeysABCtEn_Transaction = [[NSSet alloc] initWithObjects:
@"arrangedObjects",
nil];
}
:
if ( [self out_CtEn_Transaction] != nil ) {
for (NSString *keyPath in [self observableKeysABCtEn_Transaction]) {
// Añado observers para cada uno de los keyPaths en los que estoy interesado
[[self out_CtEn_Transaction] addObserver:self
forKeyPath:keyPath
options:0
context:ABObserverABCtEn_Transaction];
}
}然后在:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
// Fetch del objeto que ha cambiado en el emisor. En mi caso un BOOL
id newChange = [change objectForKey:NSKeyValueChangeNewKey];
// Detect null's
if ([NSNull null] == (NSNull*)newChange) {
newChange = nil;
} else {
:
//
// Somthing has changed in the "arrangedObjects" property
// of my coredata array controller, so it has definitely
// finished doing its work.
if ( context == ABObserverABCtEn_Transaction ) {
[[self out_ABSpinning_DDBB] stopAnimation:self];
[[self out_ABSpinning_DDBB] setHidden:YES];谢谢Luis
https://stackoverflow.com/questions/13652998
复制相似问题