AFNetworking 2.0,使用 CoreData (MagicalRecord) 保存下载状态

Posted

技术标签:

【中文标题】AFNetworking 2.0,使用 CoreData (MagicalRecord) 保存下载状态【英文标题】:AFNetworking 2.0, saving download state with CoreData (MagicalRecord) 【发布时间】:2014-03-05 16:25:37 【问题描述】:

我在使用 AFNetworking 2.0 和 MagicalRecord 的应用时遇到问题。此应用从播客网站中的一个小 JSON API 下载数据,并将每个播客剧集存储在播客实体中。

此 Podcast 实体有另一个名为 PodcastDownload 的实体,用于在播客下载时保存信息(下载状态和进度)。在这个 PodcastDownload 实体中,我使用 KVO 来更新此信息,观察 NSProgress 对象和来自 NSURLSessionDownloadTask 的状态。这很好用。

但是当我尝试在名为 PodcastManager 的单例实例中使用此方法在数据上下文中保存下载状态时遇到问题:

- (void)saveContext

  [[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) 

  if (success) 
    NSLog(@"Save OK");
   else if(error) 
    NSLog(@"Error %@", error.description);
  

 ];

当我调用此方法时,我在 AFNetworking 的 AFURLSessionManager 中收到此 EXC_BAD_ACCESS 错误,但根据我的日志,保存似乎运行正常:

Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 1 inserted objects

我不知道是什么导致了这个错误。我也尝试使用 MagicalRecord 方法 saveWithBlock 但我得到了相同的结果。

这是我在 PodcastDownload 中的 KVO Observer 的源代码:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 
  if (context == PodcastDownloadContext) 

  if ([object isKindOfClass:[NSURLSessionDownloadTask class]]) 

    NSURLSessionDownloadTask *task = (NSURLSessionDownloadTask *) object;



    if (task.state == NSURLSessionTaskStateRunning) 
      [self setStatus:PodcastDownloadRunning];
      [[PodcastManager sharedManager] saveContext];
    

    if (task.state == NSURLSessionTaskStateSuspended) 
      [self setStatus:PodcastDownloadSuspended];
      [[PodcastManager sharedManager] saveContext];
    

    if (task.state == NSURLSessionTaskStateCanceling) 
      [self setStatus:PodcastDownloadCanceling];
      self.downloadTask = nil;
      self.data = nil;
      self.progress = 0;
      [[PodcastManager sharedManager] saveContext];
    

    if (task.state == NSURLSessionTaskStateCompleted) 

      if (self.status == PodcastDownloadCanceling) 
        [self setStatus:PodcastDownloadNotSet];
       else 
        [self setStatus:PodcastDownloadCompleted];
        self.downloadTask = nil;
        self.data = nil;
        self.progress = 0;
        [[PodcastManager sharedManager] saveContext];
      

      @try 
        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state)) context:PodcastDownloadContext];
        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) context:PodcastDownloadContext];
      
      @catch (NSException * __unused exception) 
    

  
 

非常感谢

【问题讨论】:

这可能与保存操作完全没有关系。在分配给它的各种属性之前,您是否检查过以确保您的 self.downloadprogress 对象已正确初始化? 是的。事实上,如果我删除保存操作,我的 PodcastDownload 对象中的属性会正确更新。请注意,在 AFURLSessionManager 中出现 EXC_BAD_ACCESS 错误。我编辑了我的问题,添加了这个,对不起,我的错。 您的 saveContext 方法对我来说似乎是正确的。我希望我能提供进一步的帮助,但也许其他人会提出建议。我会仔细检查单例代码以确保单例已正确初始化并检查变量以确保它们都已正确初始化。 EXC_BAD_ACCESS 通常在尝试使用未正确初始化的对象或将错误类型作为参数发送给其他方法(即发送 int 到期望指针的对象)时抛出。这些始终是我诊断该异常的前两个地方。 【参考方案1】:

嗯,做一些改变我找到了解决办法,但不是原因。

我的核心数据堆栈中有三个实体(Podcast、PodcastDownload 和 PodcastPlayback)。正如我在问题中解释的那样,主要实体是 Podcast,PodcastDownload 用于保存有关下载的信息。

我所做的是从 PodcastDownload 中取出属性并将它们放入 Podcast 实体中。现在似乎可以正常工作了。

我不知道错误的确切原因,但我认为它与线程有关(对不起,我对 Objective-c 还是有点菜鸟)。

感谢大家的帮助。

【讨论】:

以上是关于AFNetworking 2.0,使用 CoreData (MagicalRecord) 保存下载状态的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.0 - 是不是使用子类?

AFNetworking 2.0,使用 NSURLSession 下载图片

使用 AFNetworking 2.0 加载图像

使用 AFNetworking 2.0 异常解析 JSON

使用 afnetworking 2.0 发送字典数组

使用 AFNetworking 2.0 发送 POST 数据