Closed3

NSExceptionをSwiftでハンドリングする...のは分かったけど、どうしてそうしなきゃならないか

mactkgmactkg

あらすじ

Objective-Cのクラスが絡むとあるエラーを直したくて、まずはExceptionが発生するテストをSwiftで書こうと思った。Objective-Cのクラスの内部ではNSException由来のExceptionが起こるようになっていて、XCTAssertThrows() を使えばテストが書けると思ったが、うまくいかなかった。

try { ~ } catch let error { ~ } とか使ってもダメ。

どうやらNSExceptionをSwiftでハンドリングすることはできなくて、ちょっとした工夫をしてやる必要があるらしい。Objective-Cの世界で例外をキャッチしてやるということ。なのでこんな感じのヘルパーを作ってあげると良い。

typedef void (^VoidBlock)(void);

BOOL throwsToBool(VoidBlock const block) {
  @try {
      block();
  }
  @catch (NSException * const notUsed) {
      return YES;
  }
  return NO;
}

このコード自体はXCTest: The Good Parts を参考にした。

使い方としては、

class FooTest: XCTestCase {
  func testCase() throws {
    XCTAssertTrue(throwsToBool {
      ObjectiveCWorld.dangerMethod()
    }, "dangerMethod() 呼んだらException!")
  }
}

って感じ。

でもどうしてObjective-Cの世界でのNSExceptionがハンドリングできないのか。がいまいちわからないので調べたい。

mactkgmactkg

NSErrorとNSExceptionについて整理する

When you’re writing code with Objective-C, exceptions are used solely for programmer errors, like out-of-bounds array access or invalid method arguments. These are the problems that you should find and fix during testing before you ship your app.
All other errors are represented by instances of the NSError class.
Dealing with Errors

とあるので...。プログラマが悪くて出荷する前に認識しておくべきようなエラーはExceptionで、そのほかはNSErrorで表現されると書いてある。

このスクラップは2021/11/26にクローズされました