【问题标题】:Why this struct shadows the type String?为什么这个结构会隐藏 String 类型?
【发布时间】:2020-05-15 04:01:49
【问题描述】:

我正在尝试理解属性包装器。

我有另一个关于 SO 的问题,我试图创建一个像这样的属性包装器:

extension String {

  func findReplace(_ target: String, withString: String) -> String
  {
    return self.replacingOccurrences(of: target,
                                     with: withString,
                                     options: NSString.CompareOptions.literal,
                                     range: nil)
  }
}


  @propertyWrapper
  struct AdjustTextWithAppName<String> {
    private var value: String?


    init(wrappedValue: String?) {
      self.value = wrappedValue
    }

    var wrappedValue: String? {
      get { value }
      set {
        if let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleName"] as? String {
          let replaced = value.findReplace("$$$", withString: localizedAppName)

        }
        value = nil
      }
    }

  }

这不起作用,因为value.findReplace 行显示错误

字符串类型的值?没有名字 findReplace

一旦有人建议我将结构行更改为

struct AdjustTextWithAppName {

整个事情开始起作用了。

为什么?我不明白为什么结构上的 &lt;String&gt; 术语隐藏了我创建的 String 类型的扩展。

这是为什么呢?

【问题讨论】:

  • 但这是你今天早些时候问过的question的重复,为什么要问同样的事情两次?
  • 不是重复的。在第一个问题中,我试图了解出了什么问题。在这个问题中,我试图理解为什么。

标签: ios swift swift4 swift5


【解决方案1】:

&lt;String&gt; 替换为通用泛型类型&lt;T&gt;,您会立即看到问题

 @propertyWrapper
  struct AdjustTextWithAppName<T> {
    private var value: T?


    init(wrappedValue: T?) {
      self.value = wrappedValue
    }

    var wrappedValue: T? {
      get { value }
      set {
        if let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleName"] as? String {
            let replaced = value.findReplace("$$$", withString: localizedAppName) // Value of type 'T' has no member 'findReplace'

        }
        value = nil
      }
    }
  }

现在错误更容易理解了

类型“T”的值没有成员“findReplace”

【讨论】:

  • 这就是为什么你应该在你的方法中使用单个字母作为泛型类型
【解决方案2】:

我不明白为什么结构上的 &lt;String&gt; 术语隐藏了我创建的 String 类型的扩展。

为什么不呢?您明确要求AdjustTextWithAppName 有一个名为String 的泛型类型参数。编译器准确地为您提供了您所要求的内容。

【讨论】:

  • 我认为 struct 创建了结构,而不是类型。在我看来,AdjustTextWithAppName 将创建一个名为 AdjustTextWithAppName 的 String 类型的结构,因为 Array 将创建一个字符串数组。为什么相同的语法会产生两种不同的东西,我无法理解。
  • @SpaceDog “为什么相同的语法会产生两种不同的东西,我无法理解。”你通过跟踪、错误、沮丧的 StackOverflow 帖子、不情愿地接受答案、冲洗和重复的过程来强行学习 Swift。你应该花一些时间学习基础知识,因为你只会永远陷入这种沮丧的循环中。
  • 关键字struct 确实声明了结构。结构是类型,所以它显然也声明了类型。 In my mind AdjustTextWithAppName&lt;String&gt; would create a structure called AdjustTextWithAppName of type StringWelp,这完全是错误的。类型标识符后面的&lt; &gt; 是泛型类型参数的列表。 “字符串类型”将表示为子类型关系,拼写为subtype: supertype,这对于String 是不可能的,因为String 是一个结构,而结构不能被子类型化。
  • as Array&lt;String&gt; will create an array of strings 根据您在此之前的陈述的逻辑,您会得出结论,这应该“创建一个名为ArrayString 类型的结构”,这没有意义。真正发生的事情是Array 是一个结构,具有一个泛型类型参数(称为Element),声明为struct Array&lt;Element&gt;see for yourself)。
  • 我没有进行反复试验。属性包装器是我无法包装(故意双关语)的东西。这个概念很简单,但语法很疯狂。 Lunacy 在 Swift 中赢得了战争,语法每次都变得更加荒谬。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 2019-09-16
相关资源
最近更新 更多