web-dev-qa-db-fra.com

Comment utiliser la journalisation Crashlytics dans Swift?

This article décrit comment utiliser la journalisation Crashlytics dans objective-c. Cependant, après avoir parcouru les étapes d'installation pour référencer correctement Crashlytics et Fabric dans mon projet, je ne semble pas avoir accès à cette méthode.

En regardant le fichier Crashlytics.h, je peux le voir défini à l'aide des drapeaux du compilateur:

#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

Ce bloc semble simplement envelopper les fonctions CLSNLog et CLSLog selon l'indicateur du compilateur.

Donc, pensant que j'allais directement à la source, j'ai essayé de référencer CLSLog directement à partir d'un fichier Swift. Toujours pas de chance:

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)
}

Les deux dernières lignes de la fonction Journal génèrent l'erreur, Use of unresolved identifier. Les rapports de crash de Crashlytics fonctionnent très bien, à l'exception de la fonction de journalisation. Selon ceci article, la prise en charge de la journalisation pour Swift a été implémentée.

En ce qui concerne les versions, j'utilise la dernière version de Fabric/Crashlytics (version de décembre, au moment de cet article).

(Note intéressante, je peux voir/utiliser CLSLogv()...)

Quelqu'un connaît-il la bonne façon d'incorporer CLS_LOG À utiliser dans un projet Swift?

37
Albert Bori

Vous devez créer un pont intermédiaire comme celui-ci:

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"

Ensuite, vous pouvez simplement ajouter cela à votre fonction Log:

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

Cela vous donnera la journalisation Crashlytics et NSLogging pendant que vous déboguez.

10
Porter Hoskins

Mike de Crashlytics ici.

Pour utiliser la journalisation personnalisée dans Swift, utilisez simplement CLSLogv ou CLSNSLogv. Vous devez créer un tableau, puis appeler la fonction getVaList sur ce tableau.

Voici un extrait:

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

Pour CLSNSLogv:

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

Voici ma version adaptée de la réponse de Dima. Je n'ai pas besoin des arguments, car vous pouvez faire tout le formatage dans la chaîne Swift que vous passez.

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
}

Et vous l'utiliseriez comme ceci:

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

MODIFIER : mis à jour vers Swift 3.1

28
ian

J'avais besoin de quelque chose de similaire à CLS_LOG() dans Swift qui imprimait des informations contextuelles sur l'emplacement de l'appel. Normalement, cela ne serait pas possible sans les directives du préprocesseur mais j'ai découvert comment reproduire ce comportement assez étroitement dans Swift ici: https://developer.Apple.com/Swift/blog/?id=15

Les identifiants dont nous avons besoin (#file, #function, #line) Affichent des informations sur l'appelant si vous les définissez comme valeurs par défaut dans une liste d'arguments.

Remarque: Si vous enregistrez des erreurs pouvant contenir des symboles %, Telles que des chaînes de requête réseau, cela peut se bloquer. Vous devrez d'abord joindre la chaîne (par exemple let string = "\(filename).\(function) line \(line) $ \(message)")

Version Swift 3 (remarque: il s'agit d'une fonction globale, elle doit donc être placée en dehors de toute définition de structure ou de classe):

/// 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
}

Version 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 $

Et voici un Gist avec plus d'informations et le fichier réel dans lequel j'ai mis ce code: https://Gist.github.com/DimaVartanian/a8aa73ba814a61f749c

Comme vous pouvez le voir, il est assez proche de la macro d'origine et ne diffère que par le fait que vous ne pouvez pas voir si vous appelez une méthode de classe ou une méthode d'instance, et que vous devez inclure votre liste d'arguments de format dans un tableau. Les deux sont des limites, je crois qu'il n'y a pas de solution pour le moment, mais plutôt mineures. Vous devez également vous assurer que DEBUG est défini dans vos indicateurs de compilateur Swift. Il ne se reporte pas automatiquement de vos indicateurs réguliers.

21
Dima

Compatible avec Swift 3

Vous devrez configurer un indicateur de compilation pour utiliser le Swift préprocesseur - allez dans le Swift Compiler - Custom Flags section de Build Settings pour configurer un -D DEBUG drapeau

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

Et comme ça?

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
}

Pas besoin du tableau alors, listez simplement les paramètres variadiques

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

Version compatible Swift 3 pour le message de journal dans Crashlytics

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