Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
260 views
in Technique[技术] by (71.8m points)

swift - Why do I need to cast this generic return value?

I'm confused about generics here. The static keyword is making it difficult for me to understand.

import CoreData

@objc(Performer)
public class Performer: NSManagedObject, Fetchable {

  @NSManaged public var dob: Date

  @NSManaged public var firstName: String

  @NSManaged public var lastName: String
}

protocol Fetchable {
  static func fetchAll<T: NSManagedObject>(withPredicate predicate: NSPredicate?, in context: NSManagedObjectContext) throws -> [T]
}

extension Fetchable {

  static func fetchAll<T: NSManagedObject>(withPredicate predicate: NSPredicate?, in context: NSManagedObjectContext) throws -> [T] {
    let entityName = String(describing: self)
    let request = NSFetchRequest<T>(entityName: entityName)
    request.predicate = predicate
    return try context.fetch(request)
  }
}

let performers: [NSManagedObject] = try! Performer.fetchAll(in: context)

//Or

let performers: [Performer] = try! Performer.fetchAll(in: context) as! [Performer]

//Or

EDIT: This line was focus of my question as it was throwing an error. But fixed it by killing Xcode and re-launching.

let performers: [Performer] = try! Performer.fetchAll(in: context)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The compiler cannot infer the generic type of fetchAll<T: NSManagedObject> because there is no passed parameter with this type. This is the reason why the type must be annotated (not cast).

To return the proper NSManagedObject subclass use an associatedtype for example

protocol Fetchable {
    associatedtype FetchableType: NSManagedObject = Self
    static var entityName : String { get }
    static func fetchAll(withPredicate predicate: NSPredicate? = nil, in context: NSManagedObjectContext) throws -> [FetchableType]
}

extension Fetchable where FetchableType == Self {

    static var entityName : String {
        return NSStringFromClass(self).components(separatedBy: ".").last!
    }

    static func fetchAll(withPredicate predicate: NSPredicate? = nil, in context: NSManagedObjectContext) throws -> [FetchableType] {
        let request = NSFetchRequest<FetchableType>(entityName: entityName)
        request.predicate = predicate
        return try context.fetch(request)
  }
}

Now this line returns [Performer] without a type cast

let performers = try! Performer.fetchAll(in: context)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...