我正在尝试编写一个简单的属性观察器,可用于查看类型的更新 - 即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)
// }
//}
我已经在缺失特性工作之外孤立地测试了观察者,但自从我测试它以来已经有很多角色。我在这一点上的目标是找到一个可以编译的解决方案(希望可以更简单)
谢谢!