ios - thread - Swift 2:コールはスローできますが、「試行」とマークされていないため、エラーは処理されません




thread 1: signal sigabrt (2)

Xcode 7ベータ版をインストールしてスウィフトコードをSwift 2に変換した後、私は理解できないコードに問題があります。 私はSwift 2が新しいと知っているので、私は検索してそれについては何もないので、私は質問を書くべきです。

ここにエラーがあります:

呼び出しはスローできますが、 'try'とマークされていないため、エラーは処理されません

コード:

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

        //The Line Below is where i expect the error
        let fetchedEntities = self.Context!.executeFetchRequest(request) as! [AccountDetail]

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

        do {
            try self.Context!.save()
        } catch _ {
        }

    }

スナップショット:


Swiftでthrowsで宣言された関数を呼び出すときは、関数呼び出しサイトにtryまたはtry!アノテーションを付ける必要がありますtry! 。 たとえば、スロー関数を指定すると次のようになります。

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

この関数は次のように呼び出すことができます:

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

ここでは、この関数に例外がスローされる可能性があり、次のコード行が実行されない可能性があることを読者に呼び出すtry呼び出しに注釈を付けます。 この関数は例外をスローする可能性があるため(つまり、 willOnlyThrowIfTrue()スローすると、 fooは自動的に例外を上方に再スローするため、 throwsでこの関数に注釈を付ける必要があります。

おそらく投げられると宣言されているが、正しい入力を与えているのであなたのケースに投げ込まないことを知っている関数を呼びたい場合は、 try!

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

このようにして、コードがスローされないことが保証されたら、例外伝播を無効にするために定型コードを追加する必要はありません。

try! 実行時に強制されます: try! 関数がスローすると、プログラムの実行は実行時エラーで終了します。

ほとんどの例外処理コードは、上記のようになります。発生したときに例外を上方向に伝播するか、そうでなければ可能な例外が除外されるように条件を設定します。 コード内の他のリソースのクリーンアップは、オブジェクトの破棄(つまりdeinit() )を介して、または時にはdeinit()コードを介して行われるべきです。

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()またはdeinit()によって途中でクリーンアップを行います。 これは、ほとんどのコードがエラーの処理方法を知らないためです。 何がうまくいかなかったのか分かっていますが、エラーについて何をすべきかを知るために、より高いレベルのコードが何をしようとしているのかについて十分な情報がありません。 ユーザーに対話を提示することが適切であるか、再試行する必要があるか、または他の何かが適切かどうかはわかりません。

しかし、より高いレベルのコードでは、エラーが発生した場合の対処方法を正確に把握する必要があります。 したがって、例外によって、特定のエラーが最初に発生した場所から処理できる場所までバブルアップすることができます。

例外の処理は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/参照してhttp://exceptionsafecode.com/ 。 具体的にはC ++を対象としていますが、Swift例外モデルを検証した後、基本はSwiftにも当てはまると思います。

Swiftの構文とエラー処理モデルの詳細については、 The Swift Programming Language(Swift 2 Prerelease)の本を参照してください。


save()コールのsave()すでに行っているようにエラーをキャッチする必要があります。ここで複数のエラーを処理しているので、1つのdo-catchブロックで複数のコールを連続して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()
}




swift