如何在Swift 3.0中连接多个可选字符串?

4
我尝试在Swift 3中连接多个字符串:
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = a! + b! + c!

在编译时,我遇到了以下错误:
error: cannot convert value of type 'String' to specified type 'String?'
var d:String? = a! + b! + c!
                ~~~~~~~~^~~~

这在Swift 2中曾经可行。我不确定为什么现在不再可行。

5个回答

8

OP提交的错误报告:

该问题已得到解决(修复已提交至主分支,于2017年1月3日),因此在即将推出的Swift 3.1中不再是问题。


这似乎是一个bug(在Swift 2.2中不存在,仅存在于3.0中),与以下情况有关:

  • 在表达式中使用至少3个术语的强制解包操作符()(使用至少2个基本运算符进行测试,例如+-)。
  • 由于上述原因,Swift在表达式的类型推断中搞砸了(具体来说,是针对表达式中的x!项本身)。

对于下面的所有示例,请让:

let a: String? = "a"
let b: String? = "b"
let c: String? = "c"

问题描述:

// example 1
a! + b! + c!
    /* error: ambiguous reference to member '+' */

// example 2
var d: String =  a! + b! + c!
    /* error: ambiguous reference to member '+' */

// example 3
var d: String? =  a! + b! + c!
    /* error: cannot convert value of type 'String' 
       to specified type 'String?' */

// example 4
var d: String?
d =  a! + b! + c!
    /* error: cannot assign value of type 'String' 
       to specified type 'String?' */

// example 5 (not just for type String and '+' operator)
let a: Int? = 1
let b: Int? = 2
let c: Int? = 3
var d: Int? = a! + b! + c!
    /* error: cannot convert value of type 'Int' 
       to specified type 'Int?' */
var e: Int? = a! - b! - c! // same error

未发现错误:

/* example 1 */
var d: String? = a! + b!

/* example 2 */
let aa = a!
let bb = b!
let cc = c!
var d: String? = aa + bb + cc
var e: String = aa + bb + cc

/* example 3 */
var d: String? = String(a!) + String(b!) + String(c!)

然而,由于这是Swift 3.0-dev版本,我不确定这是否真的是一个"bug",以及关于在尚未生产的代码版本中报告"bug"的政策是什么,但是为了安全起见,你可能应该提交radar报告。

至于如何解决此问题的回答:

  • use e.g. intermediate variables as in Bug not present: Example 2 above,
  • or explicitly tell Swift all terms in the 3-term expression are strings, as in Bug not present: Example 3 above,
  • or, better yet, use safe unwrapping of your optional, e.g. using optional binding:

    var d: String? = nil
    if let a = a, b = b, c = c {
        d = a + b + c
    } /* if any of a, b or c are 'nil', d will remain as 'nil';
         otherwise, the concenation of their unwrapped values   */
    

2
感谢您的回答,我已经在此处提交了一个Bug报告:https://bugs.swift.org/browse/SR-1122 - DMSilva

2

Swift 3

let q: String? = "Hello"
let w: String? = "World"
let r: String? = "!"
var array = [q, w, r]

print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// HelloWorld!


let q: String? = "Hello"
let w: String? = nil
let r: String? = "!"
var array = [q, w, r]

print(array.flatMap { $0 }.reduce("", {$0 + $1}))
// Hello!

1
func getSingleValue(_ value: String?..., seperator: String = " ") -> String? {

    return value.reduce("") {
        ($0) + seperator + ($1 ?? "")
        }.trimmingCharacters(in: CharacterSet(charactersIn: seperator) )
}

0
var a:String? = "a"
var b:String? = "b"
var c:String? = "c"
var d:String? = ""

let arr = [a,b,c]
arr.compactMap { $0 }.joined(separator: " ")

compactMap 可用于从扁平化数组中过滤掉 nil 值


1
虽然你的代码可能有效,但如果你能在答案中添加一些解释就更好了。 - rincewind

0
let val: String? = "nil"

val.flatMap({(str: String) -> String? in
    return str + "value"
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接