Ich fand nur eine andere Möglichkeit, Protokolle und Protokollerweiterungen in Swift verwenden, indem Sie das optionale Protokoll erweitern, um eine Funktion hinzuzufügen, so dass ich Standardwerte bereitstellen kann.Swift, wo Bedingung zu prüfen, ob eine Eigenschaft implementiert ist
Ich schrieb eine Blog-Post über diese hier: https://janthielemann.de/random-stuff/providing-default-values-optional-string-empty-optional-string-swift-3-1/
Der Kern der Post ist, dass ich eine saubere und einfache Art und Weise benötigen Standardwerte für optionalen String, die null oder leer sind zu liefern. Um dies zu tun, habe ich ein Emptyable Protokoll Ende das Fakultativprotokoll wie so erweitert:
protocol Emptyable {
var isEmpty: Bool { get }
}
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty<T: Emptyable>(_ defaultValue: T) -> T {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value as! T
}
}
}
extension String: Emptyable {}
Nun ist die Frage: Gibt es eine Möglichkeit kann ich des Emptyable Protokoll loszuwerden und haben stattdessen eine bedingte Prüfung, ob oder nicht eine Eigenschaft oder Funktion ist durch den generischen Typ implementiert, so dass ich oderWhenNilOrEmpty() für jeden Typ automatisch erhalten, der isEmpty
hat?
UPDATE
Wie Paulo vorgeschlagen, wird der T-generic eigentlich nicht braucht, und ich erstellt so einen Operator für noch schnelleren Zugriff und bequeme Nutzung (zumindest glaube ich. Fühlen Sie sich frei, mich zu korrigieren, mich bin immer glücklich, neue Dinge zu lernen und mich zu verbessern.
Ich nenne es die "nicht leere Nil Coalescing" -Operator (wer kann mit einem besseren Namen kommen? Ich fühle mich wie ich saugen Dinge benennen: /). Hoffentlich ein Tag, es hilft jemand:
protocol Emptyable {
var isEmpty: Bool { get }
}
infix operator ???: NilCoalescingPrecedence
extension Optional where Wrapped: Emptyable {
func orWhenNilOrEmpty(_ defaultValue: Wrapped) -> Wrapped {
switch(self) {
case .none:
return defaultValue
case .some(let value) where value.isEmpty:
return defaultValue
case .some(let value):
return value
}
}
static func ???(left: Wrapped?, right: Wrapped) -> Wrapped {
return left.orWhenNilOrEmpty(right)
}
}
extension String: Emptyable {}
extension Array: Emptyable {}
extension MyStruct: Emptyable {
let text: String
let number: Int
var isEmpty: Bool { return text.isEmpty && number == 0 }
init(text: String, number: Int) {
self.text = text
self.number = number
}
}
let mandatoryNotEmptyString = optionalOrEmptyString ??? "Default Value"
let mandatoryNotEmptyStruct = optionalOrEmptyStruct ??? MyStruct(name: "Hello World", number: 1)
Muss Ihre 'orWhenNilOrEmpty'-Funktion wirklich generisch sein? Kannst du 'T' nicht durch' Wrapped' ersetzen? Oder ist Ihre API so entworfen, dass sie willkürlich typisierte Standardwerte unterstützt (aber Ihre erzwungene Umwandlung in der letzten Zeile kann immer erfolgreich sein, wenn dies der Fall ist)? –
Sie haben Recht. T wird überhaupt nicht benötigt. Danke für den Tipp! – xxtesaxx