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

Iphone 正在尝试更新ASIHTTPRequest/后台线程中的NSManagedObject,iphone,ios,core-data,asihttprequest,nsmanagedobject,Iphone,Ios,Core Data,Asihttprequest,Nsmanagedobject,正如主题所述,我正试图在另一个线程中更新一个NSManagedObject。 我的iPhone应用程序正在下载多个资产,并希望更新给定对象的下载状态。由于两个不同的线程,我正在创建一个新的NSManagedObjectContext,并在我的NSOperation的main方法中获取资产 下载第一个1-n资产s时没有问题,但在尝试保存上下文时,我获得了一个EXC\u BAD\u访问 这是我的密码 AssetDownload.h #import "ASIHTTPRequest.h" @inter

正如主题所述,我正试图在另一个线程中更新一个
NSManagedObject
。 我的iPhone应用程序正在下载多个
资产
,并希望更新给定对象的
下载状态
。由于两个不同的线程,我正在创建一个新的
NSManagedObjectContext
,并在我的
NSOperation的
main
方法中获取资产

下载第一个1-n
资产
s时没有问题,但在尝试保存上下文时,我获得了一个
EXC\u BAD\u访问

这是我的密码

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:
中)


也许有人能向我解释为什么会发生这种事

好的,我重构了整个过程,并将更新移动到
资产

我没有用
ObjectID
获取
资产
,而是将其传递到
AssetDownload
类中并执行

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

到目前为止效果很好。。。而且代码比以前少得多:)

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