Objective-Cを使ったiOSアプリ開発では、C言語のプリプロセッサ命令を使って、NSLog
を#ifdef DEBUG
で囲むデバッグマクロのテクニックがよく利用されていました。
#ifdef DEBUG
#define LOG(...) NSLog(__VA_ARGS__)
#define LOG_METHOD NSLog(@"%s line %d", __func__, __LINE__)
#define LOG_OBJECT(obj) NSLog(@"%s=%@", #obj, obj);
#else
#define LOG(...)
#define LOG_METHOD
#define LOG_OBJECT(obj)
#endif
Swiftでは残念ながら、C言語ほどの複雑なマクロを実装する機能はなく、
唯一できるのは、 コマンドラインフラグ を使って、簡単な#if
を使う方法です。
OTHER_SWIFT_FLAGS = -D DEBUG
func LOG(body: String) {
#if DEBUG
NSLog(body)
#endif
}
Swiftでも__FUNCTION__
や__LINE__
といったリテラルは健在なので、
上記CマクロのLOG
やLOG_METHOD
は割りと簡単に実装できます。
が、LOG_OBJECT
のような、「#を使った文字列化(stringification)」をコンパイル時に行うことは難しいので、これをランタイム時に無理やり処理してみた、というのが今回作ったライブラリの主な趣旨です。
今回作ったライブラリ
まだ、いろいろバグが多いですが、
LOG()
LOG("Hello World!")
LOG_OBJECT(self.window)
LOG_OBJECT(AppDelegate.self)
let int: Integer = 3
LOG_OBJECT(int)
let float: Float = 3.0
LOG_OBJECT(float)
let rect: CGRect = CGRect(x: 10, y: 20, width: 30, height: 40)
LOG_OBJECT(rect)
let range: Range = 1..3
LOG_OBJECT(range)
let nsRange: NSRange = NSMakeRange(2, 4)
LOG_OBJECT(nsRange)
let optional: Int? = nil
LOG_OBJECT(optional)
と実行すると、
[AppDelegate.application(_:didFinishLaunchingWithOptions:):43]
[AppDelegate:45] Hello World!
[AppDelegate:47] self.window = <UIWindow: 0xb50ab50; frame = (0 0; 320 480); gestureRecognizers = <NSArray: 0xb50b3c0>; layer = <UIWindowLayer: 0xb50adc0>>
[AppDelegate:48] AppDelegate.self = DebugLogDemo.AppDelegate
[AppDelegate:51] int = 3
[AppDelegate:54] float = 3.0
[AppDelegate:57] rect = (10.0,20.0,30.0,40.0)
[AppDelegate:60] range = (1..3)
[AppDelegate:63] nsRange = (2,4)
[AppDelegate:66] optional = nil
といった感じに出力してくれます。
println("mySuperDuperView = \(mySuperDuperView)")
を毎回書きたくない人に便利だと思うので、ぜひ使ってみてください。