web-dev-qa-db-ja.com

SwiftでCrashlyticsロギングを使用する方法は?

This の記事では、objective-cでCrashlyticsロギングを使用する方法について説明しています。しかし、CrashlyticsおよびFabricをプロジェクトに適切に参照するためのインストール手順を徹底的に検討した後、その方法にアクセスできないようです。

Crashlytics.hファイルを見ると、コンパイラフラグを使用して定義されていることがわかります。

_#ifdef DEBUG
#define CLS_LOG(__FORMAT__, ...) CLSNSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define CLS_LOG(__FORMAT__, ...) CLSLog((@"%s line %d $ " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#endif
_

このブロックは、コンパイラフラグに応じてCLSNLogおよびCLSLog関数をラップするように見えます。

だから、ソースに直接行くと思って、Swiftファイルから直接CLSLogを参照しようとしました。

My-Bridging-Header.h:

_#import <Crashlytics/Crashlytics.h>
_

Log.Swift:

_import Foundation
import Fabric
import Crashlytics

func Log(message: String) {
    NSLog("%@", message)
    CLS_LOG("%@", message)
    CLSLog("%@", message)
}
_

Log関数の最後の2行は、エラー_Use of unresolved identifier_をスローします。 Crashlyticsのクラッシュレポートは、ログ機能を除き、正常に機能します。 this の記事によると、Swiftのロギングサポートが実装されました。

バージョンに関しては、Fabric/Crashlyticsの最新バージョンを実行しています(この投稿の時点では12月リリースです)。

(興味深いメモ、CLSLogv()...を表示/使用できます)

Swiftプロジェクトで使用するために_CLS_LOG_を組み込む正しい方法を知っている人はいますか?

37
Albert Bori

次のような中間ブリッジを作成する必要があります。

CrashlyticsBridge.h:

#import <Foundation/Foundation.h>

@interface CrashlyticsBridge : NSObject

+ (void)log:(NSString *)message;

@end

CrashlyticsBridge.m

#import "CrashlyticsBridge.h"
#import <Crashlytics/Crashlytics.h>

@implementation CrashlyticsBridge

+ (void)log:(NSString *)message {
    CLS_LOG(@"%@", message);
}

@end

My-Bridging-Header.h:

#import "CrashlyticsBridge.h"

次に、それをLog関数に追加するだけです:

func Log(message: String) {
    CrashlyticsBridge.log(message)
}

これにより、デバッグ中にCrashlyticsのログとNSLoggingが得られます。

10
Porter Hoskins

Crashlyticsのマイクはこちら。

Swiftでカスタムロギングを使用するには、CLSLogvまたはCLSNSLogvを使用します。配列を作成してから、その配列に対してgetVaList関数を呼び出す必要があります。

これがスニペットです。

CLSLogv("Log something %d %d %@", getVaList([1, 2, "three"]))

CLSNSLogvの場合:

CLSNSLogv("hello %@", getVaList(["goodbye"]))
37
Mike Bonnell

以下は、Dimaの回答から引用した私のバージョンです。あなたが渡すSwift=文字列内ですべての書式設定を行うことができるので、引数は必要ありません。

func DebugLog(_ message: String, file: StaticString = #file, function: StaticString = #function, line: Int = #line) {
    let output: String
    if let filename = URL(fileURLWithPath: file.description).lastPathComponent.components(separatedBy: ".").first {
        output = "\(filename).\(function) line \(line) $ \(message)"
    } else {
        output = "\(file).\(function) line \(line) $ \(message)"
    }

    #if targetEnvironment(simulator)
        NSLogv("%@", getVaList([output]))
    #elseif DEBUG
        CLSNSLogv("%@", getVaList([output]))
    #else
        CLSLogv("%@", getVaList([output]))
    #endif
}

そして、あなたはこれを次のように使用します:

DebugLog("this is a log message")
DebugLog("this is a log message \(param1) \(param2)")

[〜#〜] edit [〜#〜]:Swift 3.1に更新

28
ian

CLS_LOG() in Swiftに似たものが必要でした。呼び出しの場所に関するコンテキスト情報を出力しました。通常、これはプリプロセッサディレクティブなしでは不可能でしたが、 Swift here: https://developer.Apple.com/Swift/blog/?id=15

必要な識別子(_#file, #function, #line_)は、引数リストでデフォルト値として設定した場合、呼び出し元に関する情報を表示します。

注:ネットワーククエリ文字列など、_%_シンボルが含まれる可能性のあるエラーをログに記録している場合、クラッシュする可能性があります。最初に文字列を結合する必要があります(例:let string = "\(filename).\(function) line \(line) $ \(message)"

Swift 3バージョン(注:これはグローバル関数であるため、構造体またはクラス定義の外側に配置する必要があります):

_/// Usage:
///
/// CLS.log("message!")
/// CLS.log("message with parameter 1: %@ and 2: %@", ["First", "Second"])
///
func CLS_LOG_Swift(format: String = "", _ args: [CVarArg] = [], file: String = #file, function: String = #function, line: Int = #line) 
{
    let filename = URL(string: file)?.lastPathComponent.components(separatedBy: ".").first

    #if DEBUG
        CLSNSLogv("\(filename).\(function) line \(line) $ \(format)", getVaList(args))
    #else
        CLSLogv("\(filename).\(function) line \(line) $ \(format)", getVaList(args))
    #endif
}
_

Swift 2バージョン:

_// CLS_LOG_Swift()
// CLS_LOG_Swift("message!")
// CLS_LOG_Swift("message with parameter 1: %@ and 2: %@", ["First", "Second"])
func CLS_LOG_Swift(format: String = "",
    _ args:[CVarArgType] = [],
    file: String = __FILE__,
    function: String = __FUNCTION__,
    line: Int = __LINE__)
{
    let filename = NSURL(string:file)?.lastPathComponent?.componentsSeparatedByString(".").first

    #if DEBUG
        CLSNSLogv("\(filename).\(function) line \(line) $ \(format)", getVaList(args))
    #else
        CLSLogv("\(filename).\(function) line \(line) $ \(format)", getVaList(args))
    #endif

}

// CLS_LOG() output: -[ClassName methodName:] line 10 $
// CLS_LOG_Swift() output: ClassName.methodName line 10 $
_

そして、ここにいくつかのより多くの情報と私がこのコードを入れた実際のファイルの要点があります: https://Gist.github.com/DimaVartanian/a8aa73ba814a61f749c0

ご覧のとおり、元のマクロにかなり近く、クラスメソッドとインスタンスメソッドのどちらを呼び出しているかがわからず、配列に囲まれた形式引数リストを含める必要があるという点のみが異なります。両方とも、現在のところ回避策はないと考えているが、かなりマイナーな制限です。また、DEBUGがSwiftコンパイラフラグで定義されていることを確認する必要があります。通常のフラグから自動的に引き継がれることはありません。

21
Dima

Swift 3互換

Swiftプリプロセッサ-Swift Compiler - Custom FlagsBuild Settingsセクションに移動して-D DEBUGフラグを設定するために、コンパイラフラグを設定する必要があります。

enter image description here

func dLog(message: Any, filename: String = #file, function: String = #function, line: Int = #line) {
    #if DEBUG
         print("[\(filename.lastPathComponent):\(line)] \(function) - \(message)")
        #else
        CLSLogv("[\(filename.lastPathComponent):\(line)] \(function) - \(message)", getVaList([""]))
    #endif
}


 dLog(object)
3
Asdrubal

どうですか?

import Foundation
import Crashlytics

func CLSLog(_ format: String = "", _ args: CVarArg..., file: String = #file, function: String = #function, line: Int = #line) {
    let formatString: String!
    if let filename =  file.components(separatedBy: "/").last?.components(separatedBy: ".").first {
        formatString = "\(filename).\(function) line \(line) $ \(format)"
    } else {
        formatString = "\(file).\(function) line \(line) $ \(format)"
    }

    #if DEBUG
    CLSNSLogv(formatString, getVaList(args))
    #else
    CLSLogv(formatString, getVaList(args))
    #endif
}

その場合、配列は不要で、変数パラメータをリストするだけです

CLSLog("message")
CLSLog("message %@ %@", "one", "two")
1
Miha Hribar

Crashlyticsのログメッセージ用のSwift 3互換バージョン

func CLS_LOG_Swift(_ format: String = "", _ args: [CVarArg] = [], file: String = #file, function: String = #function, line: Int = #line) {

    let formatString: String!

    if let filename =  file.components(separatedBy: "/").last?.components(separatedBy: ".").first {

           formatString = "\(filename).\(function) line \(line) $ \(format)"

    }else{

           formatString = "\(file).\(function) line \(line) $ \(format)"
    }

    #if DEBUG
        CLSNSLogv(formatString, getVaList(args))
    #else
        CLSLogv(formatString, getVaList(args))
    #endif
}
1
Chetan Dobariya