ios - 我可以让 Realm Results 类使用协议(protocol)作为泛型吗?

标签 ios swift protocols realm

我想创建两个Realm模型类和一个协议(protocol),由两个模型类采用。例如:

class Dog: Object, Animal {
    dynamic var name = ""
}
class Cat: Object, Animal {
    dynamic var name = ""
}
protocol Animal {
    var name: String { get }
}

在这种情况下,我创建了两个模型类和一个协议(protocol)。

但是,当我转到实现的时候,问题出现了。下面的代码是在 View Controller 中编写的:

var dogs: Results<Dog>? {
    return try! Realm().objects(Dog)
}
var cats: Results<Cat> {
    return try! Realm().objects(Cat)
}

这段代码没有任何问题。但是下面的代码:

var animals: Results<Animal>? {
    switch currentSegmented { // this is from UISegmentedControl
    case .Cat:  // this is from enum
        return self.cats
    case .Dog:
        return self.dogs
}

未编译时出现错误:Results requires Animal inherit from Object

但是,Animal 是一个协议(protocol),因此不能从 Object 继承。

这里还可以使用协议(protocol)吗?

最佳答案

我认为没有好的解决方案。 Swift 中用户定义的泛型是不变的,所以即使 Animal是一个你不能转换的类 Results<Dog>Results<Animal> .

令人不愉快的冗长解决方案是围绕您的不同类型的结果创建一个显式包装器类型:

enum AnimalResultsEnum {
    case DogResults(dogs: Results<Dog>)
    case CatResults(cats: Results<Cat>)
}

class AnimalResults {
    var animals = AnimalResultsEnum.DogResults(dogs: try! Realm().objects(Dog))

    var realm: Realm? {
        switch animals {
        case .DogResults(let dogs):
            return dogs.realm
        case .CatResults(let cats):
            return cats.realm
        }
    }

    var count: Int {
        switch animals {
        case .DogResults(let dogs):
            return dogs.count
        case .CatResults(let cats):
            return cats.count
        }
    }

    subscript(index: Int) -> Animal {
        switch animals {
        case .DogResults(let dogs):
            return dogs[index]
        case .CatResults(let cats):
            return cats[index]
        }
    }

    // ... wrap the rest of the methods needed ...
}

您可以通过创建一个半类型删除的容器来包装结果来使其通用:

class CovariantResults<T: Object> {
    private var base: _CovariantResultsBase<T>

    init<U: Object>(_ inner: Results<U>) {
        base = _CovariantResultsImpl<T, U>(inner)
    }

    subscript(index: Int) -> T {
        return base[index]
    }

    // ... wrap the rest of the methods needed ...
}

class _CovariantResultsBase<T: Object> {
    subscript(index: Int) -> T { fatalError("abstract") }
    // ... wrap the rest of the methods needed ...
}

class _CovariantResultsImpl<T: Object, U: Object>: _CovariantResultsBase<T> {
    private let impl: Results<U>

    init(_ inner: Results<U>) {
        impl = inner
    }

    override subscript(index: Int) -> T {
        return impl[index] as! T
    }

    // ... wrap the rest of the methods needed ...
}

// Used as:
let animals = CovariantResults<Animal>(try! Realm().objects(Dog))

关于ios - 我可以让 Realm Results 类使用协议(protocol)作为泛型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34172375/

相关文章:

ios - 从 Watch 应用程序调用父应用程序时如何使用文件加密?

ios - Swift 中类型别名的枚举

swift - Realm 是否需要显式添加嵌套对象

protocols - 聊天室软件的最佳开放协议(protocol)是什么?

ios - 将参数传递给实现协议(protocol)并快速扩展类的方法

ios - 从一个类(class)向多个类(class)进行委托(delegate)调用

ios - 在 UITableView 中使用动画在顶部插入行

ios - 无法更改 UITableViewCell subview 的位置

ios - 生成的ipa会过期吗?

ios - 创建数组并将元素分配给 UITableViewCell 并取回 labelText 元素时出现问题