Swift 不支持将AnyObject用作符合协议的具体类型
我正在使用Swift 2和WeakContainer来存储一组弱对象,很像Swift 不支持将AnyObject用作符合协议的具体类型,swift,reference,hashtable,protocols,weak,Swift,Reference,Hashtable,Protocols,Weak,我正在使用Swift 2和WeakContainer来存储一组弱对象,很像NSHashTable.weakObjectsHashTable() struct WeakContainer{ 弱var值:T? } 公共协议MyDelegate:AnyObject{ } 然后在我的ViewController中,我声明 public var delegates = [WeakContainer<MyDelegate>] public-var-delegates=[WeakContain
NSHashTable.weakObjectsHashTable()
struct WeakContainer{
弱var值:T?
}
公共协议MyDelegate:AnyObject{
}
然后在我的ViewController中,我声明
public var delegates = [WeakContainer<MyDelegate>]
public-var-delegates=[WeakContainer]
但这是错误的
不支持将MyDelegate用作符合协议AnyObject的具体类型
我看到错误是
WeakContainer
将值
成员声明为弱
,因此T
应为对象。但我也将MyDelegate
声明为AnyObject
。如何解决这个问题?为什么要尝试使用泛型?我建议采取以下措施:
import Foundation
import UIKit
protocol MyDelegate : AnyObject {
}
class WeakContainer : AnyObject {
weak var value: MyDelegate?
}
class ViewController: UIViewController {
var delegates = [WeakContainer]()
}
还有
NSValue
的nonretainedObject
我也有同样的想法,用泛型创建弱容器。因此,我为
NSHashTable
创建了包装器,并针对编译器错误进行了一些变通
class WeakSet<ObjectType>: SequenceType {
var count: Int {
return weakStorage.count
}
private let weakStorage = NSHashTable.weakObjectsHashTable()
func addObject(object: ObjectType) {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
weakStorage.addObject(object as? AnyObject)
}
func removeObject(object: ObjectType) {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
weakStorage.removeObject(object as? AnyObject)
}
func removeAllObjects() {
weakStorage.removeAllObjects()
}
func containsObject(object: ObjectType) -> Bool {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
return weakStorage.containsObject(object as? AnyObject)
}
func generate() -> AnyGenerator<ObjectType> {
let enumerator = weakStorage.objectEnumerator()
return anyGenerator {
return enumerator.nextObject() as! ObjectType?
}
}
}
class-WeakSet:SequenceType{
变量计数:Int{
返回weakStorage.count
}
私有let weakStorage=NSHashTable.weakObjectsHashTable()
func addObject(对象:ObjectType){
guard对象是AnyObject,否则{fatalError(“object(\(object))应该是AnyObject的子类”)}
weakStorage.addObject(对象为?AnyObject)
}
func removeObject(对象:ObjectType){
guard对象是AnyObject,否则{fatalError(“object(\(object))应该是AnyObject的子类”)}
weakStorage.removeObject(对象为?AnyObject)
}
函数removeAllObjects(){
weakStorage.removeAllObjects()
}
func containsObject(对象:ObjectType)->Bool{
guard对象是AnyObject,否则{fatalError(“object(\(object))应该是AnyObject的子类”)}
返回weakStorage.containsObject(对象为?AnyObject)
}
func generate()->AnyGenerator{
让enumerator=weakStorage.objectEnumerator()
返回任意生成器{
是否将枚举数.nextObject()作为!ObjectType返回?
}
}
}
用法:
protocol MyDelegate : AnyObject {
func doWork()
}
class MyClass: AnyObject, MyDelegate {
fun doWork() {
// Do delegated work.
}
}
var delegates = WeakSet<MyDelegate>()
delegates.addObject(MyClass())
for delegate in delegates {
delegate.doWork()
}
协议MyDelegate:AnyObject{
func doWork()
}
类MyClass:AnyObject,MyDelegate{
趣味嫁妆{
//做委托的工作。
}
}
var delegates=WeakSet()
delegates.addObject(MyClass())
代表中的代表{
delegate.doWork()
}
这不是最好的解决方案,因为
WeakSet
可以用任何类型初始化,如果该类型不符合AnyObject
协议,则应用程序将崩溃。但是我现在看不到更好的解决方案。我在尝试实现弱容器时遇到了同样的问题。正如@plivesey在上面的评论中指出的那样,这似乎是Swift 2.2/Xcode 7.3中的一个错误,但它确实是
然而,一些基础协议并没有出现问题。例如,这将编译:
let container = WeakContainer<NSCacheDelegate>()
由于这可能会导致其他问题(某些类型无法在Objective-C中表示),因此有一种替代方法:
解决方案2
从容器中删除AnyObject
要求,并在内部将值强制转换为AnyObject
struct WeakContainer<T> {
private weak var _value:AnyObject?
var value: T? {
get {
return _value as? T
}
set {
_value = newValue as? AnyObject
}
}
}
protocol MyDelegate : AnyObject { }
var container = WeakContainer<MyDelegate>() // No compiler error
struct WeakContainer{
私有弱var_值:AnyObject?
var值:T{
得到{
将_值返回为?T
}
设置{
_value=newValue作为?AnyObject
}
}
}
协议MyDelegate:AnyObject{}
var container=WeakContainer()//没有编译器错误
警告:设置一个符合
T
,但不是AnyObject
的值失败。您的问题是WeakContainer
要求它的泛型T
是AnyObject
的子类型。协议
声明不是AnyObject
的子类型。您有四种选择:
WeakContainer
而是将其替换为实际实现MyDelegate
的内容。Swift-y方法是使用AnyX
模式:struct AnyMyDelegate:MyDelegate{…}
MyDelegate
定义为“类绑定”为protocol MyDelegate:class{…}
@obj
注释MyDelegate
,从本质上说,它是“类绑定的”WeakContainer
以不要求其泛型类型继承自AnyObject
。您将很难做到这一点,因为您需要一个声明为弱var
的属性,并且对于弱var
接受的类型存在限制,这些类型本质上是任何对象
下面是我在纯Swift中对WeakSet的实现(没有NSHashTable)
内部结构WeakBox{
内部私有(集合)弱var值:T?
私有变量指针:UnsafePointer
内部初始化(u值:T){
自我价值=价值
self.pointer=unsafeAddressOf(值)
}
}
扩展WeakBox:可散列{
var hashValue:Int{
返回self.pointer.hashValue
}
}
扩展WeakBox:equalable{}
func==(左:WeakBox,右:WeakBox)->Bool{
返回lhs.pointer==rhs.pointer
}
公共结构WeakSet:SequenceType{
私有变量框=集合()
公共变异函数插入(成员:元素){
guard let object=成员为?任何其他对象{
fatalError(“WeakSet的成员(\(成员))必须符合任何对象协议。”)
}
self.box.insert(WeakBox(对象))
}
public mutating func remove(成员:元素){
guard let object=成员为?任何其他对象{
fatalError(“WeakSet的成员(\(成员))必须符合任何对象协议。”)
}
self.box.remove(WeakBox(对象))
}
公共变异函数removeAll(){
self.box.rem
@objc
public protocol MyDelegate : AnyObject { }
let container = WeakContainer<MyDelegate>() // No compiler error
struct WeakContainer<T> {
private weak var _value:AnyObject?
var value: T? {
get {
return _value as? T
}
set {
_value = newValue as? AnyObject
}
}
}
protocol MyDelegate : AnyObject { }
var container = WeakContainer<MyDelegate>() // No compiler error
internal struct WeakBox<T: AnyObject> {
internal private(set) weak var value: T?
private var pointer: UnsafePointer<Void>
internal init(_ value: T) {
self.value = value
self.pointer = unsafeAddressOf(value)
}
}
extension WeakBox: Hashable {
var hashValue: Int {
return self.pointer.hashValue
}
}
extension WeakBox: Equatable {}
func ==<T>(lhs: WeakBox<T>, rhs: WeakBox<T>) -> Bool {
return lhs.pointer == rhs.pointer
}
public struct WeakSet<Element>: SequenceType {
private var boxes = Set<WeakBox<AnyObject>>()
public mutating func insert(member: Element) {
guard let object = member as? AnyObject else {
fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
}
self.boxes.insert(WeakBox(object))
}
public mutating func remove(member: Element) {
guard let object = member as? AnyObject else {
fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
}
self.boxes.remove(WeakBox(object))
}
public mutating func removeAll() {
self.boxes.removeAll()
}
public func contains(member: Element) -> Bool {
guard let object = member as? AnyObject else {
fatalError("WeakSet's member (\(member)) must conform to AnyObject protocol.")
}
return self.boxes.contains(WeakBox(object))
}
public func generate() -> AnyGenerator<Element> {
var generator = self.boxes.generate()
return AnyGenerator {
while(true) {
guard let box = generator.next() else {
return nil
}
guard let element = box.value else {
continue
}
return element as? Element
}
}
}
}
protocol Observerable {
associatedtype P : AnyObject
var delegates: NSHashTable<P> { get }
}
@objc protocol MyProtocol {
func someFunc()
}
class SomeClass : Observerable {
var delegates = NSHashTable<MyProtocol>.weakObjects()
}