如何添加可选的字符串扩展?
How to add an optional string extension?
您可以像这样创建一个字符串扩展:
extension String {
func someFunc() -> Bool { return true }
}
但是如果您希望它应用于可选字符串怎么办?
var optionalString: String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */
尝试添加 extension String? {
产生错误:
Constrained extension must be declared on the unspecialized generic type 'Optional' with constraints specified by a 'where' clause
更新: 有关适用于 Swift 2 及更高版本的解决方法,请参阅
可选字符串本身不是类型,因此您不能在可选类型上创建扩展。在 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
:[=32= 中检查可选字符串是否为空字符串]
if optionalString?.isEmpty == true {
doSomething()
}
这是有效的,因为表达式 optionalString?.isEmpty
returns 是一个可选的布尔值(即 true
、false
或 nil
)。因此 doSomething()
仅在 optionalString
为 not nil
、and 且该字符串为空时才会被调用.
另一种选择是:
if let string = optionalString where string.isEmpty {
doSomethingWithEmptyString(string)
}
你可以这样做:
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 已经放弃了很多东西只是为了让初学者更容易学习 或者这门语言还不够成熟。
Optional
return String
的扩展
从 Swift 3 开始,您不能直接将扩展方法限制为可选 String
。正如 Daniel Shin 的回答所解释的那样,您可以使用协议获得相同的结果。
但是,您可以在任何类型的 Optional 上创建扩展方法,我发现了一些具有 String
return 值的有用方法。这些扩展有助于将值记录到控制台。当我想用空字符串替换可能的 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
是指定类型 (Wrapped
) 的 enum
,表示它包含或不包含值。您可以在 Optional
"container" 上编写扩展名,即使它可能不包含值。
摘自Swift 可选声明
enum Optional<Wrapped> : ExpressibleByNilLiteral {
/// The absence of a value.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
...
}
在代码中,缺少值通常使用 nil
文字而不是显式 .none
枚举。
在 Swift 3.1 中,您还可以为可选值添加扩展:
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
发现了一些技巧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(.name) }
// trick
let sorted = words.sorted{ ([=10=].name as String?).compareText(.name) }
print(sorted.map{[=10=].name});
extension Optional where Wrapped == String {
var isNil: Bool {
return self == nil
}
}
@Vlad Hatko 写的上述答案工作正常,但在 Swift 4 中存在一些问题所以我将其更改为此。
从 Xcode 9.3 开始,您可以使用对@Vladyslav 的回答的这个细微修改:
extension Optional where Wrapped == String {
var isEmpty: Bool {
return self?.isEmpty ?? true
}
}
在 Swift 4.1 中,我遇到了 Optional is ambiguous for type lookup in this context
构建错误。要修复,您必须明确地将 Swift 命名空间添加到类型:
extension Swift.Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
您可以创建一个可选的字符串扩展。如果可选字符串为 nil,我执行以下操作将其设置为空:
extension Optional where Wrapped == String {
mutating func setToEmptyIfNil() {
guard self != nil else {
self = ""
return
}
}
}
您可以像这样创建一个字符串扩展:
extension String {
func someFunc() -> Bool { return true }
}
但是如果您希望它应用于可选字符串怎么办?
var optionalString: String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */
尝试添加 extension String? {
产生错误:
Constrained extension must be declared on the unspecialized generic type 'Optional' with constraints specified by a 'where' clause
更新: 有关适用于 Swift 2 及更高版本的解决方法,请参阅
可选字符串本身不是类型,因此您不能在可选类型上创建扩展。在 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
:[=32= 中检查可选字符串是否为空字符串]
if optionalString?.isEmpty == true {
doSomething()
}
这是有效的,因为表达式 optionalString?.isEmpty
returns 是一个可选的布尔值(即 true
、false
或 nil
)。因此 doSomething()
仅在 optionalString
为 not nil
、and 且该字符串为空时才会被调用.
另一种选择是:
if let string = optionalString where string.isEmpty {
doSomethingWithEmptyString(string)
}
你可以这样做:
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 已经放弃了很多东西只是为了让初学者更容易学习 或者这门语言还不够成熟。
Optional
return String
的扩展
从 Swift 3 开始,您不能直接将扩展方法限制为可选 String
。正如 Daniel Shin 的回答所解释的那样,您可以使用协议获得相同的结果。
但是,您可以在任何类型的 Optional 上创建扩展方法,我发现了一些具有 String
return 值的有用方法。这些扩展有助于将值记录到控制台。当我想用空字符串替换可能的 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
是指定类型 (Wrapped
) 的 enum
,表示它包含或不包含值。您可以在 Optional
"container" 上编写扩展名,即使它可能不包含值。
摘自Swift 可选声明
enum Optional<Wrapped> : ExpressibleByNilLiteral {
/// The absence of a value.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
...
}
在代码中,缺少值通常使用 nil
文字而不是显式 .none
枚举。
在 Swift 3.1 中,您还可以为可选值添加扩展:
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
发现了一些技巧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(.name) }
// trick
let sorted = words.sorted{ ([=10=].name as String?).compareText(.name) }
print(sorted.map{[=10=].name});
extension Optional where Wrapped == String {
var isNil: Bool {
return self == nil
}
}
@Vlad Hatko 写的上述答案工作正常,但在 Swift 4 中存在一些问题所以我将其更改为此。
从 Xcode 9.3 开始,您可以使用对@Vladyslav 的回答的这个细微修改:
extension Optional where Wrapped == String {
var isEmpty: Bool {
return self?.isEmpty ?? true
}
}
在 Swift 4.1 中,我遇到了 Optional is ambiguous for type lookup in this context
构建错误。要修复,您必须明确地将 Swift 命名空间添加到类型:
extension Swift.Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
您可以创建一个可选的字符串扩展。如果可选字符串为 nil,我执行以下操作将其设置为空:
extension Optional where Wrapped == String {
mutating func setToEmptyIfNil() {
guard self != nil else {
self = ""
return
}
}
}