我正在尝试将Objective-C项目转换为swift,但我无法找到如何将NSFastEnumeration用于符合NSFastEnumeration的类的对象。
以下是ObjC中的代码:
// get the decode results
id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// just grab the first barcode
break;
到目前为止,我试图找到如何做到这一点,但这似乎不起作用,这里是快速的代码:
var results: ZBarSymbolSet = infoDictionary?.objectForKey(ZBarReaderControllerResults) as ZBarSymbolSet
var symbol : ZBarSymbol? = nil;
for symbol in results
{ //just grab first barcode
break;
}
错误来自条件 - &#34; ZBarSymbolSet&#34;没有名为&#34; Generator&#34;
的成员我做错了什么?
这是屏幕截图
答案 0 :(得分:22)
在快速浏览swift框架文件一段时间后,我终于找到了一个名为NSFastGenerator
的好类。 NSSet
和朋友似乎使用相同的Generator
。
对于ZBarSymbolSet
,以下是将其扩展为支持for-in
循环的方式:
extension ZBarSymbolSet: SequenceType {
public func generate() -> NSFastGenerator {
return NSFastGenerator(self)
}
}
更新:看起来Swift 2.0的协议扩展为我们解决了这个问题!
答案 1 :(得分:3)
您定义的类ZBarSymbolSet
需要实现Swift SequenceType
接口才能在for <identifier> in <sequence>
语法中使用。 SequenceType
接口是
protocol SequenceType : _Sequence_Type {
typealias Generator : GeneratorType
func generate() -> Generator
}
因此您会在错误消息中看到提及Generator
的内容。
同样在语法中:
for <identifier> in <sequence> {
<statements>
}
<identifer>
仅适用于<statements>
。因此,symbol
中if
的第二次使用将超出范围且出错。一个恰当的习语是:
var symbolFound : ZBarSymbol?
for symbol in result {
symbolFound = symbol
break
}
if symbolFound ...
如果是课程,但时间ZBarSymbolSet
实施SequenceType
,那么它也会CollectionType
与subscript
实施,因此整个&#39;找到第一个元素&#39}。代码为var symbol = result[0]
答案 2 :(得分:3)
这是John Estropia对Swift 3的回答:
extension ZBarSymbolSet: Sequence {
public typealias Iterator = NSFastEnumerationIterator
public func makeIterator() -> NSFastEnumerationIterator {
return NSFastEnumerationIterator(self)
}
}
然后你的for-in循环看起来像这样:
for element in results {
let symbol = element as! ZBarSymbol
// ...
}
通过采用IteratorProtocol
可以改进此答案,因此您可以将元素关联类型指定为ZBarSymbol
。我还没弄明白怎么做。
答案 3 :(得分:2)
Step1:
extension ZBarSymbolSet: SequenceType {
public func generate() -> NSFastGenerator {
return NSFastGenerator(self)
}
}
Step2:
var results: NSFastEnumeration = info.objectForKey(ZBarReaderControllerResults) as NSFastEnumeration
var symbolFound : ZBarSymbol?
for symbol in results as ZBarSymbolSet {
symbolFound = symbol as? ZBarSymbol
break
}
resultString = NSString(string: symbolFound!.data)
答案 4 :(得分:1)
另外,如果您知道ZBarSymbolSet
中的所有对象都是ZBarSymbol
个对象(因为ObjC并未强制所有对象都是ZBarSymbol
个对象),您可以执行以下操作:
extension ZBarSymbolSet {
public struct ZBarSymbolSetIterator {
public typealias Element = ZBarSymbol
private let enumerator: NSFastEnumerationIterator
init(_ symbols: ZBarSymbolSet) {
self.enumerator = NSFastEnumerationIterator(symbols)
}
public mutating func next() -> ZBarSymbol {
if let object = self.enumerator.next() {
return object as? ZBarSymbol
}
else { return nil }
}
}
public func makeIterator() -> ZBarSymbolSetIterator {
return ZBarSymbolSetIterator(self)
}
}
现在你的for循环看起来像这样:
for element in results {
// element is a ZBarSymbol
}
答案 5 :(得分:0)
这是一种无需编写扩展名的方法
var iterator = NSFastEnumerationIterator(collection)
while let element = iterator.next() {
// use element
}