Swiftのデバッグ関数をつくる
アプリ道場 Advent Calendar 2015のトップバッター、@mo_to_44です。Advent Calendarの最初の投稿なのでゆるめにデバッグ関数の定義をしてみようと思います。
DebugLog
関数
こちらがコードです。コードはgistにアップしています。
func DebugLog(@autoclosure condition: () -> Bool = true, _ message: String = "", function: StaticString = __FUNCTION__, file: StaticString = __FILE__, line: UInt = __LINE__) {
#if DEBUG
if let fileName = NSURL(string: String(file))?.lastPathComponent {
print("time: \(NSDate()), message: \(message), function: \(function), file: \(fileName), line: \(line)")
} else {
print("time: \(NSDate()), message: \(message), function: \(function), file: \(file), line: \(line)")
}
assert(condition, message, file: file, line: line)
#endif
}
#if DEBUG
の設定方法ですが、Build Settings > Swift Compiler > Other Swift Flagsに -DDEBUG
を指定すればOKです。
なにをしているのか
なにをしているのか見ていきましょう。DebugLog
関数でやっていることは以下の通りです。
-
DebugLog
が呼び出された時間の出力 -
DebugLog
呼び出し元のファイル名出力 -
DebugLog
呼び出し元の関数名出力 -
DebugLog
呼び出し元のファイル内の行数出力 -
assert
の実行
1については簡単ですね。print
関数内でNSDate()
を呼び出して現在の時間を出力しているだけです。それ以外の部分について見ていきましょう。
関数名、ファイル名、ファイル内の行数の出力
Swiftでは__FILE__
, __LINE__
, __COLUMN__
, __FUNCTION__
という特殊な識別子が定義されており、これを利用して関数名、ファイル名、ファイル内行数の出力を行っています (参考)。
__FILE__ |
__LINE__ |
__COLUMN__ |
__FUNCTION__ |
---|---|---|---|
ファイル名 | 行数 | カラム | 関数 |
assert
関数呼び出し
condition
がfalse
だった場合はassert
が実行されるようになっています。異常な値が入っている場合にassert
が実行されます。
デフォルト引数を指定してログとassert
を使い分けるようにする
DebugLog
の引数は全てデフォルト引数を指定しているので、DebugLog()
のように呼び出した場合は単にログのみが出力されます。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
DebugLog()
}
}
上記のコードを実行した場合、以下のログが出力されます。
time: 2015-11-29 14:55:09 +0000, message: , function: viewDidLoad(), file: ViewController.swift, line: 16
デバッグ時にassert
で値のチェックもしたい場合は以下のように呼び出します。someValue
が1未満の場合はログの出力とともに、assert
で実行を停止します。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let someValue = 0
DebugLog(someValue > 0)
}
}
以下のようなログが出力され、プログラムが停止します。
time: 2015-11-29 14:58:32 +0000, message: , function: viewDidLoad(), file: ViewController.swift, line: 18
assertion failed: : file /Users/Motoki/Desktop/Example/Example/ViewController.swift, line 18
第2引数には付加情報としてメッセージを入れることができます。
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let someValue = 0
DebugLog(someValue > 0, "Unexpected value")
}
}
このように指定した場合は、以下のように出力されます。
time: 2015-11-29 15:11:03 +0000, message: Unexpected value, function: viewDidLoad(), file: ViewController.swift, line: 16
assertion failed: Unexpected value: file /Users/Motoki/Desktop/Example/Example/ViewController.swift, line 16
まとめ
必要な情報はプロジェクトによっても変わってくると思うのですが、関数名、ファイル名、行数などが分かるとデバッグ時に便利かと思います。今回は状況によってはassert
関数を実行させるようにしました。
デバッグ関数を定義する際の参考にしてみてください。