Search code examples
objective-cswiftnsmanagedobject

Objective-C converting to Swift 3.1 getting error 'Any' is not convertible


I'm finally attempting to convert one of my Objective-C apps to Swift 3.1. I'm also taking a tutorial on Swift to help me out. However, I'm running into the following error when trying to convert a 'for in' loop to Swift that worked successfully in Obj-C. I've posted both the Swift and Objective-C code below and commented the line in Swift where I am getting the error. I am getting the error with for managedObject: NSManagedObject in myResults{

The error states

'Any' is not convertible to 'MSManageObject'

Any help pointing me in the right direction is greatly appreciated.

//IN SWIFT 3.1
            let context: NSManagedObjectContext? = 
CoreDataHelper.shared().context
            let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
            let entity = NSEntityDescription.entity(forEntityName: 
"Exhibitors", in: context!)
            fetchRequest.entity = entity
            var myResults : NSArray = try! 
CoreDataHelper.shared().context.fetch(fetchRequest) as NSArray
            self.objects = myResults as! [Any]
            if !(myResults != nil) || !((myResults.count) != nil) {
                print("No Exhibitor objects found to be deleted!")
            }
            else {
        //****Getting error 'Any' is not convertible to 'NSManagedObject'
                for managedObject: NSManagedObject in myResults {
                    if !(managedObject.value(forKey: "fav") == "Yes") {
                        context?.deleteObject(managedObject)
                        var error: Error? = nil
                        // Save the object to persistent store
                        if !context?.save(error) {
                            print("Can't Save! \(error) \
(error?.localizedDescription)")
                        }
                        print("Exhibitor object deleted!")
                    }
                }
            }


//IN OBJECTIVE-C
            NSManagedObjectContext *context = [[CoreDataHelper sharedHelper] 
context];

                    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] 
init];

                    NSEntityDescription *entity = [NSEntityDescription 
entityForName:@"Exhibitors" inManagedObjectContext:context];

                    [fetchRequest setEntity:entity];

                    NSArray *myResults = [[[CoreDataHelper sharedHelper] 
context] executeFetchRequest:fetchRequest error:nil];
                    self.objects = myResults;
                    if (!myResults || !myResults.count){
                        NSLog(@"No Exhibitor objects found to be deleted!");
                    }
                    else{
                        for (NSManagedObject *managedObject in myResults) {
                            if (![[managedObject valueForKey:@"fav"] 
isEqualToString:@"Yes"]) {


                                [context deleteObject:managedObject];


                                NSError *error = nil;
                                // Save the object to persistent store
                                if (![context save:&error]) {
                                    NSLog(@"Can't Save! %@ %@", error, 
[error localizedDescription]);
                                }
                                NSLog(@"Exhibitor object deleted!");

                            }
                        }
                    }

Solution

  • The main issue is that your are annotating worse types than the compiler infers.

    Don't do that. Don't annotate types unless the compiler tells you to do.

    For example the managed object context is supposed to be non-optional

    let context = CoreDataHelper.shared().context
    

    Your fetch returns [NSManagedObject], never use NSArray and never cast distinct types up to more unspecified like [Any]

    Simply write

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
    let entity = NSEntityDescription.entity(forEntityName: "Exhibitors", in: context)
    fetchRequest.entity = entity
    do {  // its always recommended to do a good error handling !!
       self.objects = try CoreDataHelper.shared().context.fetch(fetchRequest)
       for managedObject in self.objects { 
    
          ...
    
       }
    
    } catch { print(error) }
    

    If objects is empty the loop will be skipped.