Как использовать запись Crashlytics в Swift?
В этой статье описывается использование журнала Crashlytics в objective-c. Тем не менее, после прохождения шагов установки для правильной ссылки на 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
в зависимости от флага компилятора.
Итак, думая, что я просто пойду прямо к источнику, я попытался ссылаться на 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 вызывают ошибку, Use of unresolved identifier
. Отчеты Crashlytics crash работают очень хорошо, за исключением функции ведения журнала. Согласно этой, была реализована поддержка ведения журнала для Swift.
Что касается версий, я использую последнюю версию Fabric/Crashlytics (декабрьская версия на момент публикации).
(Интересно отметить, что я вижу/использую CLSLogv()
...)
Кто-нибудь знает правильный способ включить CLS_LOG
для использования в проекте Swift?
Ответы
Ответ 1
Вам нужно создать промежуточный мост следующим образом:
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 во время отладки.
Ответ 2
Майк из Crashlytics здесь.
Чтобы использовать пользовательский журнал в Swift, используйте CLSLogv или CLSNSLogv. Вам нужно создать массив, а затем вызвать функцию getVaList в этом массиве.
Вот фрагмент:
CLSLogv("Log something %d %d %@", getVaList([1, 2, "three"]))
Для CLSNSLogv:
CLSNSLogv("hello %@", getVaList(["goodbye"]))
Ответ 3
Мне нужно что-то похожее на CLS_LOG()
в Swift, которое распечатало контекстуальную информацию о местонахождении вызова. Обычно это было бы невозможно без предпроцессорных директив, но я узнал, как скопировать это поведение довольно близко в Swift здесь:
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. Он не переносится с ваших обычных флагов автоматически.
Ответ 4
Вот моя адаптированная версия (от Димы). Мне не нужны аргументы, так как вы можете сделать все форматирование в строке Swift, которую вы передаете.
func DebugLog(_ message: String,
file: StaticString = #file,
function: StaticString = #function,
line: Int = #line)
{
let output: String
if let filename = URL(string: String(describing: file))?.lastPathComponent.components(separatedBy: ".").first
{
output = "\(filename).\(function) line \(line) $ \(message)"
}
else
{
output = "\(file).\(function) line \(line) $ \(message)"
}
#if 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
Ответ 5
Совместимость с Swift 3
Вам нужно настроить флаг компилятора для использования препроцессора Swift - перейдите в раздел Swift Compiler - Custom Flags
Build Settings
, чтобы установить флаг -D DEBUG
![введите описание изображения здесь]()
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)
Ответ 6
Swift 3 совместимая версия для сообщения журнала в 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
}
Ответ 7
Любой, кто хочет зарегистрировать ошибку usin Crashlytics, может использовать приведенный ниже код и его работу отлично для меня:)
Crashlytics.sharedInstance().recordError(error)
ошибка - это объект NSERROR, который содержит ошибку, возникшую при некотором действии