카테고리 없음

[iOS] iOS 10 / Xcode 8의 장치에서 NSLog가 잘리는 것처럼 보입니까?

필살기쓰세요 2021. 2. 3. 08:59

임시 해결책은 단지 모든 재정

NSLOG

printf

글로벌 헤더 파일에.

#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);

-------------------
iOS 10 및 Xcode 8에서 Apple은 오래된

ASL

(Apple System Log)에서

Unified logging

.

NSLog

실제로 호출은 새

os_log

API에 위임됩니다 . (출처 :

https://developer.apple.com/reference/os/logging

) :

중대한

통합 로깅은 iOS 10.0 이상, macOS 10.12 이상, tvOS 10.0 이상 및 watchOS 3.0 이상에서 사용할 수 있으며 ASL (Apple System Logger) 및 Syslog API를 대체합니다. 역사적으로 로그 메시지는 /etc/system.log와 같은 디스크의 특정 위치에 기록되었습니다. 통합 로깅 시스템은 텍스트 기반 로그 파일에 쓰는 대신 메모리와 데이터 저장소에 메시지를 저장합니다.

중대한

시스템의 최대 메시지 길이보다 큰 로그 메시지 행은 로깅 시스템에 의해 저장 될 때 잘립니다. 로그 명령 줄 도구를 사용하여 실시간 활동 스트림을 볼 때 완전한 메시지가 표시됩니다. 그러나 스트리밍 로그 데이터는 비용이 많이 드는 작업입니다.

@Hot_Leaks (출처 :)에서 언급 한 바와 같이 "시스템의 최대 메시지 길이"제한은 SDK의 헤더에 형식화 된 변수에 대해 1024 자로 표시됩니다

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

버퍼 크기 제한이으로 하드 코딩 된 것 같기 때문에,

libsystem_trace.dylib

주위에 방법이 없지만 형식이 지정된 변수 (

%@

) 대신 문자열 리터럴을 인쇄 하거나 형식이 지정된 문자열 변수를 <1024 문자열로 분할합니다.

printf

디버거 (Xcode)가 프로세스의 출력 / 오류 스트림을 표시하기 때문에 디버깅 중에 작동하지만 장치 로그 자체로 전송되지는 않습니다. 즉, xfdai의 솔루션은 macOS의

Console

과 같은 다른 로그 응용 프로그램을 사용 하거나 디버깅되지 않은 응용 프로그램 (예 : 고객의 장치에서 실행되는 AppStore 응용 프로그램)에서 문제 가 발생할 때 도움이되지 않습니다 .


xfdai의 답변을 배포 된 애플리케이션으로 확장

배포 된 애플리케이션 / 디버그가 아닌 빌드에서는

NSLog

s 또는

printf

s 를 볼 수있는 방법이 없습니다 .장치 로그 (Xcode-> Window-> Devices, mac의 콘솔 앱 또는

deviceconsole

과 같은 타사 유틸리티를 사용하여 액세스 할 수 있음)에 직접 메시지를 인쇄하는 유일한 방법

os_log

API (

ASL

iOS 10 이후 사용 된 후속 유틸리티 )를 호출 하는 것입니다. ).다음 은 iOS 10

NSLog

에서 호출로 재정의하는 데 사용하는 전역 헤더 파일입니다

_os_log_internal

.

#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 */
                                                              

-------------------
iOS 10 전용 "기능"입니다. 대신 사용 :

printf("%s", [logString UTF8String]);

-------------------
이 방법을 사용할 수 있습니다. 800 자마다 분할합니다. 또는 설정할 수 있습니다. NSLOG 나는 1000 자마다 자른다 고 생각합니다. 문자열이 800 미만이면 간단한 NSLog를 사용합니다. 이것은 Json 긴 문자열에 유용하며 콘솔을 사용합니다. printf는 콘솔이 아닌 Xcode 디버그 창을 사용합니다.

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

-------------------
iOS 10 :

  1. printf() Xcode의 콘솔 내에서 작동하지만 장치의 콘솔 로그에서는 작동하지 않습니다.
  2. NSLog 두 곳 모두에서 잘립니다.

지금 제가하고있는 것은

NSLog

문자열을 줄로 나누고 각 줄을 개별적으로 로깅하는 것입니다.

- (void) logString: (NSString *) string
{
    for (NSString *line in [string componentsSeparatedByCharactersInSet: [NSCharacterSet newlineCharacterSet]])
        {
                NSLog(@"%@", line);
                    }
                    }
                    

이것은 콘솔에서 작동하지만 읽기가 쉽지 않습니다.-------------------
이것은 좋은 출력을 제공하지는 않지만 콘솔에서도 긴 로그에 필요한 모든 정보를 인쇄합니다.

func Log(_ logString: String?) {
    if logString?.isEmpty ?? false { return }
        NSLog("%@", logString!)
            Log(String(logString!.dropFirst(1024)))
            }
            

-------------------
@xfdai 대답에서 예쁜 기능과 줄을 추가하십시오.

날짜 포함



출처
https://stackoverflow.com/questions/39920159