Q:

Swift 3 - NSFetchRequest Distinct Results

Any help appreciated.   
Xcode auto updated to 8...  I am Targeting IOS 9.3  
Have all of the code converted across but one thing is now breaking, I have tried various suggestions in similar questions! My fetch request that was previously working is now breaking.
My goal is to get a distinct list.  The app crashes on the line:
let results = try context.fetch(fetchRequest) 

With the error described in the console as:
Could not cast value of type 'NSKnownKeysDictionary1' (0x10fd29328) to 'MyApp.BodyType' (0x10eebc820).

Here is the function
func getBodyTypes() {
            let context = ad.managedObjectContext
            let fetchRequest = NSFetchRequest<BodyType>(entityName: "BodyType")
            fetchRequest.propertiesToFetch = ["name"]
            fetchRequest.returnsDistinctResults = true
            fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType

            do {
                let results = try context.fetch(fetchRequest)

                for r in results {
                    bodyTypes.append(r.value(forKey: "name") as! String)
                }
            } catch let err as NSError {
                print(err.debugDescription)
            }
}

If the line below is hidden it doesn't break, but then i don't get what i want! 
fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType 

I understand i could use all of the results (4300) and loop through them as a bandaid fix, but this doesn't feel like the correct way to fix this, especially as it was working before!

A:

The trick is to make the generic more general - instead of <BodyType> in your fetch request, use <NSFetchRequestResult>:
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "BodyType")

The result of this fetch request is [Any], so you will need to cast to the appropriate dictionary type before using. Eg:
func getBodyTypes() {
    let context = ad.managedObjectContext
    // 1) use the more general type, NSFetchRequestResult, here:
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "BodyType")
    fetchRequest.propertiesToFetch = ["name"]
    fetchRequest.returnsDistinctResults = true
    fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType

    do {
        let results = try context.fetch(fetchRequest)

        // 2) cast the results to the expected dictionary type:
        let resultsDict = results as! [[String: String]]

        for r in resultsDict {
            bodyTypes.append(r["name"])
        }

    } catch let err as NSError {
        print(err.debugDescription)
    }
}

Note: NSFetchRequestResult is a protocol, adopted by four types:
- NSDictionary,
- NSManagedObject,
- NSManagedObjectID, and
- NSNumber 
Typically, we're using it with an NSManagedObject, such as your BodyType. In this case, though, you're getting the dictionary type because of the statement:
fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType

