Swift 如何添加可选的字符串扩展名?
您可以创建如下所示的字符串扩展名:Swift 如何添加可选的字符串扩展名?,swift,swift-extensions,Swift,Swift Extensions,您可以创建如下所示的字符串扩展名: extension String { func someFunc() -> Bool { return true } } 但如果您希望它应用于可选字符串,该怎么办 var optionalString: String? = "" optionalString!.someFunc() /* String? does not have a member someFunc */ 是否正在尝试添加扩展字符串?{产生错误: 必须在非专
extension String {
func someFunc() -> Bool { return true }
}
但如果您希望它应用于可选字符串,该怎么办
var optionalString: String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */
是否正在尝试添加扩展字符串?{
产生错误:
必须在非专用泛型类型“Optional”上声明受约束的扩展,并使用“where”子句指定的约束
更新:有关适用于Swift 2及以上版本的解决方案,请参阅
可选字符串本身不是类型,因此无法在可选类型上创建扩展。在Swift中,
optional
只是一个枚举(加上一点语法糖)可以是包装值的None
,也可以是包装值的Some
。要使用字符串方法,您需要打开可选字符串
。您可以轻松使用可选链接来实现此目的:
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)
}
您可以这样做:
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
}
}
以及:
您不能约束可选
或字符串
,因为它们是struct
。通过为每一个都创建伪协议,现在我们可以随意约束
我觉得斯威夫特放弃了很多东西,只是为了让初学者更容易学习,或者可能语言还不够成熟。对可选的扩展返回字符串
从Swift 3开始,您不能直接将扩展方法约束到可选的字符串
。如Daniel Shin的回答所述,您可以通过协议获得相同的结果
但是,您可以在任何类型的可选项上创建扩展方法,我发现一些有用的方法具有字符串
返回值。这些扩展有助于将值记录到控制台。当我想用空字符串替换可能的nil时,我在字符串
可选项上使用了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
控制台输出:
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
可选
不同于零指针
这些扩展说明可选的
不同于零指针。可选的
是指定类型(包装的
)的枚举
,表示它包含或不包含值。您可以在可选的
容器上编写扩展即使它可能不包含值
Swift可选声明摘录
enum Optional<Wrapped> : ExpressibleByNilLiteral {
/// The absence of a value.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
...
}
enum可选:expressiblebynellateral{
///缺少一个值。
无案例
///值的存在,存储为“Wrapped”。
包装箱(已包装)
...
}
在代码中,缺少值通常使用nil
文本而不是显式.none
枚举情况写入。在Swift 3.1中,您还可以为可选值添加扩展名:
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
找到了一些技巧,斯威夫特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});
A类{
变量名称:String!;
init(uu名称:String?){
self.name=名称;
}
}
扩展名可选,其中Wrapped==String{
func compareText(uu其他:字符串?)->Bool{
开关(自身、其他){
案例(a?、b?):
返回a
以上由@Vlad Hatko编写的答案很好,但在Swift 4中存在一些问题,因此我将其改为此。自Xcode 9.3以来,您可以使用@Vladyslav的答案的这一细微修改:
extension Optional where Wrapped == String {
var isEmpty: Bool {
return self?.isEmpty ?? true
}
}
在Swift 4.1中,我遇到了一个可选的不明确的生成错误,用于此上下文中的类型查找生成错误。要修复此错误,必须将Swift命名空间显式添加到类型:
extension Swift.可选,其中Wrapped==String{
var为空:Bool{
返回自我?为空?为真
}
}
您可以创建可选的字符串扩展名。如果可选字符串为nil,我执行了以下操作将其设置为空:
extension Optional where Wrapped == String {
mutating func setToEmptyIfNil() {
guard self != nil else {
self = ""
return
}
}
}
您需要始终将其展开才能应用扩展。所以我将其展开,但可能是我做错了?optionalString!.someFunc()
如果您确定optional不会返回nil,那没关系,否则您需要使用If-letIt有时会为nil,这就是为什么使用optional。我仍在调试,我怀疑我的游乐场是不同步的。我可能会马上结束这个问题。@LeonardoSavioDabus是的,这就是我希望在扩展中添加并使用扩展t的原因o solve。我不喜欢嵌套的IF语句。我猜Swift的未来版本最终会在这方面有所改进。我试图创建一个扩展以避免可选绑定。似乎不会possible@vol7ron请问为什么?可选的链接/绑定不方便吗?考虑一个你想检查的可选字符串据我所知,您必须使用嵌套的if'sif let str=optString{if str.isEmpty{doSomething();}}
我宁愿这是一个isBlank
扩展名