Sie können eine String-Erweiterung wie folgt erstellen:
extension String {
func someFunc -> Bool { ... }
}
aber was ist, wenn Sie möchten, dass es auf optionale Zeichenfolgen angewendet wird?
var optionalString :String? = ""
optionalString!.someFunc() /* String? does not have a member someFunc */
swift
swift-extensions
vol7ron
quelle
quelle
optionalString!.someFunc()
Antworten:
In Swift 3.1 können Sie optionalen Werten auch eine Erweiterung hinzufügen:
extension Optional where Wrapped == String { var isBlank: Bool { return self?.isBlank ?? true } }
quelle
if myOptionalString?.isBlank {
gibt den Wert des optionalen Typs Bool an? noch nicht ausgepackt.Type Wrapped constrained to non-protocol type String
Fehler bekommen . Hier ist eine wahrscheinlich relevante Diskussion über Reddit, die möglicherweise in Zukunft behoben wird.where Wrapped == T
?myOptionalString.isBlank
. Ohne das,?
da Sie es auf dem optionalen selbst anstatt auf dem aufrufenString
.Sie können es so machen:
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 } }
Und:
let optStr: String? = nil optStr.getOrElse("hello world")
Der Grund, den Sie nicht einschränken können
Optional
oderString
für diese Angelegenheit, ist, weil sie sindstruct
. Indem wir für jedes Pseudoprotokoll erstellen, können wir jetzt nach Belieben einschränken.Ich habe das Gefühl, dass Swift viele Dinge aufgegeben hat, um Anfängern das Lernen zu erleichtern , oder vielleicht ist die Sprache noch nicht genug gereift.
quelle
Erweiterungen dazu
Optional
geben a zurückString
Ab Swift 3 können Sie eine Erweiterungsmethode nicht direkt auf eine optionale beschränken
String
. Sie können das gleiche Ergebnis mit Protokollen erzielen, wie die Antwort von Daniel Shin erklärt.Sie können jedoch eine Erweiterungsmethode für eine Option eines beliebigen Typs erstellen, und ich habe einige nützliche Methoden gefunden, die einen
String
Rückgabewert haben. Diese Erweiterungen sind hilfreich, um Werte in der Konsole zu protokollieren. Ich habe asStringOrEmpty () für eineString
Option verwendet, wenn ich eine mögliche Null durch eine leere Zeichenfolge ersetzen möchte.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)" } } }
Beispiel Verwendung:
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())")
Konsolenausgabe:
booleanValue: (nil) stringValue: (nil) intValue: (nil) booleanValue: true stringValue: text! intValue: 41
Optional
anders als Null ZeigerDiese Erweiterungen veranschaulichen, dass an
Optional
sich von einem Nullzeiger unterscheidet. AnOptional
ist einenum
vom angegebenen Typ (Wrapped
), der angibt, dass es einen Wert enthält oder nicht. Sie können eine Erweiterung in denOptional
"Container" schreiben , obwohl dieser möglicherweise keinen Wert enthält.Auszug aus der optionalen Swift-Erklärung
enum Optional<Wrapped> : ExpressibleByNilLiteral { /// The absence of a value. case none /// The presence of a value, stored as `Wrapped`. case some(Wrapped) ... }
Im Code wird das Fehlen eines Werts normalerweise
nil
eher mit dem Literal als mit dem expliziten.none
Aufzählungsfall geschrieben.quelle
In Swift 4.1 wurde ein
Optional is ambiguous for type lookup in this context
Buildfehler angezeigt. Um dies zu beheben, müssen Sie den Swift-Namespace explizit zum Typ hinzufügen:extension Swift.Optional where Wrapped == String { var isBlank: Bool { return self?.isBlank ?? true } }
quelle
extension Optional where Wrapped == String { var isNil: Bool { return self == nil }
Die obige Antwort (geschrieben von @Vlad Hatko) funktioniert gut, aber in Swift 4 gibt es einige Probleme, deshalb habe ich sie geändert.
quelle
Seit Xcode 9.3 können Sie diese geringfügige Änderung der Antwort von @ Vladyslav verwenden:
extension Optional where Wrapped == String { var isEmpty: Bool { return self?.isEmpty ?? true } }
quelle
Update: Eine Problemumgehung, die mit Swift 2 und höher funktioniert, finden Sie in der Antwort von Daniel Shin
Ein optionaler String ist an und für sich kein Typ, daher können Sie keine Erweiterung für einen optionalen Typ erstellen. In Swift
Optional
ist an nur eine Aufzählung (plus ein bisschen syntaktischer Zucker), die entweder seinNone
kann oderSome
einen Wert umschließt. Um Ihre String-Methode zu verwenden, müssen Sie Ihre auspackenoptionalString
. Sie können einfach eine optionale Verkettung verwenden, um dies zu erreichen:Wenn
optionalString
nichtnil
,someFunc
wird darauf aufgerufen. Eine alternative (weniger prägnante) Möglichkeit besteht darin, mithilfe der optionalen Bindung festzustellen, oboptionalString
ein Wert vorhanden ist oder nicht , bevor Sie versuchen, die Methode aufzurufen:if let string = optionalString { string.someFunc() // `string` is now of type `String` (not `String?`) }
In Ihrem Beispiel aus den Kommentaren unten müssen Sie nicht mehrere
if
Anweisungen verschachteln . Sie können überprüfen, ob die optionale Zeichenfolge eine leere Zeichenfolge in einer einzelnen istif
:if optionalString?.isEmpty == true { doSomething() }
Dies funktioniert , weil der Ausdruck
optionalString?.isEmpty
eines optionalen Bool (dh zurückgibttrue
,false
odernil
). SodoSomething()
wird nur aufgerufen werden , wennoptionalString
ist nichtnil
, und wenn die Zeichenfolge leer ist .Eine andere Alternative wäre:
if let string = optionalString where string.isEmpty { doSomethingWithEmptyString(string) }
quelle
if let str=optString { if str.isEmpty { doSomething(); } }
ich lieber eineisBlank
Erweiterung einer optionalen Zeichenfolge seinif optStr.isBlank { … }
Boom. Für etwas so Neues wie Swift würde man denken, dass das Endziel darin besteht, lesbar zu sein, da lesbar wartbar ist.fand einen Trick schnell 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});
quelle
Sie können eine optionale Zeichenfolgenerweiterung erstellen. Ich habe Folgendes getan, um eine optionale Zeichenfolge auf leer zu setzen, wenn sie null war:
extension Optional where Wrapped == String { mutating func setToEmptyIfNil() { guard self != nil else { self = "" return } } }
quelle