加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Swift 3中的多个NSFetchedResultsControllers

发布时间:2020-12-14 04:37:56 所属栏目:百科 来源:网络整理
导读:我在 Swift中有一个包装多个NSFetchedResultsControllers的类,成为它们的委托,并在返回它自己的委托之前转换IndexPaths.只要这些类符合相同的协议,该类就可以使NSFetchedResultsControllers返回不同的实体.升级到Swift 3时,我无法获得相同的编译功能. 假设我
我在 Swift中有一个包装多个NSFetchedResultsControllers的类,成为它们的委托,并在返回它自己的委托之前转换IndexPaths.只要这些类符合相同的协议,该类就可以使NSFetchedResultsControllers返回不同的实体.升级到Swift 3时,我无法获得相同的编译功能.

假设我想要包装两个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’的具体类型”这是完全有道理的.

但我不确定另一种方法可以做我想做的事情.

解决方法

这看起来像……

enter image description here

键入擦除!

在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

(也在上面)似乎同样有效.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读