核心数据:应用程序在访问NSManagedObject属性

时间:2016-04-15 18:15:45

标签: ios swift uitableview core-data

我描述了这个问题。我有一个CoreData实体" New"。我使用带有tableView的fetchedResultsController来呈现对象。问题是,当应用程序尝试更新标签时,它崩溃了(单元格有两个标签,但是应用程序总是在同一个句子中崩溃,更新相同的标签......)。

这里有一些代码:

  • 这是CoreDataManager的定义:

{

// MARK: - Shared Instance

/**
*  This class variable provides an easy way to get access
*  to a shared instance of the CoreDataStackManager class.
*/
class func sharedInstance() -> CoreDataStackManager {

    struct Singleton {
        static let instance = CoreDataStackManager()
    }
    return Singleton.instance
}

// MARK: - The Core Data stack. The code has been moved, unaltered, from the AppDelegate.
lazy var applicationDocumentsDirectory : NSURL = {

    let urls  = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1]
}()

lazy var managedObjectModel: NSManagedObjectModel = {

    let modelURL = NSBundle.mainBundle().URLForResource("Model", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {

    let coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent(SQLITE_FILE_NAME)

    var failureReason = "There was an error creating or loading the application's saved data."
    do {
        try coordinator?.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
    } catch {
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason

        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
        abort()
    }

    return coordinator
}()

lazy var managedObjectContext: NSManagedObjectContext = {

    let coordinator = self.persistentStoreCoordinator
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator

    return managedObjectContext
}()

// MARK: - Core Data Saving support
func saveContext() {

    if managedObjectContext.hasChanges {

        managedObjectContext.performBlockAndWait {
            do {
                try self.managedObjectContext.save()
            } catch {
                let nserror = error as NSError
                NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
                abort()
            }
        }
    }
  • 此处,应用崩溃的地方:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    
        let cell = tableView.dequeueReusableCellWithIdentifier("HotNewsCell") as! NewsTableViewCell
        let new = fetchedResultsController.objectAtIndexPath(indexPath) as! New
    
        configureCell(cell, new: new)
    
        return cell
    }
    
    private func configureCell(cell: NewsTableViewCell, new: New) {
    
    cell.titleLabel.text = new.title
    /* Next line is where app crashes :( */
    cell.descriptionLabel.text = new.newBody
    
    if let url = NSURL(string: new.photoReference) {
    
        cell.activityIndicator.startAnimating()
    
        if new.image != nil {
            cell.imageViewNews.image = new.image
            cell.activityIndicator.stopAnimating()
        }
        else {
    
            let task = NetworkRequests.sharedInstance().makeImageRequestFromURL(url) { (data, error) in
    
                guard error == nil else {
                    print(error)
                    return
                }
    
                guard let data = data else {
                    print("No data available")
                    return
                }
    
                let image = UIImage(data: data)
                new.image = image
    
                dispatch_async(dispatch_get_main_queue())
                {
                    cell.imageViewNews.image = image
                    cell.activityIndicator.stopAnimating()
                }
            }
    
            cell.taskToCancelifCellIsReused = task
        }
    }
    

很奇怪,因为如果我发表评论" cell.descriptionLabel.text = new.newBody",应用效果非常好。

谢谢!

修改

错误是EXC_BAD_ACCESS。然后,我启用了NSZombie,错误是"消息被发送到解除分配的实例"。

1 个答案:

答案 0 :(得分:1)

我认为这是使用以new....开头的属性名称的人工制品。要避免此问题,只需更改属性的名称。

另请参阅this answer一个不相关的问题,该问题突出了new...的问题。从答案中确定的document(Clang文档),从技术上看,如果角色紧跟在" new"之后,问题就不会出现。是一个小写字母。所以newbody可以,而newBody则不行。此外,为了完整性,同样应避免使用以下前缀(尽管它们不太可能是属性名称的选择):

  • 的alloc
  • 复制
  • mutableCopy
  • 初始化

有趣的是,Xcode(至少版本7.3;不确定以前的版本)将不允许在Objective-C中使用这些属性名称,从而产生编译器错误:

  

属性遵循Cocoa命名惯例,用于返回'拥有的'对象

可悲的是,Swift编译器没有给出任何错误或警告。