заменить guard let try на do и catch

#swift

#swift

Вопрос:

У меня есть следующая реализация, и я распространяю проблемы на ViewController для правильного отображения предупреждения. Как вы видите в моем коде, я использую guard let и пробую все вместе в одной строке. Я думаю, это работает, но не рекомендуется.

Что было бы наилучшим для обработки / рефакторинга кода для правильной обработки каждого случая броска?

 enum ServiceError: Error {
  case ClassroomApplicationCreation(Error)
  case ClassroomDoesNotExist(Error)
  case ClassRoomSelectionError
}

func createClassroom() throws -> String {
    guard let selectedClass = try findClassroom() else {
      throw ServiceError.ClassSelectionError
    }
    guard let classURL = URL(string: selectedClass) else {
      throw ServiceError.ClassroomDoesNotExist
    }
    let authority = try Authority(url: classURL)
    let configuration = ClassroomApplicationConfig(className: selectedClass, redirectUri: nil, authority: authority)
    do {
      return try ClassRoom(configuration: configuration)
    } catch {
      throw ServiceError.ClassroomApplicationCreation(error)
    }
}

func findClassroom() throws -> String? {
    guard
      let selectedClass = UserDefaults.standard.string(forKey: selectedClass)
    else {
      throw ServiceError.ClassRoomSelectionError
    }
    do {
      return try serviceManager.retrieveClassroom(selectedClass)
    } catch {
      throw ServiceError.ClassRoomSelectionError
    }
}
  

Комментарии:

1. Почему нормально пересылать по инициализации полномочий, в то время как другие ошибки должны быть запутаны?

2. IMO, если ваш метод выдает ошибку, вы не должны перехватывать там ошибки. Просто выбросьте правильные ошибки из вашего метода findClassroom и инициализатора ClassRoom.

3. @LeoDabus, не могли бы вы привести пример?

4. Просто удалите do catch и выдайте ошибку из вашего инициализатора и из метода findClassroom

5. Вы имеете в виду последнее do catch ? На какой инициализатор вы ссылаетесь?

Ответ №1:

Вы можете провести рефакторинг, чтобы у вас не было никаких охранников или блоков do / catch:

 func createClassroom() throws -> ClassRoom {
    let selectedClass = try findClassroom()
    let classURL = try makeClassURL(from: selectedClass)
    let authority = try Authority(url: classURL)
    let configuration = ClassroomApplicationConfig(classId: selectedClass.ID, redirectUri: nil, authority: authority)
    return try makeClassRoom(from: configuration)
}


func findClassroom() throws -> String {
    guard allIsWell else { throw ServiceError.ClassRoomSelectionError }
    return ""
}

func makeClassURL(from string: String) throws -> URL {
    guard let classURL = URL(string: string) else {
        throw ServiceError.UserDoesNotExist
    }
    return classURL
}

func makeClassRoom(from configuration: ClassroomApplicationConfig) throws -> ClassRoom {
    do {
        return try ClassRoom(configuration: configuration)
    } catch {
        throw ServiceError.ClassroomApplicationCreation(error)
    }
}
  

Ответ №2:

Предполагая ClassRoom(configuration: configuration) , что выбрасывает .classroomApplicationCreation и findClassroom выбрасывает .classRoomSelectionError при сбое и возвращает необязательный результат при успешном выполнении, код может быть сокращен до

 enum ServiceError: Error {
   case classroomApplicationCreation(Error)
   case userDoesNotExist(Error) 
   case classRoomSelectionError
}

func createClassroom() throws -> ClassRoom {
    let selectedClass = try findClassroom()
    guard let classURL = URL(string: selectedClass) else {
       throw ServiceError.userDoesNotExist
    }
    let authority = try Authority(url: classURL)
    let configuration = ClassroomApplicationConfig(classId: selectedClass.ID, redirectUri: nil, authority: authority)
    return try ClassRoom(configuration: configuration)
}
  

И тип возвращаемого значения должен быть ClassRoom .

Комментарии:

1. У меня есть исправленный findClassroom() метод