Swift泛型 - 处理ARC类型修饰符的策略?

时间:2015-07-27 03:46:29

标签: ios xcode macos swift generics

我正在尝试编写一个简单的属性观察器,可用于查看类型的更新 - 即didSet的公共形式。基本实现很简单,但我想将它用于强(值和参考)类型和弱(引用)类型。后者的动机是作为一种懒惰的缓存策略,其中共享资源将保持使用,直到最后一个观察者释放它,然后它将再次查询该值 - 通常来自NSURLCache,但是否则是远程服务器。简而言之,我想要一个透明的多层缓存。

我在C ++中已经完成了这样的事情,我已经存储了一个类型,或者包含在智能指针中的类型,通过使用类型为Stode,StoredType等类型的特征,所以我可以为值类型传递特征,或者为重新计数的指针类型等传递特征。

根据我对Swift的理解,无主和弱修饰符应用于属性而不是类型本身,因此您不能执行以下操作:

  

typealias StorageType = weak T

为了解决这个限制,我抽象了我的泛型类型T以始终使用存储容器,其中容器可以使用直接类型,或者弱引用必须是基于类的{{1} }类型。 (这种努力本身就是因为你无法覆盖赋值运算符,并且转换函数在早期的beta中被放弃了)

令人沮丧的是,我遇到了编译器错误,它只是分裂了。

鉴于我不能成为第一个尝试解决此类问题的人,有没有人找到一个干净的方法呢?显然,段错误只是另一个编译器错误,但也许有一个更简单的解决方案?

作为参考,我的代码(注释中包含段错误的代码)是:

AnyClass

我的实际代码涉及的更多,我从观察者派生了一个懒惰的加载类,但这也引发了一个段错误:

public class ObserverSubscription : Hashable {

    // public (hashable)
    public var hashValue: Int { return token }

    // private
    private init(token:Int, observable:ObservableProtocol) {
        self.token = token
        self.observable = observable
    }

    deinit {
        self.observable.unsubscribe(self)
    }

    private var token:Int
    private var observable:ObservableProtocol
}


public func ==(lhs: ObserverSubscription, rhs: ObserverSubscription) -> Bool {
    return lhs.hashValue == rhs.hashValue
}



public protocol Storage {
    typealias T
    typealias StorageType
    init(t:StorageType)
    var element:StorageType { get set }
}

public class Weak<Type:AnyObject> : Storage {
    typealias T = Type
    typealias StorageType = T?
    public required init(t:StorageType) { element = t }
    public weak var element:StorageType
}


public class Strong<Type> : Storage{
    typealias T = Type
    typealias StorageType = T
    public required init(t:StorageType) { element = t }
    public var element:StorageType
}


public protocol ObservableProtocol {
    func unsubscribe(subscription:ObserverSubscription)
}


public class Observable<T, Container:Storage where T == Container.T> : ObservableProtocol {

    public typealias StorageType = Container.StorageType
    public typealias Subscription = ObserverSubscription
    public typealias ChangeNotifier = (Container.StorageType) -> ()


    public init(_ t:Container.StorageType) {
        self.value = Container(t:t)
    }

    public init(_ source:Observable<T, Container>) {
        self.value = Container(t:source.value.element)
    }


    public func subscribe(notifier:ChangeNotifier) {
        let subscription = Subscription(token: token++, observable: self)
        subscriptions[subscription] = notifier
    }

    public func unsubscribe(subscription:Subscription) {
        subscriptions.removeValueForKey(subscription)
    }

    public func subscription(notifier:(Container.StorageType) -> ()) -> Subscription {
        let subscription = Subscription(token: token++, observable: self)
        subscriptions[subscription] = notifier
        return subscription
    }

    public func update(t:Container.StorageType) {
        self.value.element = t
    }

    public private(set) var value:Container { didSet {
        for n in subscriptions.keys {
            self.subscriptions[n]!(self.value.element)
        }}}


    private var token:Int = 0
    private var subscriptions: [Subscription: ChangeNotifier] = [:]
}


public class ValueObserver<T> : Observable<T, Strong<T>> {
    override init(_ t:StorageType) {
        super.init(t)
    }
}

// dare ye segfault?

//public class WeakObserver<T:AnyObject> : Observable<T, Weak<T>> {
//    override init(_ t:StorageType) {
//        super.init(t)
//    }
//}

我已经在缺失特性工作之外孤立地测试了观察者,但自从我测试它以来已经有很多角色。我在这一点上的目标是找到一个可以编译的解决方案(希望可以更简单)

谢谢!

0 个答案:

没有答案