喜欢主题状态 - 我正在尝试更新另一个线程中的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:
也许有人可以向我解释为什么会发生这种情况!?
答案 0 :(得分:0)
Asset
类。
而不是使用Asset
获取ObjectID
我只是将其传递到AssetDownload
类并执行
- (void) updateDownloadStatus:(TCRDownloadStatus)status
{
NSNumber *statusNum = [NSNumber numberWithInt:status];
[self.asset performSelectorOnMainThread:@selector(updateDownloadStatus:)
withObject:statusNum
waitUntilDone:YES];
}
每当状态发生变化时。
到目前为止效果很好......而且代码远远少于以前:)