как говорится в теме - я пытаюсь обновить NSManagedObject
в другой теме.приложение для моего iPhone загружает несколько Asset
и хочет обновить downloadStatus
указанного объекта.из-за двух разных потоков я создаю новый NSManagedObjectContext
и выбираю Актив в методе main
моих NSOperation
/ ASIHTTPRequest
.
первых 1-n Asset
sзагружаются без проблем, но затем я получаю EXC_BAD_ACCESS
при попытке сохранить контекст.
вот мой код
AssetDownload.h
#import "ASIHTTPRequest.h"
@interface AssetDownload : ASIHTTPRequest
{
@private
Asset *_tempAsset;
NSManagedObjectID *_assetId;
NSManagedObjectContext *_ctx;
}
@property (nonatomic, strong) NSManagedObjectID *assetId;
@property (nonatomic, strong) NSManagedObjectContext *ctx;
- (id) initWithURL:(NSURL *)assetUrl andAsset:(NSManagedObjectID *)assetId;
+ (id) requestWithURL:(NSURL *)newURL andAsset:(NSManagedObjectID *)assetId;
@end
и AssetDownload.m
#import "AssetDownload.h"
#import "DataController.h"
@interface AssetDownload (Private)
- (void) checkArticleStatusForAsset;
@end
@implementation AssetDownload
@synthesize assetId=_assetId;
@synthesize ctx=_ctx;
- (id) initWithURL:(NSURL *)assetUrl andAsset:(NSManagedObjectID *)assetId
{
self = [self initWithURL:assetUrl];
if (self)
{
self.assetId = assetId;
}
return self;
}
//
- (void) main
{
// CORE DATA & MULTITHREADING
_ctx = [[NSManagedObjectContext alloc] init];
[self.ctx setUndoManager:nil];
[self.ctx setPersistentStoreCoordinator: [[DataController sharedInstance] persistentStoreCoordinator]];
// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:self.ctx];
// get the asset from temp managedContext
NSError *err;
_tempAsset = (Asset *) [self.ctx existingObjectWithID:self.assetId error:&err];
if (_tempAsset == nil)
{
// asset not found
NSLog(@"download asset data not found in CoreData - cancel download");
return;
}
if ([_tempAsset isAvailable])
{
NSLog(@"AssetDownload main() >>> already downloaded -> COMPLETE");
complete = YES;
[self markAsFinished];
[self checkArticleStatusForAsset];
return;
}
NSLog(@"AssetDownload main() >>> download");
[super main];
}
//
- (void) requestFinished
{
NSLog(@"AssetDownload requestFinished() >>> %i", self.responseStatusCode);
NSError *mError;
NSFileManager *fmngr = [NSFileManager defaultManager];
if (self.responseStatusCode == 200)
{
if ([fmngr moveItemAtPath:self.downloadDestinationPath toPath:_tempAsset.localPath error:&mError])
{
NSLog(@"file moved: %@", _tempAsset.localPath);
_tempAsset.downloadStatus = DownloadStatusComplete;
[self checkArticleStatusForAsset];
}
else
{
NSLog(@"ERROR file not moved: %@ ... %@", _tempAsset.localPath, mError);
_tempAsset.downloadStatus = DownloadStatusError;
}
}
else
{
[fmngr removeItemAtPath:self.downloadDestinationPath error:nil];
_tempAsset.downloadStatus = DownloadStatusError;
}
NSError *sError;
[self.ctx save:&sError];
[super requestFinished];
}
//
- (void) failWithError:(NSError *)theError
{
NSLog(@"AssetDownload failWithError() >>> %@", theError);
_tempAsset.downloadStatus = DownloadStatusError;
[self.ctx save:nil];
[super failWithError:theError];
}
//
- (void) checkArticleStatusForAsset
{
if (_tempAsset.article.isLoaded)
{
NSDictionary *info = [NSDictionary dictionaryWithObject:_tempAsset.article forKey:@"article"];
[[NSNotificationCenter defaultCenter] postNotificationName:kNotificationArticleAssetsLoaded
object:self
userInfo:info];
}
}
#pragma mark -
- (void) mergeChanges:(NSNotification *)notification
{
if ([notification object] == self.ctx)
{
NSLog(@"MERGE !");
NSManagedObjectContext *mainContext = [[DataController sharedInstance] managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
}
#pragma mark -
//
+ (id) requestWithURL:(NSURL *)newURL andAsset:(NSManagedObjectID *)assetId andManager:(AssetManager*)manager
{
return [[self alloc] initWithURL:newURL andAsset:assetId andManager:manager];
}
@end
и именно здесь происходит ОШИБКА (в requestFinished:
)
NSError *sError;
[self.ctx save:&sError];
, может быть, кто-то может объяснить мне, почему это происходит!?