簡體   English   中英

是否可以更改字符串類型別名的 Swift 字符串插值?

[英]Is it possible to change Swift String Interpolation for the String typealias?

我的應用程序中有很多 DTO,它們記錄了一些字段。 不應記錄該字段,因為數據有點敏感。 model 看起來像這樣:

typealias HiddenFieldType = String

struct DTO1 {
    var field1_1: String
    var fieldToHide: HiddenFieldType
    var field1_2: String
    var field1_3: String
}

struct DTO2 {
    var field2_1: String
    var field2_2: String
    var fieldToHide: HiddenFieldType
    var field2_3: String
}

輸出數據的代碼是這樣的(實際上它是真實應用程序中的os_log ):

func test() {
    let dto1 = DTO1(field1_1: "1_1", fieldToHide: "super-secret-1", field1_2: "1_2", field1_3: "1_3")
    let dto2 = DTO2(field2_1: "2_1", field2_2: "2_2", fieldToHide: "super-secret-2", field2_3: "2_3")

    print("Test1: dto1=\(dto1) dto2=\(dto2)")
}

方法#1

似乎可以使用以下代碼將該字段隱藏在 DTO1 中:

extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: DTO1) {
        appendInterpolation("field1_1: \(value.field1_1), fieldToHide: 🤷‍♀️, field1_2: \(value.field1_2), field1_3: \(value.field1_3)")
    }
}

但是,該解決方案既不可擴展也不可維護:

  • 應為每個 DTO 添加相同的擴展名
  • 每個字段都應該包含在appendInterpolation ——很多樣板文件
  • 如果將新字段添加到某些 DTO,我們可能會忘記更新appendInterpolation

方法#2

我試圖為HiddenFieldType添加插值(假設它是一種類型,就像DTO1 ...):

extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: HiddenFieldType) {
        appendInterpolation("🤷‍♀️")
    }
} 

但是這個解決方案根本不起作用:

  • 編譯器說“函數調用導致無限遞歸”
  • 它實際上會導致無限遞歸
  • appendInterpolation更改為appendLiteral時,沒有遞歸,但未隱藏“super-secret-1”

方法#3

我嘗試覆蓋DefaultStringInterpolation ,符合ExpressibleByStringLiteral / ExpressibleByStringInterpolation ,但它不起作用:編譯器說HiddenFieldTypeString ,並且Conformance of 'String' to protocol 'ExpressibleByStringLiteral' was already stated in the type's module 'Swift'

我能想到的唯一方法是將typealias HiddenFieldType = String更改為struct HiddenFieldType { let value: String } ,因此HiddenFieldType成為“真實”類型。


方法#4

然后這樣的代碼不再導致無限遞歸,但也不起作用(值未隱藏)

struct HiddenFieldType { 
    let value: String 
}

extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: HiddenFieldType) {
        appendInterpolation("🤷‍♀️")
    }
}

方法#5

這段代碼終於起作用了:

struct HiddenFieldType { 
    let value: String 
}

extension HiddenFieldType: CustomStringConvertible {
    var description: String {
        "🤷‍♀️"
    }
}

我無法想象更好,現在我會使用這種方法,但它也有一些輕微的可擴展性問題,因為我必須更新每個DTO的初始化點:從

let dto1 = DTO1(field1_1: "1_1", fieldToHide: "super-secret-1", field1_2: "1_2", field1_3: "1_3")

let dto1 = DTO1(field1_1: "1_1", fieldToHide: .init(value: "super-secret-1"), field1_2: "1_2", field1_3: "1_3")

我希望只在包含typealias HiddenFieldType = String的文件中添加一些擴展名,而不是更新整個代碼。


問題

  • 是否可以隱藏HiddenFieldType的值而不將其從typealias更改為struct並且不更新每個DTO
  • 有沒有比5更好的方法?

提前致謝

是否可以隱藏 HiddenFieldType 的值而不將其從 typealias 更改為 struct

我認為您正在嘗試使用錯誤的工具來完成這里的工作。 typealias只是一個名稱更改,聽起來您想要的東西與String的行為根本不同(即,一個在傳遞到os_log調用時被打印出來,而另一個則沒有)。 您將無法編寫處理String與其類型別名不同的typealias 編譯器不區分它們。

是否可以制作DTO的類而不是結構? (編輯:見下文,您可以將它們保留為結構並僅使用協議擴展)如果是這樣,您可以在超類上使用反射來完成此操作,而無需手動為每個不同的 DTO 指定description

struct HiddenFieldType {
    let value: String
}

open class DTO: CustomStringConvertible {
    public var description: String {
        Mirror(reflecting: self).children.compactMap { $0.value as? String }.joined(separator: "\n")
    }
}

final class DTO1: DTO {
    let field1_1: String
    let field1_2: String
    let fieldToHide: HiddenFieldType

    init(field1_1: String, field1_2: String, fieldToHide: HiddenFieldType) {
        self. field1_1 = field1_1
        self. field1_2 = field1_2
        self. fieldToHide = fieldToHide
    }
}

請注意,我在description中包括了所有字符串,但是,如果您想要記錄除StringHiddenFieldType以外的類型,您總是可以專門filterHiddenFieldType

就個人而言,我會猶豫是否要對任何關鍵代碼依賴反射,但其他人對此有更多的容忍度,因此這是一個判斷電話。

編輯:您不需要使用 inheritance 來完成此操作。 DTO應該是符合CustomStringConvertible的協議,而不是超類:

protocol DTO: CustomStringConvertible {}
extension DTO {
    public var description: String {
        Mirror(reflecting: self).children.compactMap { $0.value as? String }.joined(separator: "\n")
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM