Swift: Используете try? поймать индекс вне допустимого диапазона - PullRequest
0 голосов
/ 06 мая 2020

, поэтому я делаю игру, и есть сетка, и вы можете разместить только в том случае, если любой из соседних блоков является исходным блоком, ну, если вы пытаетесь разместить блок в верхней сетке, над ним нет блока, поэтому индекс будет выдана ошибка вне допустимого диапазона. Я пытаюсь поймать это, но xcode, похоже, считает, что ошибка невозможна. Я делаю это неправильно? Думаю, я мог бы go к каждому случаю и добавить уловку, но я чувствую, что это должно сработать.

myCode

скопируйте дружественный текст, если хотите чтобы попробовать это в своей собственной IDE:

func isValidPlacement(row:Int,col:Int) -> Bool {
        if let t = try? tiles[row-1][col], t.isSource {
            return true
        }
        else if let t = try? tiles[row][col-1], t.isSource {
            return true
        }
        else if let t = try? tiles[row+1][col], t.isSource {
            return true
        }
        else if let t = try? tiles[row][col+1], t.isSource {
            return true
        }
        else {
            return false
        }
    }

Ответы [ 3 ]

0 голосов
/ 06 мая 2020

В Swift. вы можете поймать только экземпляры Error, которые генерируются кодом, вы не можете поймать исключения времени выполнения, такие как нарушение границ массива

Вы можете создать свою собственную функцию safeAccess. Вы не говорите, какой тип находится в вашем массиве, поэтому я буду использовать SomeType в качестве примера

func safeAccess(row:Int, col:Int) -> SomeType? {
   guard row >= 0, row < tiles.count else {
       return nil
   }

   guard col >= 0, col < tiles[row].count else {
       return nil
   }

   return tiles[row][col]
}

func isValidPlacement(row:Int,col:Int) -> Bool {

    if let t = tiles.safeAccess(row:row-1,col:col), t.isSource {
        return true
    }

    if let t = tiles.safeAccess(row:row,col:col-1),, t.isSource {
        return true
    }

    if let t = tiles.safeAccess(row:row+1,col:col), t.isSource {
        return true
    }

    if let t = tiles.safeAccess(row:row,col:col+1), t.isSource {
        return true
    }

    return false

}

Вы также можете определить расширение для Array

extension Array {
    func element(at index: Int) -> Element? {
        if index >= 0 && index < self.count {
             return self[index]
        }
        return nil
    }
}

И использовать:

func isValidPlacement(row:Int,col:Int) -> Bool {
    if let tiles = tiles.element(at:row-1), let t = tiles.element(at:col), t.isSource {
        return true
    }
    else if tiles.element(at:row), let t = tiles.element(at:col-1), t.isSource {
        return true
    }
    else if let tiles = tiles.element(at:row+1), let t = tiles.element(at:col), t.isSource {
        return true
    }
    else if let tiles = tiles.element(at:row), let t = tiles.element(at:col+1), t.isSource {
        return true
    }
    else {
        return false
    }
}
0 голосов
/ 06 мая 2020

Ошибки времени выполнения и возвращение bools - это способ C цели! Бросить бросить бросить! ?

public extension Collection {
  /// - Returns: same as subscript, if index is in bounds
  /// - Throws: CollectionIndexingError
  func element(at index: Index) throws -> Element {
    guard indices.contains(index)
    else { throw CollectionIndexingError() }

    return self[index]
  }
}

extension Collection where Element: Collection {
  /// - Returns: same as subscripting, if indices are in bounds
  /// - Throws: CollectionIndexingError
  func element( at indices: (Index, Element.Index) ) throws -> Element.Element {
    try element(at: indices.0).element(at: indices.1)
  }
}

/// Thrown when `getElement` is called with an invalid index.
public struct CollectionIndexingError: Error { }
extension Tile {
  enum PlacementError: Error {
    case invalid
    case noSources
  }
}

extension Collection where
  Index == Int,
  Element: Collection, Element.Index == Int, Element.Element == Tile
{
  func validatePlacement(row: Index, column: Element.Index) throws {
    let tiles = [(-1, 0), (0, -1), (1, 0), (0, 1)].compactMap {
      try? element( at: (row + $0.0, column + $0.1) )
    }

    guard !tiles.isEmpty
    else { throw Tile.PlacementError.invalid }

    guard tiles.contains(where: \.isSource)
    else { throw Tile.PlacementError.noSources }
  }
}
0 голосов
/ 06 мая 2020

Доступ к индексу несуществующего массива приводит к исключению времени выполнения. Вы не можете использовать здесь try, потому что массив ничего не бросает.

Попробуйте добавить эти две строки в начале игры c и избавьтесь от всех попыток?

guard row <= tiles.count - 1 else {
    return false
}
guard col <= tiles[row].count - 1 else {
    return false
}

Также я предполагаю, что все, что здесь хранится в массиве типов, является по желанию. если нет, можно удалить, если тоже

func isValidPlacement(row:Int,col:Int) -> Bool {
    guard row <= tiles.count - 1 else {
        return false
    }
    guard col <= tiles[row].count - 1 else {
        return false
    }

    if let t =  tiles[row-1][col], t.isSource  {
        return true
    }
    else if let t =  tiles[row][col-1], t.isSource  {
        return true
    }
    else if let t =  tiles[row+1][col], t.isSource  {
        return true
    }
    else if let t =  tiles[row][col+1], t.isSource  {
        return true
    }
    else {
        return false
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...