类型“String.Index”不符合协议“IntegerLiteralConvertible”
Posted
技术标签:
【中文标题】类型“String.Index”不符合协议“IntegerLiteralConvertible”【英文标题】:Type 'String.Index' does not conform protocol 'IntegerLiteralConvertible' 【发布时间】:2014-07-22 06:46:56 【问题描述】:使用 Beta 3 一切正常,现在我收到一个奇怪的错误,我不知道如何修复它。尝试了所有类似问题的解决方案。
这是我的代码:
if !name.isEmpty
var splitted: [String] = name.componentsSeparatedByString(" ")
for curPart in splitted
if !curPart.isEmpty
acronym += curPart.substringToIndex(1) //Error
if (acronym as NSString).length > 2
acronym = acronym.substringToIndex(2) //Error
两条标记的行都给了我同样的错误:
有人可以帮助我吗?还是 Beta 4 被窃听了? 谢谢!
【问题讨论】:
【参考方案1】:在 beta 4 中,Swift 的 String.Index 处理再次发生了变化——当需要 String.Index
时,您现在无法提供 Int
。处理它的方法是使用advance
方法创建您需要的String.Index
:
if !name.isEmpty
var splitted: [String] = name.componentsSeparatedByString(" ")
for curPart in splitted
if !curPart.isEmpty
acronym += curPart.substringToIndex(advance(curPart.startIndex, 1))
if countElements(acronym) > 2
acronym = acronym.substringToIndex(advance(acronym.startIndex, 2))
这一切都是基于确保正确处理 Unicode 字符串 - 因为不同的 Unicode 字符可以有不同的大小,纯整数索引会隐藏字符串不是随机访问的事实。
【讨论】:
感谢您的解决方案!它编译并且似乎工作!谢谢。我也认为这会在 swift 1.0 之前改变 “这一切都是基于确保正确处理 Unicode 字符串 - 因为不同的 Unicode 字符可以有不同的大小,纯整数索引会隐藏字符串不是随机访问的事实。”。我认为通过使用恰好是一个 unicode 字符的Charcater
类型(而不是例如字节)来快速解决这个问题,而 swift String
s 可以被认为是这样的数组吗?访问字符串的第 n 个(unicode)字符的方式是什么?
不,每个Character
都是字符串中的单个可见 字符,可以由一个、两个或多个代码点组成。例如,????我认为是七。
如果您正在寻找一个确实使用 Int 来获取您可能想要的所有子字符串的扩展,请试试这个:***.com/questions/24044851/…
"访问字符串的第 n 个(unicode)字符的方式是什么?" -- Swift 的理念是,您应该在编写代码时感受到 Unicode 字符串处理的运行时成本。昂贵的操作写起来很痛苦。【参考方案2】:
Swift 的字符串组件和迭代的概念在 Beta 4 中发生了变化。从the guide,我们看到:
Swift 的 Character 类型的每个实例都代表一个扩展的字素簇。扩展字素簇是一个或多个 Unicode 标量的序列,这些标量(组合时)产生单个人类可读字符。
这有一些有趣的副作用:
let str1 = "abc"
let str2 = "\u20DDdef"
countElements(str1) // 3
countElements(str2) // 4
countElements(str1+str2) // 6 ≠ 3+4 !!!
那是因为 c
和 \u20DD
组合成 c⃝。另请注意,我们使用的是countElements
。为了算出字符串的长度,Swift 实际上必须遍历整个字符串并找出实际的字素划分在哪里,因此需要 O(n) 时间。
我们还可以看到不同编码的效果:
Array((str1+str2).utf8) // [97, 98, 99, 226, 131, 157, 100, 101, 102]
Array((str1+str2).utf16) // [97, 98, 99, 8413, 100, 101, 102]
另一个问题,正如您的错误所说,String
的IndexType
不再可以从整数文字转换:您不能通过指定偏移量对字符串执行随机访问。相反,您可以使用startIndex
和advance
在字符串中向前移动一段距离,例如str[str.startIndex]
或str[advance(str.startIndex, distance)]
。
或者您可以同时定义自己的辅助函数:
func at<C: Collection>(c: C, i: C.IndexType.DistanceType) -> C.GeneratorType.Element
return c[advance(c.startIndex, i)]
func take<C: protocol<Collection, Sliceable>>(c: C, n: C.IndexType.DistanceType) -> C.SliceType
return c[c.startIndex..<advance(c.startIndex, n)]
at(str1+str2, 3) // d
take(str1+str2, 2) // ab
显然,在未来的更新中可能(并且可能会)进行一些改进。您可能想file a bug 提出您的疑虑。从长远来看,正确支持字素集群可能是一个不错的决定,但同时它也会让字符串访问变得更加痛苦。
【讨论】:
好的,现在我知道幕后发生了什么:D 谢谢!【参考方案3】:对于 Swift 2.0
使用上面的例子:
curPart.substringToIndex(curPart.startIndex.advancedBy(1))
【讨论】:
以上是关于类型“String.Index”不符合协议“IntegerLiteralConvertible”的主要内容,如果未能解决你的问题,请参考以下文章
尝试符合可等式泛型 Set 时,类型“任何”不符合协议“等式”