您可以像这样创建一个String扩展名:
extension String {
func someFunc -> Bool { ... }
}
但是如果你想将它应用于可选字符串呢?
var optionalString :String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */
答案 0 :(得分:139)
在Swift 3.1中,您还可以为可选值添加扩展名:
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
答案 1 :(得分:12)
你可以这样做:
protocol OptionalType { typealias A; var opt: A? { get } }
extension Optional: OptionalType { var opt: A? { return self } }
protocol StringType { var get: String { get } }
extension String: StringType { var get: String { return self } }
extension Optional where Wrapped: StringType {
func getOrElse(s: String) -> String {
return self.opt?.get ?? s
}
}
和
let optStr: String? = nil
optStr.getOrElse("hello world")
您无法限制Optional
或String
的原因是因为它们是struct
。通过为每个伪协议制定,现在我们可以根据自己的喜好进行约束。
我觉得swift已经放弃了很多东西,只是为了让初学者学习更容易,或者语言还不够成熟。
答案 2 :(得分:7)
Optional
上返回String
从Swift 3开始,您无法直接将扩展方法约束为可选的String
。您可以通过Daniel Shin的答案解释,获得与协议相同的结果。
但是,您可以在任意类型的Optional上创建扩展方法,并且我发现了一些具有String
返回值的有用方法。这些扩展有助于将值记录到控制台。当我想用空字符串替换可能的nil时,我在String
可选项上使用了asStringOrEmpty()。
extension Optional {
func asStringOrEmpty() -> String {
switch self {
case .some(let value):
return String(describing: value)
case _:
return ""
}
}
func asStringOrNilText() -> String {
switch self {
case .some(let value):
return String(describing: value)
case _:
return "(nil)"
}
}
}
使用示例:
var booleanValue: Bool?
var stringValue: String?
var intValue: Int?
print("booleanValue: \(booleanValue.asStringOrNilText())")
print("stringValue: \(stringValue.asStringOrNilText())")
print("intValue: \(intValue.asStringOrNilText())")
booleanValue = true
stringValue = "text!"
intValue = 41
print("booleanValue: \(booleanValue.asStringOrNilText())")
print("stringValue: \(stringValue.asStringOrNilText())")
print("intValue: \(intValue.asStringOrNilText())")
控制台输出:
booleanValue: (nil)
stringValue: (nil)
intValue: (nil)
booleanValue: true
stringValue: text!
intValue: 41
Optional
与nil指针不同这些扩展说明Optional
与nil指针不同。 Optional
是指定类型(enum
)的Wrapped
,表示它包含或不包含值。您可以在Optional
“容器”上编写扩展名,即使它可能不包含值。
摘自Swift Optional Declaration
enum Optional<Wrapped> : ExpressibleByNilLiteral {
/// The absence of a value.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
...
}
在代码中,缺少值通常使用nil
字面而不是显式.none
枚举情况编写。
答案 3 :(得分:3)
extension Optional where Wrapped == String {
var isNil: Bool {
return self == nil
}
上面的答案(由@Vlad Hatko编写)工作正常,但在快速4中有一些问题,所以我把它改成了。
答案 4 :(得分:3)
在Swift 4.1中,我遇到了 File E:\Code\PCPE\Install\pcpe301\Common\dac.exe
File E:\Code\PCPE\Install\pcpe301\Common\DataCollectionLauncher.exe
File E:\Code\PCPE\Install\pcpe301\Common\dataserv.exe
File E:\Code\PCPE\Install\pcpe301\Common\Display.exe
File E:\Code\PCPE\Install\pcpe301\Common\drvutil.dll
的构建错误。要解决此问题,您必须将Swift命名空间显式添加到类型中:
Optional is ambiguous for type lookup in this context
答案 5 :(得分:2)
更新:有关适用于Swift 2及更高版本的变通方法,请参阅Daniel Shin’s answer
可选字符串本身并不是一种类型,因此您无法在可选类型上创建扩展名。在Swift中,Optional
只是一个枚举(加上一些语法糖),可以是包含值的None
或Some
。要使用String方法,您需要打开optionalString
的内容。您可以轻松使用可选链接来实现此目的:
optionalString?.someFunc()
如果optionalString
不是nil
,则会在其上调用someFunc
。另一种(不太简洁)的方法是在尝试调用方法之前使用可选绑定来确定optionalString
是否有值:
if let string = optionalString {
string.someFunc() // `string` is now of type `String` (not `String?`)
}
在下面的评论示例中,您不需要嵌套多个if
语句,您可以检查可选字符串是否为单个if
中的空字符串:
if optionalString?.isEmpty == true {
doSomething()
}
这是有效的,因为表达式optionalString?.isEmpty
会返回一个可选的Bool(即true
,false
或nil
)。因此,只有doSomething()
不 optionalString
,和(如果该字符串为空),才会调用nil
。
另一种选择是:
if let string = optionalString where string.isEmpty {
doSomethingWithEmptyString(string)
}
答案 6 :(得分:2)
从Xcode 9.3开始,您可以使用@ Vladyslav的答案的轻微修改:
extension Optional where Wrapped == String {
var isEmpty: Bool {
return self?.isEmpty ?? true
}
}
答案 7 :(得分:1)
发现了一些技巧swift 3
class A{
var name:String!;
init(_ name:String?){
self.name = name;
}
}
extension Optional where Wrapped == String {
func compareText(_ other:String?)->Bool{
switch (self,other){
case let(a?,b?):
return a < b;
case (nil,_):
return true;
default:
return false;
}
}
}
let words:[A] = [A("a"),A(nil),A("b"),A("c"),A(nil)];
// let sorted = words.sorted{ 0.name.compareText($1.name) }
// trick
let sorted = words.sorted{ ($0.name as String?).compareText($1.name) }
print(sorted.map{$0.name});
答案 8 :(得分:1)
您可以创建一个可选的字符串扩展名。我执行了以下操作,以将可选字符串设置为空(如果为nil):
extension Optional where Wrapped == String {
mutating func setToEmptyIfNil() {
guard self != nil else {
self = ""
return
}
}
}