【问题标题】:'var' parameters are deprecated and will be removed in Swift 3'var' 参数已弃用,将在 Swift 3 中删除
【发布时间】:2023-03-25 12:23:02
【问题描述】:

好吧,我只是将 Xcode 更新到 7.3,现在我收到了这个警告:

'var' 参数已弃用,将在 Swift 3 中删除

当我需要在这个函数中使用 var 时如何解决这个问题:

public func getQuestionList(var language: String) -> NSArray {
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}

【问题讨论】:

  • public func getQuestionList(inout language: String) -> NSArray怎么样
  • 不,这不是合适的替代品。 OP 可能不希望getQuestion 有任何副作用。
  • 我真的不知道他们为什么会考虑删除它。这是让 swift 变得很棒的功能之一!
  • 自己没用过,不懂大惊小怪。
  • @MikeTaverne(延迟回复)考虑以下函数:func foo(_ bar: int) { /*use bar*/ bar+=1; foo(bar); }。如果没有 var 参数,这是不可能的。您要么需要在函数中创建一个单独的 var 并复制该值,要么将参数标记为 inout。前者很慢,后者导致未定义的行为。许多算法都使用这样的递归。

标签: xcode swift xcode7 swift3


【解决方案1】:

关于从函数参数中删除 Var 的讨论已完整记录在 GitHub 上的此提交中:Remove Var Parameters

在该文档中,您会发现人们经常将var 参数与inout 参数混淆。 var 参数仅表示该参数在函数的上下文中是可变的,而使用 inout 参数时,返回点的参数值将被复制出函数并进入调用者的上下文。

解决这个问题的正确方法是从参数中去掉var,引入一个局部的var变量。在例程的顶部,将参数的值复制到该变量中。

【讨论】:

  • 我完全不明白这个变化,为什么必须写另一行来创建一个可变的本地变量比仅仅将参数定义为一个变量更好?
  • 对我来说这个改变很好,因为它解决了我应该实现局部变量但我没有实现的情况,因为我采取了简单的方法并接受了(旧)Swift 的建议输入参数a var
  • 我支持@RossBarbish。所以......这是因为懒惰的开发人员无法区分 inout 和 var 参数而被删除?噗……
  • 这似乎非常不必要......,他们应该保留这两个选项。
  • 可能 swift 在后台声明了一个局部变量,覆盖在参数之上。现在我们必须手动完成。性能没有变化,但我们失去了用简单概念帮助初学者的便利。
【解决方案2】:

您是否尝试分配给新的 var

public func getQuestionList(language: String) -> NSArray {
    var lang = language
    if self.data.count > 0 {
        if (lang.isEmpty) {
            lang = "NL"
        }
        return self.data.objectForKey("questionList" + lang) as! NSArray
    }

    return NSArray()
}

【讨论】:

  • 不是我认为的 OP 想要的
  • 我会以与@garana 相同的方式理解 OP 的问题。 OP 在他们的问题中没有使用 inout,他们只是对预先存在的变量 locally 进行变异。
  • 其实这是正确的解决方案。请参阅提出此更改的 Swift 进化问题:github.com/apple/swift-evolution/blob/master/proposals/…
  • @TimVermeulen 每个人都想使用渐进式语言。 Apple 可以通过多种方式开发他们的语言,而不是每个月更改语法。如您所知,大量在线文档和代码 sn-p 已因 Apple 而过期或过时。开发人员因此不得不来这个网站反复寻求许多愚蠢问题的帮助。如果 Apple 想要更多的开发者擅长语法,语法必须从一开始就稳固。
  • 使用 var language = language,如果你不想引入另一个变量名(这是 var 参数的主要优势首先是imo)
【解决方案3】:

只需在函数开头添加这一行:

var language = language

您的其余代码可以保持不变,如下所示:

public func getQuestionList(language: String) -> NSArray {
    var language = language
    if self.data.count > 0 {
        if (language.isEmpty) {
            language = "NL"
        }
        return self.data.objectForKey("questionList" + language) as! NSArray
    }

    return NSArray()
}

【讨论】:

  • 迄今为止最好的答案。只需要改变一行。
  • 但是看起来很不自然@James
  • 我觉得这是最好的答案,因为它保持相同的名称。类似于其他常用语言的做法。
  • @RiverSatya 为什么不直接使用参数呢?
  • 真是一个很棒的建议。我们将在 Swiftify 中以这种方式实现它:)
【解决方案4】:

很多人建议使用inout 参数,但这真的不是他们的设计目的。此外,它不允许使用let 常量调用函数,也不允许使用字符串文字。为什么不简单地将默认值添加到函数签名中?

public func getQuestionList(language language: String = "NL") -> NSArray {
    if data.count > 0 {
        return data.objectForKey("questionList" + language) as! NSArray
    } else {
        return NSArray()
    }
}

请确保不要使用空字符串调用getQuestionList,以防您需要默认语言,但只需省略参数即可:

let list = getQuestionList() // uses the default "NL" language

【讨论】:

  • 我也不明白为什么当 OP 一开始甚至没有使用 inout 解决方案时,每个人都跳入了 inout 解决方案......
  • 他们假设 var 和 inout 做了同样的事情。
【解决方案5】:
public func getQuestionList(language: inout String) -> NSArray {
if self.data.count > 0 {
    if (language.isEmpty) {
        language = "NL"
    }
    return self.data.objectForKey("questionList" + language) as! NSArray
}

return NSArray()

}

【解决方案6】:

我认为@Harris 和@garanda 的答案是最好的方法。

无论如何,在你的情况下,不需要 var,你可以这样做:

public func getQuestionList(language: String) -> NSArray {
    if self.data.count > 0 {
        return self.data.objectForKey("questionList" + (language.isEmpty ? "NL" : language)) as! NSArray
    }
    return NSArray()
}

【讨论】:

    【解决方案7】:

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html

    输入输出参数

    函数参数默认为常量。尝试从该函数的主体内更改函数参数的值会导致编译时错误。这意味着您不能错误地更改参数的值。如果您希望函数修改参数的值,并且希望这些更改在函数调用结束后仍然存在,请将该参数定义为 in-out 参数。

    您可以通过将 inout 关键字放在参数类型之前来编写一个 in-out 参数。 in-out 参数有一个值,该值被传入函数,被函数修改,并被传回函数外以替换原始值。有关输入输出参数的行为和相关编译器优化的详细讨论,请参阅输入输出参数。

    您只能将变量作为输入输出参数的参数传递。您不能将常量或文字值作为参数传递,因为无法修改常量和文字。当您将变量作为参数传递给 in-out 参数时,您可以在变量名称之前直接放置一个 & 符号,以表明它可以被函数修改。

    注意

    in-out参数不能有默认值,variadic参数不能标记为inout。

    这是一个名为 swapTwoInts(::) 的函数示例,它有两个输入输出整数参数,分别称为 a 和 b:

    func swapTwoInts(_ a: inout Int, _ b: inout Int) {
        let temporaryA = a
        a = b
        b = temporaryA
    }
    

    swapTwoInts(::) 函数只是将 b 的值交换为 a,并将 a 的值交换为 b。该函数通过将 a 的值存储在名为temporaryA 的临时常量中,将b 的值分配给a,然后将temporaryA 分配给b 来执行此交换。

    您可以使用两个 Int 类型的变量调用 swapTwoInts(::) 函数来交换它们的值。请注意,someInt 和 anotherInt 的名称在传递给 swapTwoInts(::) 函数时以 & 符号为前缀:

    var someInt = 3
    var anotherInt = 107
    swapTwoInts(&someInt, &anotherInt)
    print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
    // Prints "someInt is now 107, and anotherInt is now 3"
    

    上面的例子表明 someInt 和 anotherInt 的原始值被 swapTwoInts(::) 函数修改,即使它们最初是在函数外部定义的。

    注意

    输入输出参数与从函数返回值不同。上面的 swapTwoInts 示例没有定义返回类型或返回值,但它仍然修改了 someInt 和 anotherInt 的值。输入输出参数是函数在其函数体范围之外产生影响的另一种方式。

    【讨论】:

      【解决方案8】:

      这是另一个想法。我的用例是传递一个字符串数组以附加到它,为此数组必须可变地传入。我也不想在我的课堂上有状态。所以我创建了一个包含数组并传递它的类。根据您的用例,拥有一个只包含一个变量的类可能看起来很愚蠢。

      private class StringBuilder {
          var buffer: [String] = []
      
          func append(_ str: String) {
              buffer.append(str)
          }
      
          func toString() -> String {
              return buffer.joined()
          }
      }
      

      我只在数组上使用appendjoined 方法,因此只需对我的代码进行最少的其他更改即可轻松更改类型。

      一些示例用法:

      private func writeMap(map: LevelMap, url: URL) -> Bool {
          let buffer = StringBuilder()
      
          if !writeHeader(map: map, buffer: buffer) {
              return false
          }
          if !writeFloors(map: map, buffer: buffer) {
              return false
          }
      
          let content = buffer.toString()
          do {
              try content.write(to: url, atomically: true, encoding: .utf8)
              return true
          } catch {}
          return false
      }
      
      private func writeHeader(map: LevelMap, buffer: StringBuilder) -> Bool {
          buffer.append("something here ...\n")
          return true
      }
      

      【讨论】:

      • 我的回答是,如果您希望修改调用者看到的原始值。如果您只是希望能够在本地重新分配值但不影响调用者,那么上面的其他答案可以解决这个问题。
      猜你喜欢
      • 1970-01-01
      • 2016-07-10
      • 1970-01-01
      • 1970-01-01
      • 2016-07-24
      • 2016-07-09
      • 2016-11-30
      • 1970-01-01
      相关资源
      最近更新 更多