получение ошибки при интеграции v1.1 API [дубликат]

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

132
задан Farhad 9 June 2015 в 16:03
поделиться

2 ответа

Вы должны поймать ошибку так же, как вы уже делаете для своего вызова save(), и поскольку вы обрабатываете несколько ошибок здесь, вы можете try несколько вызовов последовательно в одном блоке блокировки наложения, например :

func deleteAccountDetail() {
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
    let request = NSFetchRequest()
    request.entity = entityDescription

    do {
        let fetchedEntities = try self.Context!.executeFetchRequest(request) as! [AccountDetail]

        for entity in fetchedEntities {
            self.Context!.deleteObject(entity)
        }

        try self.Context!.save()
    } catch {
        print(error)
    }
}

Или, как указано в @ bames53 в комментариях ниже, часто лучше не ловить ошибку, где она была выбрана. Вы можете пометить метод как throws, затем try, чтобы вызвать метод. Например:

func deleteAccountDetail() throws {
    let entityDescription = NSEntityDescription.entityForName("AccountDetail", inManagedObjectContext: Context!)
    let request = NSFetchRequest()

    request.entity = entityDescription

    let fetchedEntities = try Context.executeFetchRequest(request) as! [AccountDetail]

    for entity in fetchedEntities {
        self.Context!.deleteObject(entity)
    }

    try self.Context!.save()
}
145
ответ дан Mick MacCallum 17 August 2018 в 15:07
поделиться
  • 1
    Это поможет мне разобраться в этом, спасибо. – Farhad 9 June 2015 в 16:20
  • 2
    На самом деле не обязательно, чтобы исключение было поймано здесь. Можно просто добавить ключевое слово try в вызов функции и объявить эту функцию как func deleteAccountDetail() throw. Или, если вы гарантировали, что функция не будет выбрасывать для данного ввода, вы можете использовать try!. – bames53 9 June 2015 в 16:32
  • 3
    Я приношу это не к nitpick, а потому, что на самом деле очень важно для достойной обработки ошибок на основе исключений, что большинство мест, где происходят исключения, не перехватывают исключения. Существует три типа мест, где уловки исключений являются подходящими. Во всех других местах код не должен обрабатывать исключения явно и должен полагаться на неявные вызовы deinit() для очистки (т. Е. RAII) или иногда использовать defer для выполнения некоторой специальной очистки. Дополнительную информацию см. В разделе exceptionsafecode.com (он говорит о C ++, но основные принципы применимы и к исключениям Swift). – bames53 9 June 2015 в 16:34
  • 4
    Но как бы вы запустили эту функцию? Если я пойду с помощью @ bames53? – Farhad 9 June 2015 в 17:21
  • 5
    @NickMoore То, что разработчики Swift предпочитают называть, не влияет на то, что они на самом деле. Новая система обработки ошибок Swift представляет собой реализацию исключений, так как этот термин обычно используется во всей остальной отрасли. – bames53 18 June 2015 в 18:48

При вызове функции, объявленной с помощью throws в Swift, вы должны аннотировать сайт вызова функции с помощью try или try!. Например, с учетом функции throwing:

func willOnlyThrowIfTrue(value: Bool) throws {
  if value { throw someError }
}

эту функцию можно вызвать как:

func foo(value: Bool) throws {
  try willOnlyThrowIfTrue(value)
}

Здесь мы аннотируем вызов с помощью try, который вызывает что эта функция может генерировать исключение, и любые следующие строки кода могут не выполняться. Мы также должны аннотировать эту функцию с помощью throws, потому что эта функция может генерировать исключение (т. Е. Когда willOnlyThrowIfTrue() бросает, тогда foo автоматически восстанавливает исключение вверх.

Если вы хотите вызовите функцию, которая объявлена ​​как возможно бросающая, но которую вы знаете, не будет бросать в ваш случай, потому что вы даете ей правильный ввод, вы можете использовать try!.

func bar() {
  try! willOnlyThrowIfTrue(false)
}

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

try! применяется во время выполнения: если вы используете try!, и функция

Большинство обработок обработки исключений должно выглядеть так: либо вы просто распространяете исключения вверх, когда они происходят, либо вы устанавливаете такие условия, что в противном случае исключаются исключения. Любая очистка других ресурсов вашего кода должна происходить посредством уничтожения объекта (например, deinit()) или иногда через defer ed код.

func baz(value: Bool) throws {

  var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
  var data = NSData(contentsOfFile:filePath)

  try willOnlyThrowIfTrue(value)

  // data and filePath automatically cleaned up, even when an exception occurs.
}

Если по какой-либо причине вы очищаете код, который нужно запустить, но не в функции deinit(), вы можете использовать defer.

func qux(value: Bool) throws {
  defer {
    print("this code runs when the function exits, even when it exits by an exception")
  }

  try willOnlyThrowIfTrue(value)
}

Большинство кода, который имеет дело с исключениями, просто передают их вверх вызывающим абонентам, проводя очистку по пути через deinit() или defer. Это связано с тем, что большинство кодов не знает, что делать с ошибками; он знает, что пошло не так, но у него недостаточно информации о том, что пытается сделать какой-то код более высокого уровня, чтобы знать, что делать с ошибкой. Он не знает, подходит ли представление пользователю диалога, или если он должен повторить попытку, или если что-то еще подходит.

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

Обработка исключений выполняется с помощью операторов catch.

func quux(value: Bool) {
  do {
    try willOnlyThrowIfTrue(value)
  } catch {
    // handle error
  }
}

Вы можете имеют несколько операторов catch, каждый из которых имеет различный вид исключения.

  do {
    try someFunctionThatThowsDifferentExceptions()
  } catch MyErrorType.errorA {
    // handle errorA
  } catch MyErrorType.errorB {
    // handle errorB
  } catch {
    // handle other errors
  }

Подробнее о передовых методах с исключениями см. в http://exceptionsafecode.com/ . Это специально предназначено для C ++, но после изучения модели исключения Swift я считаю, что основы применимы и к Swift.

Подробнее о модели синтаксиса Swift и обработки ошибок см. В книге The Swift Язык программирования (Swift 2 Prerelease) .

35
ответ дан bames53 17 August 2018 в 15:07
поделиться
  • 1
    В основном уловка может справиться с ошибкой? или входной функции – Farhad 9 June 2015 в 18:26
  • 2
    @BrianS Я точно не знаю, что вы спрашиваете, особенно в отношении «функции ввода», но «catch» по сути является синонимом «handle» в контексте исключений. То есть, исключение и обработка исключения - одно и то же, что касается языков программирования. – bames53 9 June 2015 в 19:49
  • 3
    Это то, что я имел в виду – Farhad 9 June 2015 в 19:50
  • 4
    У меня одна ошибка, я не понимаю, не могли бы вы помочь мне? Invalid conversion from throwing function of type '() throws -> _' to non-throwing function type '(NSData?, NSURLResponse?, NSError?) -> Void' – Farhad 9 June 2015 в 19:52
  • 5
    @BrianS Похоже, вы где-то используете функцию с некорректной подписью. Что-то ожидает получить функцию, которая принимает NSData?, NSURLResponse?, NSError? как аргументы, но вы даете ей функцию, которая не принимает никаких аргументов. – bames53 9 June 2015 в 19:57
Другие вопросы по тегам:

Похожие вопросы: