Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 不支持将AnyObject用作符合协议的具体类型_Swift_Reference_Hashtable_Protocols_Weak - Fatal编程技术网

Swift 不支持将AnyObject用作符合协议的具体类型

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

我正在使用Swift 2和WeakContainer来存储一组弱对象,很像
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()
    
    }