Objective-CとSwiftとの大きな違いの一つとしてマクロの扱いが挙げられます。
そのためマクロ前提のロギングなどのObjective-CライブラリはSwiftでは利用できなくなりました。
ネット上でよく見かける擬似コードは以下のようになります。
func MyLog(message: String, function: String = __FUNCTION__, line: Int = __LINE__) {
#if DEBUG
println("")//省略
#endif
}
上記の場合、以下の2点が気になります。
-
DEBUG
ではない場合もmessage
が評価される-
MyLog("\(fibonacci(100))")
のような重い処理が表示されなくても実行されてしまう
-
-
MyLog(1, 2, "3")
のように複数の値を同時に表示することができない
##1
の対策
Swiftのassert
関数のように@autoclosure
で包み込む
func MyLog(message: @autoclosure () -> String, _ function: String = __FUNCTION__, _ line: Int = __LINE__) {
#if DEBUG
println("\(message())")//省略
#endif
//DEBUGではない場合、message内部は評価されない
}
##2
の対策
こちらはGenericsとオーバーロードの力技で対応します。
func MyLog<T>(message: T, _ function: String = __FUNCTION__, _ line: Int = __LINE__) {
#if DEBUG
println("")//省略
#endif
}
func MyLog<T1, T2>(t1: T1, _ t2: T2, _ function: String = __FUNCTION__, _ line: Int = __LINE__) {
MyLog((t1, t2), function, line)
}
func MyLog<T1, T2, T3>(t1: T1, _ t2: T2, _ t3: T3, _ function: String = __FUNCTION__, _ line: Int = __LINE__) {
MyLog((t1, t2, t3), function, line)
}
//以下、必要な個数分続く
MyLog(1) //MyLog<T>(...)が呼ばれる
MyLog(1, "2") //MyLog<T1, T2>(...)が呼ばれる
1
はともかく2
は単純に手間なので、それらを踏まえ実装した自作ライブラリがこちらになります。
LoggingKit
Swift1.1の記法に対応しました。
LoggingKit tag:swift/1.1
使い方
AppDelegate.swift
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
#if DEBUG
LOGGING_VERBOSE() //デバッグ時は全てのログを表示
#endif
}
Logging.e(someError)
let v: String! = nil
Logging.v(1, "2", 3.0, v, Optional(5)) //(1, 2, 3.0, nil, 5)
補足
Swift1.2 Beta1で作成しているためSwift1.1では今のところ利用できません。
週末にSwift1.1に対応したいと思います。