(可可错误1570.)," NSValidationErrorKey"错误

时间:2017-12-19 02:57:02

标签: swift cocoa core-data mkmapview nsmanagedobject

我的应用程序应该删除名为" Pin"的NSManagedObjects。包含以下属性:

@NSManaged public var imageData: NSData?
@NSManaged public var imageURL: String?
@NSManaged public var title: String?
@NSManaged public var pin: Pin?

...但是,我收到了错误:

"NSLocalizedDescription": The operation couldn’t be completed. (Cocoa error 1570.), "NSValidationErrorKey": imageData]

将imageData属性设置为可选属性,因此我对Core Data无法删除的原因感到有些困惑。

这是执行删除的didSelect函数:

    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {

    if !isEditing {
        do {
            let pinAnnotation = view.annotation as! PinAnnotation
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Pin")
            let predicate = NSPredicate(format: "latitude == %@ AND longitude == %@", argumentArray: [pinAnnotation.coordinate.latitude, pinAnnotation.coordinate.longitude])
            fetchRequest.predicate = predicate
            let pins = try CoreDataStack.sharedInstance().context.fetch(fetchRequest) as? [Pin]
            selectedPin = pins![0]
        } catch let error as NSError {
            print("failed to get pin by object id")
            print(error.localizedDescription)
            return
        }
        self.performSegue(withIdentifier: "collectionViewSegue", sender: self)
    } else {
        mapView.removeAnnotation(view.annotation!)
        if let selectedPin = selectedPin {
            CoreDataStack.sharedInstance().context.delete(selectedPin)
        }
        CoreDataStack.sharedInstance().saveContext()
        return
    }
}

我的引脚类:

    convenience init(latitude: Double, longitude: Double, context: NSManagedObjectContext) {
    if let entity = NSEntityDescription.entity(forEntityName: "Pin", in: context) {
        self.init(entity: entity, insertInto: context)
        self.latitude = latitude
        self.longitude = longitude
    } else {
        fatalError("Unable to find entity name")
    }
}

Pin属性扩展:

extension Pin {

@nonobjc public class func fetchRequest() -> NSFetchRequest<Pin> {
    return NSFetchRequest<Pin>(entityName: "Pin")
}

@NSManaged public var latitude: Double
@NSManaged public var longitude: Double
@NSManaged public var images: NSSet?

}

...并且Pin NSManagedObject的实例化:

@objc func handleLongPress(_ gestureRecognizer : UIGestureRecognizer) {
    if gestureRecognizer.state != .began { return }
    print("Tap gesture recognized")

    // Create the annotation
    let touchPoint = gestureRecognizer.location(in: mapView)
    let newCoordinate = self.mapView.convert(touchPoint, toCoordinateFrom:self.mapView)
    let annotation = MKPointAnnotation()
    annotation.coordinate = newCoordinate

    // Initialize NSManagedObject 'Pin' with properties
    selectedPin = Pin(context: CoreDataStack.sharedInstance().context)
    selectedPin?.latitude = annotation.coordinate.latitude
    selectedPin?.longitude = annotation.coordinate.longitude

    if let selectedPin = selectedPin {
        let pinAnnotation = PinAnnotation(objectID: selectedPin.objectID, title: nil, subtitle: nil, coordinate: annotation.coordinate)
        mapView.addAnnotation(pinAnnotation)

        FlickrClient.sharedInstance().getImagesFromFlickr(pin: selectedPin, context: CoreDataStack.sharedInstance().context, page: 1) { (images, error) in

            guard error == nil else {
                print("There was an error get images objects")
                return
            }

            if let images = images {
                for image in images {
                    image.pin = selectedPin
                }
                performUIUpdatesOnMain {
                    self.images = images
                    CoreDataStack.sharedInstance().saveContext()
                }
            }
        }
    }
    print("The context has changes: \(CoreDataStack.sharedInstance().context.hasChanges)")
    CoreDataStack.sharedInstance().saveContext()

}

建议?

1 个答案:

答案 0 :(得分:0)

我通过删除保存功能的一个实例解决了这个问题:

CoreDataStack.sharedInstance().saveContext()

在我的handleLongPress函数的底部。在将视图分配给视图控制器中的局部变量之前调用此方法。 saveContext()只需要在performUIUpdatesOnMain(我的GCD异步方法)函数中调用。

同一个类中的代码也是不必要的:

for image in images {
                image.pin = selectedPin
            }