■ 概要
Swiftでログを出力するとなれば標準の「print関数」を使うのが一番簡単で手っ取り早いと思います。何かしらの結果をすぐログで出力して確認する用途であれば十分なのですが、アプリ内の処理結果を追う目的などの意図的に残すログとしてはあまりにも不十分です。(ショボすぎ)
とは言いつつ、そのログで確認したい情報ってある程度限られてきますし、そのためにLoggerのライブラリを入れるのもなぁという気持ちしかないです。
そのため今回は、標準のライブラリとフレームワークのみを使ったカスタムLoggerを実装してみました。
■ 環境
開発動作環境:MacBook Pro 16インチ
OSバージョン:macOS Sequoia バージョン15.0.1
Xcodeバージョン:16.2
■ 実装
import Foundation
class Logger {
private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter
}()
static func puts(_ items: Any..., file: String = #file, function: String = #function, line: Int = #line) {
let currentTime = Logger.dateFormatter.string(from: Date())
let itemStrings = items.map { String(describing: $0) }.joined(separator: " ")
let fileName = URL(fileURLWithPath: file).lastPathComponent
print("[\(currentTime)] \(fileName) (Line: \(line)) \(function) \(itemStrings)")
}
}
こんな感じで呼び出すと
Logger.puts("テスト")
こんな感じで出力されます。
[2025-03-28 14:47:01] TransitionView.swift (Line: 78) updateAnimation() テスト
■ 解説
Loggerとして必要な最低限の情報を
① 日付時間
② ファイル名
③ 行数
④ 関数名
⑤ 出力する任意の値
として実装しました。
Swiftで「print関数」をラップする形で実装することで、軽量かつ、ライブラリ関連などの特定環境に依存しないというメリットがあります。また上記の項目以外にも必要な情報があれば追加して、自由に出力のフォーマットを変更できるのも良い点です。
実装自体は「解説」ってほど内容はないですが、要所だけ。
1. 可変長引数
第一引数はAny型の可変長引数(任意の数だけ引数を渡せます)にしており、標準の「print関数」とインターフェースを統一してみました。
2. リテラル(#file、 #function、 #line)
第二引数以降はファイルパス(#file)
、関数名(#function)
、行数(#line)
のリテラルを、引数のデフォルト値に設定しておくことで、この関数の「呼び出し元」の値を取得することができます。(つまりこのputs関数の呼び出した側のクラスのファイルパス、関数名、行数を取得できます。)
またデフォルト値が設定されていることにより、実際にコーディングする時にエディタの補完にも第二引数以降は出てこない(省略可能である)ため、第二引数以降を基本的には一切意識せずに使用できます。
3. 「DateFormatter」はstatic定数で定義
スレッドセーフ、パフォーマンスを考慮してDateFormatterオブジェクトは静的定数で定義しています。
■ 最後に (感想)
Loggerとして必要最低限の機能を、限りなくミニマムで実装できたので良かったです。使えそうだなと思ってもらえたり、何かの実装の参考になれば幸いです。
最後まで読んでいただきありがとうございました。