Ich habe Probleme mit der Architektur meines Codes. Ich habe view
, die erstellen und hängen an model
Klasse. Modellklasse ist verantwortlich für alle Berechnungen und Logik. Dies bedeutet, dass es viele Dinge zu berechnen hat und Objekte aus Core-Daten erhalten.NSManagedObject in verschiedenen Threads abrufen und verwenden
Bezüglich enter link description here jedes NSManagedObject, die in einem Thread erhalten wird, muß in demselben Thread verwendet werden.
Mein Problem ist, dass auf erstellen Objekt in verschiedenen Thread erhalten werden muss, weil es einige Zeit dauert, um Modell zu bauen, aber danach muss ich Objekt und sie Eigenschaften im Hauptthread von View erhalten (zum Beispiel in CellForIndex ...)
Ich weiß, ich bin nicht der einzige mit diesem Design. Wie andere dieses Problem lösen?
EDIT:
dies mit Code betonieren.
Lassen Sie sagen, wir UIView
Objekt MyUIView
und Modellobjekt Model
MyUIView
@interface MyUIView()
@property(nonatomic) Model * model;
@end
@implementation MyUIView
- (void) createModel
{
// privateManagerContext is context manager created with
// NSPrivateQueueConcurrencyType, connected to persistent store
// and sync with "main thread" manager context with
// NSManagedObjectContextDidSaveNotification and NSManagedObjectContextDidSaveNotification
[self.model createWithManagadContext:privateManagerContext];
}
// ASSUME THAT THIS CODE IS CALLED AFTER
- (void) getNumberOfSomeProperties
{
int number = [self.model getNumberOfProperties];
}
- (void) getProperties
{
NSArray *array = [self.model properties]
}
// OR WE HAVE TO TRIGGERED SOME LONG CALCULATION
- (void) triggerLongCalculation
{
[self.model longCalculation];
}
- (void) afterNotifyModelIsCompletedCalculating
{
[self doSomeWork];
[self getProperties];
....
}
@end
Modell
@interface Model()
@property(nonatomic) NSArray * cashedProperties;
@end
@implementation MyUIView
- (void) createWithManagadContext:(NSManagedObjectContext *) privateManagerContext
{
dispatch_async(self.model_queue, ^(void){
// Here we fetch objects and do some calculations
[self populateModel];
/// Model is complete
[Notifications notifyModelIsCompletedCreating:self];
});
}
- (void) longCalculation
{
dispatch_async(self.model_queue, ^(void){
// NO CORE DATA FETCH INVOLVED
[Notifications notifyModelIsCompletedCalculating:self];
});
}
- (int) getNumberOfProperties
{
return self.cashedProperties.count;
}
- (NSArray) properties
{
NSMutableArray * a = [[NSMutableArray alloc]init];
for (Property * p in self.cashedProperties) {
[a addObject:p.name];
}
return a;
}
@end
01 haben
Wie würden Sie also in diesen hypothetischen Klassen mit NSManagedObject und NSManagedObjectContext umgehen?
EDIT 2:
I Muster sind mit dem ich erstelle zwei verwaltete Objektkontext in AppDelegate, einem privaten und eine Haupt-und schaffen sync zwischen ihnen.
- (NSManagedObjectContext *)managedObjectContext
{
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return __managedObjectContext;
}
- (NSManagedObjectContext *) privateQueueContext
{
if (_privateQueueContext != nil) {
return _privateQueueContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_privateQueueContext setPersistentStoreCoordinator:coordinator];
}
return _privateQueueContext;
}
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSavePrivateQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self privateQueueContext]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contextDidSaveMainQueueContext:)
name:NSManagedObjectContextDidSaveNotification
object:[self managedObjectContext]];
}
return self;
}
#pragma mark - Notifications
- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.managedObjectContext performBlock:^{
NSArray* objects = [notification.userInfo valueForKey:NSUpdatedObjectsKey];
for (NSManagedObject* obj in objects) {
NSManagedObject* mainThreadObject = [self.managedObjectContext objectWithID:obj.objectID];
[mainThreadObject willAccessValueForKey:nil];
}
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
- (void)contextDidSaveMainQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.privateQueueContext performBlock:^{
NSArray* objects = [notification.userInfo valueForKey:NSUpdatedObjectsKey];
for (NSManagedObject* obj in objects) {
NSManagedObject* mainThreadObject = [self.privateQueueContext objectWithID:obj.objectID];
[mainThreadObject willAccessValueForKey:nil];
}
[self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
Sie können das Objekt in den Hauptthread laden, oder Sie können eine nicht verwaltete Version des Objekts erstellen und diese nach Abschluss der Berechnungen an den Hauptthread übergeben. – Avi