假设我想要包装两个NSFetchedResultsControllers,返回两个不同的Entity类型,以便在单个tableView中显示.两个CoreData实体都符合以下协议
protocol ManagedobjectdisplayType : NSFetchRequestResult { var id:String { get } func friendlyName() -> String }
问题是现在NSFetchedResultsControllers是通用的,没有具体类型的NSFetchedResultsController我可以传递给我的Wrapper类,因为这两个控制器是不同类型的.
例如:
let entity1Request = NSFetchRequest<Entity1>(entityName: entityName) let entity1Frc = NSFetchedResultsController<ManagedobjectdisplayType>(fetchRequest: entity1Request,managedobjectContext:mainManagedobjectContext,sectionNameKeyPath: nil,cacheName: nil) let entity2Request = NSFetchRequest<Entity2>(entityName: entityName) let entity2Frc = NSFetchedResultsController<ManagedobjectdisplayType>(fetchRequest: entity2Request,cacheName: nil)
当我这样做时,我得到以下错误:“不支持使用’ManagedobjectdisplayType’作为符合协议’NSFetchRequestResult’的具体类型”这是完全有道理的.
但我不确定另一种方法可以做我想做的事情.
解决方法
键入擦除!
在Swift中有很多关于类型擦除的文章,但这是一个有趣的情况.我假设您在创建一个可以为您的不同类型保存多个NSFetchedResultsController的对象时遇到问题.问题是Swift(在其当前版本中)需要一个具体类型来正确分配所需的内存.标准库和其他地方的标准解决方案是创建一个隐藏基础类型的框.在这种情况下,下面的AnyFetchedResultsController类有效地擦除它所包含的具体类型(NSFetchedResultsController< T>,其中T:ManagedobjectdisplayType).
class AnyFetchedResultsController: CustomDebugStringConvertible { var descImpl: () -> String var performImpl: () throws -> () init<T>(_ controller: NSFetchedResultsController<T>) where T: ManagedobjectdisplayType { descImpl = { controller.debugDescription } performImpl = { try controller.performFetch() } } func performFetch() throws { try performImpl() } var debugDescription: String { return "wrapping \(descImpl())" } } let entity1Request = NSFetchRequest<Entity1>(entityName: "Foobar") let entity1Frc = NSFetchedResultsController<Entity1>(fetchRequest: entity1Request,cacheName: nil) let entity2Request = NSFetchRequest<Entity2>(entityName: "Barfoo") let entity2Frc = NSFetchedResultsController<Entity2>(fetchRequest: entity2Request,cacheName: nil) let frcs: [AnyFetchedResultsController] = [AnyFetchedResultsController(entity1Frc),AnyFetchedResultsController(entity2Frc)]
现在你有了一种存储这些获取结果控制器的方法,你需要使用你需要在底层NSFetchedResultsController上调用的任何其他方法来充实AnyFetchedResultsController类.
我希望这是有道理的.如果您还有其他问题,请回来!
编辑
AnyFetchedResultsController.init的原始签名:
init<T,U: NSFetchedResultsController<T>>(_ controller: U,_ managedobjectType: T? = nil) where T: ManagedobjectdisplayType
非常复杂,并且有一个虚拟的managedobjectType参数,似乎是修复某些编译器错误所必需的.但是,我刚发现更简单:
init<T>(_ controller: NSFetchedResultsController<T>) where T: ManagedobjectdisplayType
(也在上面)似乎同样有效.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。