forzar - como cerrar pestañas abiertas en iphone
Detectando si la aplicación de iOS se ejecuta en el depurador (7)
Configuré mi aplicación para enviar salida de depuración a la consola o un archivo de registro. Ahora, me gustaría decidir con el código si
- se ejecuta en el depurador (o simulador) y tiene una ventana de consola en la que me gustaría leer el resultado directamente o si
- no hay ventana de consola y, por lo tanto, la salida debe redirigirse a un archivo.
¿Hay alguna manera de determinar si la aplicación se ejecuta en el depurador?
¿Por qué no usar el bloque de compilación condicional en Swift?
#if DEBUG
// Do something.
#endif
¿Alguna objeción?
Puede definir si desea una constante de tiempo de ejecución
#if DEBUG
public let IS_RUNNING_IN_DEBUGGER: Bool = true
#else
public let IS_RUNNING_IN_DEBUGGER: Bool = false
#endif
El mismo enfoque se puede usar en Objc y más.
Es posible indicar al depurador que establezca variables de entorno cuando inicia un proceso que está por depurar. Esto se puede hacer en Xcode yendo a la opción de menú Producto-> Editar esquema. Luego, bajo la pestaña Argumentos del esquema de Depuración, agregue una nueva variable de entorno. La variable debe llamarse "depurador" con el valor "verdadero". A continuación, se puede utilizar el siguiente fragmento de código para determinar si el depurador inició su proceso:
NSDictionary* env = [NSProcessInfo processInfo].environment;
if ([env[@"debugger"] isEqual:@"true"]) {
NSLog(@"debugger yes");
}
else {
NSLog(@"debugger no");
}
Hay una función de Apple para detectar si un programa se está depurando en el Technical Q & A 1361 ( entrada en la biblioteca Mac y entrada en la biblioteca iOS , son idénticas).
Código de la sección de preguntas y respuestas técnicas:
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
static bool AmIBeingDebugged(void)
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
{
int junk;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we''re looking for information about a specific process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
// Call sysctl.
size = sizeof(info);
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
assert(junk == 0);
// We''re being debugged if the P_TRACED flag is set.
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}
También preste atención a esta nota al final de la sesión de preguntas y respuestas:
Importante: Debido a que la definición de la estructura
kinfo_proc
(en<sys/sysctl.h>
) está condicionada por__APPLE_API_UNSTABLE
, debe restringir el uso del código anterior a la compilación de depuración de su programa.
La solución más simple en realidad es
_isDebugging = isatty(STDERR_FILENO);
No es exactamente lo mismo que decir si la aplicación se está ejecutando en el depurador, pero lo suficientemente bueno (¿incluso mejor?) Para determinar si el registro debe escribirse en el disco.
Para mí, esta pieza de código rápido funciona perfectamente:
func isDebuggerAttached() -> Bool {
return getppid() != 1
}
Siempre es bueno tener diferentes soluciones, así que aquí están mis dos centavos:
La idea es comprobar el NSLog
stderr (aquí es donde se imprime NSLog
). Esta solución ha estado funcionando confiablemente desde al menos iOS 4 y sigue haciéndolo en iOS 9, tanto en el simulador como en el dispositivo.
#import <sys/ioctl.h>
#import <sys/param.h>
#if TARGET_IPHONE_SIMULATOR
#import <sys/conf.h>
#else
// Not sure why <sys/conf.h> is missing on the iPhoneOS.platform.
// It''s there on iPhoneSimulator.platform, though. We need it for D_DISK, only:
#if ! defined(D_DISK)
#define D_DISK 2
#endif
#endif
BOOL isDebuggerAttatchedToConsole(void)
{
// We use the type of the stderr file descriptor
// to guess if a debugger is attached.
int fd = STDERR_FILENO;
// is the file handle open?
if (fcntl(fd, F_GETFD, 0) < 0) {
return NO;
}
// get the path of stderr''s file handle
char buf[MAXPATHLEN + 1];
if (fcntl(fd, F_GETPATH, buf ) >= 0) {
if (strcmp(buf, "/dev/null") == 0)
return NO;
if (strncmp(buf, "/dev/tty", 8) == 0)
return YES;
}
// On the device, without attached Xcode, the type is D_DISK (otherwise it''s D_TTY)
int type;
if (ioctl(fd, FIODTYPE, &type) < 0) {
return NO;
}
return type != D_DISK;
}
Suelo buscar una solución mucho más simple; es el binario compilado con optimizaciones?
Una versión de depuración no está optimizada y los registros son agradables. Una versión de lanzamiento debería tener optimizaciones y no tantos registros. Puede verificar esto con el símbolo __OPTIMIZE__
.
Para el registro utilizo esta configuración para logg- funciones :
#ifdef __OPTIMIZE__
#define CWLog(...)
#define CWLogDebug(...)
#define CWLogInfo(...)
#else
#define CWLog(...) NSLog(__VA_ARGS__)
#define CWLogDebug( s, ... ) NSLog( @"DEBUG <%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#ifndef LOG_INFO
#define CWLogInfo(...)
#else
#define CWLogInfo( s, ... ) NSLog( @"INFO <%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#endif
#endif
#define CWLogWarning( s, ... ) NSLog( @"WARNING <%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#define CWLogError( s, ... ) NSLog( @"ERROR <%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )