我遇到了Swift 2到3转换工作的问题以及一些遗留语法给出:类型'[Any]'的值没有成员错误。
我希望有人能指出我一个好的解决方案。
Swift 2代码
Swift 2 code
func search() {
epsonPrinters = [Printer]()
starPrinters = [Printer]()
epson_startSearching()
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { [unowned self] in
let devices = SMPort.searchPrinter()
self.starPrinters = devices.map { portInfo -> Printer in
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
if let name = portInfo.modelName as? String {
p.emulation = name.containsString("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}
}
}
Swift 3 Code (我在有错误的区域上添加了评论)
func search() {
epsonPrinters = [Printer]()
starPrinters = [Printer]()
epson_startSearching()
DispatchQueue.global(qos: .background).async { [unowned self] in
let devices = SMPort.searchPrinter()
self.starPrinters = [devices.map { portInfo -> Printer in
// id, model and portName in below fails with messages like:
// Value of type '[Any]' has no member 'modelName'
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
// error on portInfo.modelName
// Value of type '[Any]' has no member 'modelName'
if let name = portInfo.modelName as? String {
p.emulation = name.containsString("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}!]
}
}
我知道我可以用以下内容替换'id:...'部分:
id: ((portInfo[0] as AnyObject).modelName) ?? "",
但这不正确,因为根据我们找到的打印机数量,PortInfo可以没有,1或倍数。
我很感激任何以优雅的方式重构这一点的建议,这是一个很好的Swift 3语法,可能会存在于Swift 4中。
我正在使用Xcode 8.3.2
答案 0 :(得分:0)
当您收到有关类型的错误时,您最好检查每个变量的类型。当您在devices
行中选择let devices = ...
时,Xcode的快速帮助会显示如下内容:
声明 let devices: [Any]?
首先,它是一个可选项,您需要在使用实际内容之前将其解包。
其次,devices
中的元素类型为Any
,您无法应用任何方法(包括属性访问器)。您需要在适当的位置将其强制转换为适当的类型。
要解决上述两件事,你可以这样写:
guard let devices = SMPort.searchPrinter() as? [PortInfo] else {
fatalError("This may never happen")
}
使用上面的警告声明,快速帮助将显示:
声明 let devices: [PortInfo]
非{可选,简单的PortInfo
数组,因此您可以使用PortInfo
的任何方法来处理此devices
的元素。
我会将你的Swift 2代码翻译成Swift 3,如下所示:
func search() {
epsonPrinters = []
starPrinters = []
epson_startSearching()
DispatchQueue.global(qos: .default).async {
guard let devices = SMPort.searchPrinter() as? [PortInfo] else {
fatalError("This may never happen")
}
self.starPrinters = devices.map { portInfo -> Printer in
let p = Printer(
id: portInfo.modelName,
make: "Star Micronics",
model: portInfo.modelName,
portName: portInfo.portName)
if let name = portInfo.modelName {
p.emulation = name.contains("TSP143") ? "StarGraphics" : "StarLine"
}
return p
}
}
}
您可能需要一些修复(我相信并不多)才能使用此代码,因为您没有显示所有相关内容,例如Printer
的定义。