Прежде всего, избегайте хранения больших BLOB-объектов в Core Data, сохранение эскизов — это нормально (хотя вы должны оптимизировать свою модель для этого), но вы должны хранить полное изображение после его реконструкции в папке «Документы».
Вам обязательно следует использовать очередь, NSOperationQueue или сетевую очередь ASI. Я делаю что-то подобное в своем приложении, которое имеет несколько зависимостей. Таким образом, для каждого из 30 объектов вам нужно, чтобы блок (или рабочая функция) вызывался при загрузке 15 изображений. В идеале вы хотите сделать эту работу вне основного потока. Соберите все эти требования вместе, и я бы сказал, что вам нужно как минимум две очереди, одна для сетевых запросов и одна для рабочих блоков, и вы должны использовать NSBlockOperations, что значительно упрощает все это. Итак, код будет примерно таким...
// Loop through the objects
for (NSArray *objectParts in objectsToDownload) {
// Create our Object
Object *obj = [Object insertIntoManagedObjectContext:self.moc];
// This is the block which will do the post processing for the object
NSBlockOperation *processBlock = [NSBlockOperation blockOperationWithBlock:^{
// Do post processing here, be very careful with multi-threading CoreData
// it's likely you'll need some class to dispatch you MOCs which have all
// all the observers set up.
// We're gonna assume that all the sub-images have been stored in a instance
// variable:
[obj performPostProcessing];
}];
// Given the list of 15 images which form each object
for (NSURL *part in objectParts) {
// Create the ASI request for this part
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:part];
// Configure the request
[request setDelegate:self];
[request setDidFailSelector:@selector(partRequestDidFail:)];
[request setDidFinishSelector:@selector(partRequestDidFinish:)];
// Store the object in the UserInfo dictionary
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:obj, @"Object", nil];
[request setUserInfo:userInfo];
// Add it as a dependency
[processBlock addDependency:request];
// Add it to our network queue
[networkQueue addOperation:request];
}
// Add the processBlock to our worker queue
[workerQueue addOperation:processBlock];
}
Затем вам также нужно будет написать методы делегата, didFinish будет выглядеть примерно так...
- (void)partRequestDidFinish:(ASIHTTPRequest *)request {
// Remember this is one the main thread, so any heavy lifting should be
// put inside a block operation, and queued, which will complicate the
// dependencies somewhat, but is possible.
// Get the result data
NSData *data = [request responseData];
// Get the object that it belongs to from the user info dic
Object *obj = [[request userInfo] objectForKey:@"Object"];
// Keep track of the partial data in the object
[obj storePartialDataForPostProcessing:data];
}
И все это войдет в ваш класс, который подключается к вашему серверу и создает ваши объекты, так что это не контроллер представления или что-то еще, а просто обычный подкласс NSObject. Он должен будет иметь две очереди, контекст управляемого объекта (и, скорее всего, метод, который возвращает другой MOC для использования в потоках, что-то вроде этого:
// Fends a MOC suitable for use in the NSBlockOperations
- (NSManagedObjectContext *)moc {
// Get a blank managed object context
NSManagedObjectContext *aContext = [[UIApplication sharedApplication] managedObjectContext;
[aContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChangesFromMOC:) name:NSManagedObjectContextDidSaveNotification object:aContext];
return aContext;
}
- (void)mergeChangesFromMOC:(NSNotification *)aNotification {
@try {
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:aNotification];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:[aNotification object]];
}
@catch (NSException * e) {
NSLog(@"Stopping on exception: %@", [e description]);
}
@finally {}
}
Вам также нужно каким-то образом отслеживать прогресс, повторно ставить в очередь неудачные загрузки, отменять и сохранять MOC в конце. Повторная постановка в очередь неудачных загрузок довольно сложна. Во всяком случае, надеюсь, что это поможет.
Итак, просто чтобы уточнить, в вашем методе делегата вы должны сохранить загруженное изображение во временной переменной экземпляра вашего объекта. Затем, когда все 15 зависимостей завершены, вы можете получить доступ к этой переменной экземпляра и выполнить свою работу.
person
Daniel Thorpe
schedule
14.06.2011