可选的可变力展开,我还没有看到解决方案

时间:2017-04-28 14:32:18

标签: swift optional

强行展开是邪恶的,所以我正在使用警卫,或者尽可能让我尽力,但有时这真的让我头疼。

基于1的列表索引变量到函数中基于0的数组

//index is an integer from a 1 based list, so it can be 1, 2, 3,... (index is coming from an external API)
func someFunction (index : Int?) {
guard let newIndex = index - 1 else {
            throw Abort.custom(status: .badRequest,
                               message: "blah blah")
        }
 let result = myArray[newIndex]
 ....
}

编辑器标记错误“

  

可选类型Int的值未解包,您的意思是使用!要么   ?“

行中的@ index: guard让newIndex = index - 1 else {

添加!索引结果导致另一个错误:

  

“条件绑定的初始化程序必须具有可选类型,而不是int”

所以我目前使用的解决方案是:

 guard var newIndex = index else {
            throw Abort.custom(status: .badRequest,
                               message: "blah blah")
        }

     newIndex -= 1
     let result = myArray[newIndex]
     ....

它有效,但我认为它有点难看......

4 个答案:

答案 0 :(得分:2)

您可以使用方法调用而不是运算符进行减法:

func someFunction (index : Int?) {
    guard var newIndex = index?.advanced(by: -1) else {
        throw Abort.custom(status: .badRequest,
                           message: "blah blah")
    }

    let result = myArray[newIndex]
    ....
}

一般不会回答这个问题,但是在你的具体情况下。

答案 1 :(得分:0)

guard let newIndex = index - 1

guard let仅用于展开Optional。在这里,你混淆了展开的动作,以及将1移除到整数的动作。

你是正确的,分两步,而不是一步。它根本不丑陋! 例如:

func someFunction (index : Int?) throws {
    guard let unwrappedIndex = index else {
        //The given index is nil, abort.
        throw Abort.custom(status: .badRequest,
                          message: "Index is nil")
    }

    //Now everything is fine, unwrappedIndex is not an Optional anymore.
    guard unwrappedIndex - 1 > 0 else {
        throw Abort.custom(status: .badRequest,
                          message: "Wrong index")
    }

    //Happy scenario... Do you things...
    let result = myArray[newIndex]
    ...
}

更好的是,你没有被迫声明另一个变量名来解开它!做一个像这样的警卫:

guard let index = index else { throw Error }

答案 2 :(得分:0)

最安全的方法是使用可选绑定来解包索引,然后检查(从1开始)索引是否在数组中项目数的范围内(〜=是模式匹配运算符)

guard var newIndex = index, // unwraps the optional
    1...myArray.count ~= newIndex // is index in the range 1 ... number of items in the array
        else {
            throw Abort.custom(status: .badRequest,
                           message: "blah blah")
            return }
newIndex -= 1
let result = myArray[newIndex]

有效索引范围是

0-based : 0..<myArray.count
1-based : 1...myArray.count

如果检查成功,则减少索引并获取该项目。

如果以后不使用newIndex,或者更简单:

guard let newIndex = index, // unwraps the optional
    1...myArray.count ~= newIndex // is index in the range 1 ... number of items in the array
        else {
            throw Abort.custom(status: .badRequest,
                           message: "blah blah")
            return }
let result = myArray[newIndex - 1]

答案 3 :(得分:0)

对于您的特定情况,您可以执行以下操作:

func someFunction (index : Int?) throws {
    guard let newIndex = Optional( (index ?? 0) - 1 ), newIndex >= 0 else {
        throw Abort.custom(status: .badRequest, message: "blah blah")
    }

    let result = myArray[newIndex]
    ....
}
  • (index ?? 0),您告诉如果index不是nil,那么index = index!,否则为0

    < / LI>
  • 因此,您拥有未包装的值,并从中减去1。但是您必须使用Optional类型进行可选绑定。因此,请Optional( (index ?? 0) - 1 )

  • 选择它
  • 到目前为止,您已获得newIndex并通过提供newIndex >= 0检查确认您不会对负指数值执行任何操作。

因此,您可以将基于 1的列表索引变量转换为函数中基于0的数组