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?
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.
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"]))
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
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.
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
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)
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")
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
}