LoginSignup
31
24

More than 5 years have passed since last update.

NSExceptionをSwiftでtry-catchする

Last updated at Posted at 2016-11-01

KVOでaddObserverしたものをremoveObserverするときなどに、addした以上にremoveを呼ぶとExceptionが発生します。
しかし、発生したExceptionはSwiftで直接catchすることはできません。

以下のようなObjective-Cのラッパーを使用することで、そのExceptionをcatchすることができるようになります。

ExceptionHandler.m
#import "ExceptionHandler.h"

@implementation ExceptionHandler

+ (BOOL)catchExceptionWithTryBlock:(__attribute__((noescape)) void(^ _Nonnull)())tryBlock error:(NSError * _Nullable __autoreleasing * _Nullable)error {
    @try {
        tryBlock();
        return YES;
    } @catch (NSException *exception) {
        *error = [NSError errorWithDomain:exception.name code:-9999 userInfo:exception.userInfo];
        return NO;
    }
}

@end

上記のように引数がNSError **で返り値がBOOLなメソッドは、Swift側で自動的にthrowableなメソッドとして変換されるようです。

ExceptionCatchable.swift
protocol ExceptionCatchable {}

extension ExceptionCatchable {
    func execute(_ tryBlock: () -> ()) throws {
        try ExceptionHandler.catchException(try: tryBlock)
    }
}

Protocolとして継承したクラスでのみ使いたかったので、デフォルト実装をしてもう一度throwします。

ViewController.swift
class DataSource: NSObject {
    dynamic var value: String = ""
}

class ViewController: UIViewController, ExceptionCatchable {

    let dataSource = DataSource()

    deinit {
        do {
            try execute {
                dataSource.removeObserver(self, forKeyPath: "value")
                dataSource.removeObserver(self, forKeyPath: "value")
            }
        } catch let e {
            print("\n", e, "\n")
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        dataSource.addObserver(self, forKeyPath: "value", options: .new, context: nil)
    }
}

上記のようにすることで、executeメソッドにExceptionが起こるであろう処理のClosureを渡して、try-catchできるようになります。

KVOのremoveの場合だけでなく、握りつぶしたいExceptionの場合にも使用可能です。

31
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
24