Pourquoi la sortie de la console est-elle incomplète dans Xcode 8 / iOS 10?
Réponses
Trop de publicités?Dans iOS 10 & Xcode 8, Apple est passé de la bonne vieille ASL
(Pomme Journal Système) à un nouveau système d'enregistrement appelé Unified logging
. NSLog
des appels sont en fait de déléguer à nouveau os_log
de l'API. (source: https://developer.apple.com/reference/os/logging):
Important
Unifiée enregistrement est disponible dans iOS 10.0, et plus tard, macOS et 10.12 plus tard, tvOS 10.0, et plus tard, et watchOS 3.0 et versions ultérieures, et annule et remplace ASL (Apple Enregistreur du Système) et le Syslog Api. Historiquement, journal les messages ont été écrits à des endroits précis sur le disque, telles que /etc/system.journal. Le unifiée, système d'enregistrement stocke les messages dans la mémoire et dans une banque de données, plutôt que d'écrire un texte basé sur les fichiers de log.
Et
Important
Message du journal des lignes de plus que le système du maximum de la longueur du message est tronqué quand stockées par le système de journalisation. Messages complets sont visible lors de l'utilisation du journal d'outil de ligne de commande pour afficher un flux en direct de de l'activité. Gardez à l'esprit, cependant, que le streaming de données de journal est un activité coûteuse.
Le "système de la longueur maximale de la" limitation est révélé dans le SDK de l'en-tête de 1024 caractères formatée variables, comme le fait remarquer @Hot_Leaks (source: <os/log.h>
):
/*!
* @function os_log
*
* ...
*
* There is a physical cap of 1024 bytes per log line for dynamic content,
* such as %s and %@, that can be written to the persistence store.
* All content exceeding the limit will be truncated before it is
* written to disk.
*
* ...
*
*/
#define os_log(log, format, ...) os_log_with_type(log, OS_LOG_TYPE_DEFAULT, format, ##__VA_ARGS__)
Puisque la taille de la mémoire tampon limitation semble être codées en dur dans l' libsystem_trace.dylib
, je ne vois pas un moyen de contourner cela, mais pour imprimer une chaîne littérale au lieu de forme variable (%@
), ou de scission de la chaîne mise en forme des variables < 1024 cordes.
printf
pendant le débogage, depuis le débogueur (Xcode) montre le processus de sortie / erreur de cours d'eau, mais il ne sera pas envoyé à l'appareil de journal lui-même. Cela signifie que xfdai la solution ne sera pas vous aider lors de l'utilisation d'autres journaux des applications telles que macOS est Console
App, ou avec la question du jour sur la non-corrigés des applications (telles que l'AppStore l'application en cours d'exécution sur l'appareil du client).
L'extension de xfdai de réponse pour les applications déployées
Dans les applications déployées / non-debug, il n'y a pas moyen de voir soit NSLog
s ou printf
s.
La seule façon d'avoir des messages d'imprimer directement sur le périphérique de journal (qui peut être consulté à l'aide de Xcode -> Fenêtre -> Appareils, mac la Console de l'Application ou de la 3e partie des utilitaires tels que deviceconsole) appelle os_log
l'API (qui est le successeur de l' ASL
utilisé depuis iOS 10).
Voici un mondial de l'en-tête de fichier que j'utilise pour redéfinir NSLog
comme un appel à l' _os_log_internal
sur iOS 10:
#ifndef PrefixHeader_pch
#define PrefixHeader_pch
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
#import <os/object.h>
#import <os/activity.h>
/*
* System Versioning Preprocessor Macros
*/
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
// os_log is only supported when compiling with Xcode 8.
// Check if iOS version > 10 and the _os_log_internal symbol exists,
// load it dynamically and call it.
// Definitions extracted from #import <os/log.h>
#if OS_OBJECT_SWIFT3
OS_OBJECT_DECL_SWIFT(os_log);
#elif OS_OBJECT_USE_OBJC
OS_OBJECT_DECL(os_log);
#else
typedef struct os_log_s *os_log_t;
#endif /* OS_OBJECT_USE_OBJC */
extern struct os_log_s _os_log_default;
extern __attribute__((weak)) void _os_log_internal(void *dso, os_log_t log, int type, const char *message, ...);
// In iOS 10 NSLog only shows in device log when debugging from Xcode:
#define NSLog(FORMAT, ...) \
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {\
void(*ptr_os_log_internal)(void *, __strong os_log_t, int, const char *, ...) = _os_log_internal;\
if (ptr_os_log_internal != NULL) {\
_Pragma("clang diagnostic push")\
_Pragma("clang diagnostic error \"-Wformat\"")\
_os_log_internal(&__dso_handle, OS_OBJECT_GLOBAL_OBJECT(os_log_t, _os_log_default), 0x00, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);\
_Pragma("clang diagnostic pop")\
} else {\
NSLog(FORMAT, ##__VA_ARGS__);\
}\
} else {\
NSLog(FORMAT, ##__VA_ARGS__);\
}
#endif /* PrefixHeader_pch */
Vous pouvez utiliser cette méthode. Fractionner tous les 800 caractères. Ou peut être réglé. NSLOG je pense tronquer tous les 1000 caractères. Si string est inférieur à 800, un simple NSLog sera utilisé. Ceci est utile pour les chaînes longues Json et utilise la console. printf utilise la fenêtre de débogage Xcode et non la console.
-(void) JSLog:(NSString*)logString{
int stepLog = 800;
NSInteger strLen = [@([logString length]) integerValue];
NSInteger countInt = strLen / stepLog;
if (strLen > stepLog) {
for (int i=1; i <= countInt; i++) {
NSString *character = [logString substringWithRange:NSMakeRange((i*stepLog)-stepLog, stepLog)];
NSLog(@"%@", character);
}
NSString *character = [logString substringWithRange:NSMakeRange((countInt*stepLog), strLen-(countInt*stepLog))];
NSLog(@"%@", character);
} else {
NSLog(@"%@", logString);
}
}
Sur iOS 10:
-
printf()
fonctionne dans la console de Xcode mais pas dans le journal de la console du périphérique. -
NSLog
tronque aux deux endroits.
Ce que je fais pour l'instant est de scinder mes chaînes NSLog
en lignes et d'enregistrer chaque ligne individuellement.
- (void) logString: (NSString *) string
{
for (NSString *line in [string componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]])
{
NSLog(@"%@", line);
}
}
Cela fonctionne sur la console, mais n'est pas facile à lire.