尝试更新ASIHTTPRequest /后台线程中的NSManagedObject

时间:2012-01-20 20:16:51

标签: iphone ios core-data asihttprequest nsmanagedobject

喜欢主题状态 - 我正在尝试更新另一个线程中的NSManagedObject。 我的iPhone应用程序正在下载多个Asset,并希望更新给定对象的downloadStatus。因为有两个不同的主题我正在创建一个新的NSManagedObjectContext,并使用main / NSOperation的{​​{1}}方法获取资产。

下载的第一个1-n ASIHTTPRequest没有问题,但在尝试保存上下文时我得到Asset

这是我的代码

AssetDownload.h

EXC_BAD_ACCESS

和AssetDownload.m

#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

这就是ERROR发生的地方(在#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:

也许有人可以向我解释为什么会发生这种情况!?

1 个答案:

答案 0 :(得分:0)

好吧,我重构了整个事情并将更新移到了Asset类。

而不是使用Asset获取ObjectID我只是将其传递到AssetDownload类并执行

- (void) updateDownloadStatus:(TCRDownloadStatus)status
{
    NSNumber *statusNum = [NSNumber numberWithInt:status];
    [self.asset performSelectorOnMainThread:@selector(updateDownloadStatus:)    
                                 withObject:statusNum
                              waitUntilDone:YES];
}

每当状态发生变化时。

到目前为止效果很好......而且代码远远少于以前:)