Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.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 制作一本快捷字典,其中的关键是;“类型”是什么;?_Swift_Dictionary_Types - Fatal编程技术网

Swift 制作一本快捷字典,其中的关键是;“类型”是什么;?

Swift 制作一本快捷字典,其中的关键是;“类型”是什么;?,swift,dictionary,types,Swift,Dictionary,Types,我正试着做这种事 static var recycle: [Type: [CellThing]] = [] 但是——我不能:) 未声明的类型“type” 在这个例子中,CellThing是我的基类,所以A:CellThing,B:CellThing,C:CellThing等等。我的想法是将各种A、B、C存储在字典数组中 如何使一个“类型”(理想情况下,我想,限制在手机上)成为Swift字典的关键 我很感激我能(也许?)使用String(description:T.self),但那会让我失眠

我正试着做这种事

static var recycle: [Type: [CellThing]] = []
但是——我不能:)

未声明的类型“type”

在这个例子中,
CellThing
是我的基类,所以
A:CellThing
B:CellThing
C:CellThing
等等。我的想法是将各种A、B、C存储在字典数组中

如何使一个“类型”(理想情况下,我想,限制在手机上)成为Swift字典的关键

我很感激我能(也许?)使用
String(description:T.self)
,但那会让我失眠


这是一个用例,设想的代码看起来像这样

@discardableResult class func make(...)->Self {
  return makeHelper(...)
  }

private class func makeHelper<T: CellThing>(...)->T {
  let c = instantiateViewController(...) as! T
  return c
  }
@discardableResult类func make(…)->Self{
返回makeHelper(…)
}
私有类func makeHelper(…)->T{
设c=实例化eviewController(…)为!T
返回c
}
所以,就像

static var recycle: [Type: [CellThing]] = []

private class func makeHelper<T: CellThing>(...)->T {
  let c = instantiateViewController(...) as! T

  let t = type whatever of c (so, maybe "A" or "B")
  recycle[t].append( c )

  let k = recycle[t].count
  print wow, you have k of those already!

  return c
  }
static var recycle:[Type:[CellThing]]=[]
私有类func makeHelper(…)->T{
设c=实例化eviewController(…)为!T
设t=c的任何类型(因此,可能是“A”或“B”)
回收[t]。追加(c)
设k=recycle[t]。计数
打印哇,你已经有k个了!
返回c
}

不幸的是,目前元类型不可能符合协议(请参阅相关内容)–因此
CellThing.Type
目前不符合,也不能符合
哈希表。因此,这意味着它不能直接用作
词典

但是,您可以使用为元类型创建包装器,以便提供可散列的
实现。例如:

/// Hashable wrapper for a metatype value.
struct HashableType<T> : Hashable {

  static func == (lhs: HashableType, rhs: HashableType) -> Bool {
    return lhs.base == rhs.base
  }

  let base: T.Type

  init(_ base: T.Type) {
    self.base = base
  }

  func hash(into hasher: inout Hasher) {
    hasher.combine(ObjectIdentifier(base))
  }
  // Pre Swift 4.2:
  // var hashValue: Int { return ObjectIdentifier(base).hashValue }
}
然后可以这样使用:

class CellThing {}
class A : CellThing {}
class B : CellThing {}

var recycle: [HashableType<CellThing>: [CellThing]] = [:]

recycle[A.self] = [A(), A(), A()]
recycle[B.self] = [B(), B()]

print(recycle[A.self]!) // [A, A, A]
print(recycle[B.self]!) // [B, B]
将触发字典中存储的数组的O(N)副本

这是一个旨在通过解决的问题,已在Swift 5中作为非官方语言功能实现。如果您对使用非官方语言特性感到满意,并且该特性可能会在将来的版本中出现(不推荐用于生产代码),那么您可以将下标实现为:

extension Dictionary {
  subscript<T>(key: T.Type) -> Value? where Key == HashableType<T> {
    get { return self[HashableType(key)] }
    _modify {
      yield &self[HashableType(key)]
    }
  }
}
扩展字典{
下标(key:T.Type)->Value?其中key==HashableType{
获取{return self[HashableType(key)]}
_修改{
yield和self[哈希表类型(键)]
}
}
}
它解决了性能问题,允许数组值在字典中进行适当的变异

否则,一个简单的替代方法是不定义自定义下标,而是在类型上添加一个方便的computed属性,以便将其用作键:

class CellThing {
  // Convenience static computed property to get the wrapped metatype value.
  static var hashable: HashableType<CellThing> { return HashableType(self) }
}

class A : CellThing {}
class B : CellThing {}

var recycle: [HashableType<CellThing>: [CellThing]] = [:]

recycle[A.hashable] = [A(), A(), A()]
recycle[B.hashable] = [B(), B()]

print(recycle[A.hashable]!) // [A, A, A]
print(recycle[B.hashable]!) // [B, B]
类细胞{
//方便静态计算属性获取包装的元类型值。
静态变量hashable:HashableType{return HashableType(self)}
}
A类:细胞{}
B类:细胞{}
var recycle:[HashableType:[CellThing]=[:]
回收[A.hashable]=[A(),A(),A()]
回收[B.hashable]=[B(),B()]
打印(循环使用[A.hashable]!)/[A,A,A]
打印(循环使用[B.hashable]!)/[B,B]
希望有帮助。但它出现在Xcode 8.0中

您可以执行以下操作:

var info: [AnyHashable : Any]? = nil
如果扩展,则可以直接使用已定义的通用

extension Dictionary {
    // Key and Value are already defined by type dictionary, so it's available here
    func getSomething(key: Key) -> Value {
        return self[key]
    }
}

这是因为字典已经为自己的使用定义了泛型

您尝试过CellThing.selfAre类型可哈希吗?@matt-我很感激我可能必须使CellThing可哈希。这真的是问题所在吗(错误很奇怪)?是的。它正在寻找一个名为Type的类,但没有。我可以使用类作为非静态变量的键:var recycle:[UIView.self:[String]]=[]//没有编译器错误我也不知道
AnyHashable
会有什么帮助;它只能包装
可散列的
事物,但元类型不是
可散列的
。因此,回顾一下问题标题(1)那里的元类型实际上是:
CellThing.Type
(2)然而,实际上在Swift中,您不能使元类型可散列:就是这样。谁知道呢?@JoeBlow
CellThing.Type
是元类型类型,它是类型的类型(而
CellThing.self
是元类型值,它的一个实例)。当前无法将元类型直接与协议一致。请参阅。@matt元类型值只是指向给定类型的底层元类型信息的指针–
ObjectIdentifier
只是使用这些指针值(您可以看到它只是转换到
内置.RawPointer
)来给您一个
hashValue
实现(通过一个简单的身份比较实现平等)。我很抱歉打断了这么一个老话题,但我只是想知道,如果
CellThing
不是一个基类,而是一个协议,有没有办法让你的答案起作用?当我尝试时,Swift告诉我
不能为“[HashableType:[CellThing]”类型的值下标'使用类型为'A.type'的参数打印(回收[A.self]!)
@谢谢你的问题。我也有同样的问题。你找到解决方案了吗?不过,
type
不是可散列的
seven,谢谢-我不确定这是否解决了问题,因为我不再理解我写的问题:)我得考虑一下。问哈米什:)@Fattie——我读到的问题是,我怎样才能写出一些需要泛型并在字典上运行的东西。最简单的方法(至少对我来说)就是扩展字典。@sevenseven不完全-问题是如何使用元类型作为字典键,例如,如何编写类似于
[String.self:“hello”]
dict[String.self]=“hello”
的内容。话虽如此,使用字典扩展的想法让我了解了如何定义一个方便的下标,以便为您在
HashableType
中装箱元类型:)
var info: [AnyHashable : Any]? = nil
extension Dictionary {
    // Key and Value are already defined by type dictionary, so it's available here
    func getSomething(key: Key) -> Value {
        return self[key]
    }
}