파일에 NS 로그인하는 방법
모든 것을 쓰는 것이 가능합니까?NSLog
콘솔뿐만 아니라 파일로도?이것을 교체하지 않고 준비하고 싶습니다.NSLog
안으로someExternalFunctionForLogging
.
모두 교체하는 것은 정말 문제가 될 것입니다.NSLog
할 수 이 있습니까? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
옵션 1: ASL 사용
NSLog는 로그를 ASL(Apple 버전의 syslog) 및 콘솔로 출력합니다. 이는 아이폰 시뮬레이터를 사용할 때 이미 Mac의 파일에 쓰고 있음을 의미합니다.읽으려면 Console.app 응용프로그램을 열고 필터 필드에 응용프로그램의 이름을 입력합니다.아이폰 기기에서도 똑같이 하려면 ASL API를 사용하고 코딩을 해야 합니다.
옵션 2: 파일에 쓰기
시뮬레이터에서 실행 중인데 Console.app을 사용하지 않겠다고 가정해 보겠습니다.freopen:freopen의 파일을 사용하여 수 .
freopen([path cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
자세한 내용은 본 설명 및 샘플 프로젝트를 참조하십시오.
또는 매크로를 사용하여 사용자 지정 함수로 NSLog를 재정의할 수 있습니다.예를 들어 프로젝트에 이 클래스를 추가합니다.
// file Log.h
#define NSLog(args...) _Log(@"DEBUG ", __FILE__,__LINE__,__PRETTY_FUNCTION__,args);
@interface Log : NSObject
void _Log(NSString *prefix, const char *file, int lineNumber, const char *funcName, NSString *format,...);
@end
// file Log.m
#import "Log.h"
@implementation Log
void _Log(NSString *prefix, const char *file, int lineNumber, const char *funcName, NSString *format,...) {
va_list ap;
va_start (ap, format);
format = [format stringByAppendingString:@"\n"];
NSString *msg = [[NSString alloc] initWithFormat:[NSString stringWithFormat:@"%@",format] arguments:ap];
va_end (ap);
fprintf(stderr,"%s%50s:%3d - %s",[prefix UTF8String], funcName, lineNumber, [msg UTF8String]);
[msg release];
}
@end
그리고 당신의 프로젝트에 다음을 추가하여 그것을 광범위하게 수입합니다.<application>-Prefix.pch
:
#import "Log.h"
이제 NSLog에 대한 모든 호출은 기존 코드를 터치할 필요 없이 사용자 정의 기능으로 대체됩니다.그러나 위 기능은 콘솔용으로 인쇄하는 것에 불과합니다.파일 출력을 추가하려면 _Log: 위에 다음 함수를 추가합니다.
void append(NSString *msg){
// get path to Documents/somefile.txt
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"logfile.txt"];
// create if needed
if (![[NSFileManager defaultManager] fileExistsAtPath:path]){
fprintf(stderr,"Creating file at %s",[path UTF8String]);
[[NSData data] writeToFile:path atomically:YES];
}
// append
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:path];
[handle truncateFileAtOffset:[handle seekToEndOfFile]];
[handle writeData:[msg dataUsingEncoding:NSUTF8StringEncoding]];
[handle closeFile];
}
그리고 _Log 함수의 fprintf 아래에 이 행을 추가합니다.
append(msg);
파일 쓰기는 iPhone 장치에서도 작동하지만 파일은 장치 내부의 디렉토리에 생성되므로 코드를 추가하여 Mac으로 다시 보내거나 앱 내부의 보기에 표시하거나 iTunes를 사용하여 문서 디렉토리를 추가하지 않으면 액세스할 수 없습니다.
훨씬 더 쉬운 접근법이 있습니다.출력을 응용프로그램의 파일로 리디렉션하는 방법은 다음과 같습니다.Documents
를 뽑아 때할 수 있습니다.이것은 개발 스튜디오 밖에서 맥에서 플러그를 뽑아 앱을 테스트하고 싶을 때 유용할 수 있습니다.
ObjC:
- (void)redirectLogToDocuments
{
NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [allPaths objectAtIndex:0];
NSString *pathForLog = [documentsDirectory stringByAppendingPathComponent:@"yourFile.txt"];
freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}
스위프트:
// 1. Window > Devices and Simulators
// 2. Select the device
// 3. Select your app and click gear icon
// 4. Download container
// 5. Right click and "view contents"
// 6. Find "yourfile.log" under Downloads
//
// redirectLogToDocuments()
func redirectLogToDocuments() {
let allPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = allPaths.first!
let pathForLog = "\(documentsDirectory)/yourfile.log"
freopen(pathForLog.cString(using: String.Encoding.ascii)!, "a+", stdout)
}
한 후 한 된 은 를 은 에 의해 생성된 모든 출력NSLog
( (ObjC)는print
(Swift)는 지정된 파일로 전달됩니다.한을는법법는oOrganizer
프로그램의 및 저장, 의 Application Data
파일 시스템의 어딘가에, 단순히 찾아보기만 하는 것이 아니라Documents
폴더.
이 문제에 대한 가장 간단한 해결책을 찾았습니다.아이폰의 파일에 로그인합니다. NSLog 코드를 변경하거나 로거 자체를 변경할 필요가 없습니다. 이 4줄을 완료된 FinishLaunchingWithOptions에 추가하고 빌드 설정에서 라이브 릴리스가 활성화되지 않도록 하십시오(이를 위해 LOG2FILE 플래그를 추가했습니다).
#ifdef LOG2FILE
#if TARGET_IPHONE_SIMULATOR == 0
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
#endif
#endif
JaakL의 답변을 스위프트에게 번역하여 다른 사람도 필요로 하는 경우에는 여기에 올렸습니다.
이 코드를 앱의 어딘가에서 실행하면, 그 순간부터 파일에 출력된 NSLog()가 문서 디렉토리에 모두 저장됩니다.
let docDirectory: NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as NSString
let logpath = docDirectory.stringByAppendingPathComponent("YourFileName.txt")
freopen(logpath.cStringUsingEncoding(NSASCIIStringEncoding)!, "a+", stderr)
추가: Xcode로 로그 파일을 찾는 방법:
Xcode에서 간단히 로그에 액세스할 수 있습니다.Windows > Devices > 앱 선택 > InfoWheelButton > 다운로드 컨테이너finder로 파일 보기 : file에서 마우스 오른쪽 버튼 클릭 > package content > appdata > documents > 파일은
스위프트 4 버전
let docDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let logpathe = docDirectory.appendingPathComponent("Logerr.txt")
freopen(logpathe.path.cString(using: .ascii)!, "a+", stderr)
let logpatho = docDirectory.appendingPathComponent("Logout.txt")
freopen(logpatho.path.cString(using: .ascii)!, "a+", stdout)
스위프트에서 출력print()
에 있을 것입니다stdout
좋아요! 먼저 에반 뮬라우스키에게 감사를 표합니다.여기 제 해결책이 있습니다. 아마도 누군가에게 도움이 될 것입니다.
AppDelegate에서 기능 추가:
void logThis(NSString* Msg, ...)
{
NSArray* findingMachine = [Msg componentsSeparatedByString:@"%"];
NSString* outputString = [NSString stringWithString:[findingMachine objectAtIndex:0]];
va_list argptr;
va_start(argptr, Msg);
for(int i = 1; i < [findingMachine count]; i++) {
if ([[findingMachine objectAtIndex:i] hasPrefix:@"i"]||[[findingMachine objectAtIndex:i] hasPrefix:@"d"]) {
int argument = va_arg(argptr, int); /* next Arg */
outputString = [outputString stringByAppendingFormat:@"%i", argument];
NSRange range;
range.location = 0;
range.length = 1;
NSString* tmpStr = [[findingMachine objectAtIndex:i] stringByReplacingCharactersInRange:range withString:@""];
outputString = [outputString stringByAppendingString:tmpStr];
}
else if ([[findingMachine objectAtIndex:i] hasPrefix:@"@"]) {
id argument = va_arg(argptr, id);
// add argument and next patr of message
outputString = [outputString stringByAppendingFormat:@"%@", argument];
NSRange range;
range.location = 0;
range.length = 1;
NSString* tmpStr = [[findingMachine objectAtIndex:i] stringByReplacingCharactersInRange:range withString:@""];
outputString = [outputString stringByAppendingString:tmpStr];
}
else if ([[findingMachine objectAtIndex:i] hasPrefix:@"."]) {
double argument = va_arg(argptr, double);
// add argument and next patr of message
outputString = [outputString stringByAppendingFormat:@"%f", argument];
NSRange range;
range.location = 0;
range.length = 3;
NSString* tmpStr = [[findingMachine objectAtIndex:i] stringByReplacingCharactersInRange:range withString:@""];
outputString = [outputString stringByAppendingString:tmpStr];
}
else if ([[findingMachine objectAtIndex:i] hasPrefix:@"f"]) {
double argument = va_arg(argptr, double);
// add argument and next patr of message
outputString = [outputString stringByAppendingFormat:@"%f", argument];
NSRange range;
range.location = 0;
range.length = 1;
NSString* tmpStr = [[findingMachine objectAtIndex:i] stringByReplacingCharactersInRange:range withString:@""];
outputString = [outputString stringByAppendingString:tmpStr];
}
else {
outputString = [outputString stringByAppendingString:@"%"];
outputString = [outputString stringByAppendingString:[findingMachine objectAtIndex:i]];
}
}
va_end(argptr);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString * filePath = [[paths objectAtIndex:0]stringByAppendingPathComponent:@"logFile.txt"];
NSError* theError = nil;
NSString * fileString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&theError];
if (theError != nil||[fileString length]==0) {
fileString = [NSString stringWithString:@""];
}
fileString = [fileString stringByAppendingFormat:@"\n%@",outputString];
if(![fileString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&theError])
{
NSLog(@"Loging problem");
}
NSLog(@"%@",outputString);
}
그런 다음 "replace for all" NSLog -> log This를 사용합니다.이 코드는 제 앱에 맞게 수정되었습니다.다양한 요구에 맞게 확장할 수 있습니다.
도와주셔서 감사합니다.
이것이 제가 사용하는 것이고 잘 작동합니다.
http://parmanoir.com/Redirecting_NSLog_to_a_file
도움이 되길 바랍니다.
그냥 내용상으로 여기에 올릴게요.
- (BOOL)redirectNSLog {
// Create log file
[@"" writeToFile:@"/NSLog.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
id fileHandle = [NSFileHandle fileHandleForWritingAtPath:@"/NSLog.txt"];
if (!fileHandle) return NSLog(@"Opening log failed"), NO;
[fileHandle retain];
// Redirect stderr
int err = dup2([fileHandle fileDescriptor], STDERR_FILENO);
if (!err) return NSLog(@"Couldn't redirect stderr"), NO; return YES;
}
스위프트 2.0:
Appelegate did가 옵션을 사용하여 시작을 마쳤습니다.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var paths: Array = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory: String = paths[0]
let logPath: String = documentsDirectory.stringByAppendingString("/console.log")
if (isatty(STDERR_FILENO) == 0)
{
freopen(logPath, "a+", stderr)
freopen(logPath, "a+", stdin)
freopen(logPath, "a+", stdout)
}
print(logPath)
return true
}
console.log에 액세스하는 중:
Xcode Log Area에 로그 경로가 인쇄되면 경로를 선택하고 마우스 오른쪽 버튼을 누른 후 Finder에서 Services - Reaveal을 선택하고 file console.log를 엽니다.
Alvin George의 답변을 조금 참고했습니다.
로그 파일 크기를 제어하기 위해 "10세대 로그 파일" 솔루션을 구현하고 나중에 삭제하는 기능을 추가했습니다.
앱이 시작될 때마다 인덱스가 "0"인 새 로그 파일이 생성됩니다.나가는 파일의 이름이 이전보다 높은 인덱스로 바뀝니다.인덱스 "10"이 삭제됩니다.
시작할 때마다 최대 10세대에 이르는 새로운 로그 파일이 제공됩니다.
가장 우아한 방법은 아닐 수도 있지만 지난 몇 주 동안은 매우 효과적이었습니다. "맥을 끊는" 오랜 로깅이 필요했기 때문입니다.
// -----------------------------------------------------------------------------------------------------------
// redirectConsoleToFile()
//
// does two things
// 1) redirects "stderr", "stdin" and "stdout" to a logfile
// 2) deals with old/existing files to keep up to 10 generations of the logfiles
// tested with IOS 9.4 and Swift 2.2
func redirectConsoleToFile() {
// Instance of a private filemanager
let myFileManger = NSFileManager.defaultManager()
// the path of the documnts directory of the app
let documentDirectory: String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first!
// maximum number of logfiles
let maxNumberOfLogFiles: Int = 10
// look if the max number of files already exist
var logFilePath : String = documentDirectory.stringByAppendingString("/Console\(maxNumberOfLogFiles).log")
var FlagOldFileNoProblem: Bool = true
if myFileManger.fileExistsAtPath(logFilePath) == true {
// yes, max number of files reached, so delete the oldest one
do {
try myFileManger.removeItemAtPath(logFilePath)
} catch let error as NSError {
// something went wrong
print("ERROR deleting old logFile \(maxNumberOfLogFiles): \(error.description)")
FlagOldFileNoProblem = false
}
}
// test, if there was a problem with the old file
if FlagOldFileNoProblem == true {
// loop over all possible filenames
for i in 0 ..< maxNumberOfLogFiles {
// look, if an old file exists, if so, rename it with an index higher than before
logFilePath = documentDirectory.stringByAppendingString("/Console\((maxNumberOfLogFiles - 1) - i).log")
if myFileManger.fileExistsAtPath(logFilePath) == true {
// there is an old file
let logFilePathNew = documentDirectory.stringByAppendingString("/WayAndSeeConsole\(maxNumberOfLogFiles - i).log")
do {
// rename it
try myFileManger.moveItemAtPath(logFilePath, toPath: logFilePathNew)
} catch let error as NSError {
// something went wrong
print("ERROR renaming logFile: (i = \(i)), \(error.description)")
FlagOldFileNoProblem = false
}
}
}
}
// test, if there was a problem with the old files
if FlagOldFileNoProblem == true {
// No problem so far, so try to delete the old file
logFilePath = documentDirectory.stringByAppendingString("/Console0.log")
if myFileManger.fileExistsAtPath(logFilePath) == true {
// yes, it exists, so delete it
do {
try myFileManger.removeItemAtPath(logFilePath)
} catch let error as NSError {
// something went wrong
print("ERROR deleting old logFile 0: \(error.description)")
}
}
}
// even if there was a problem with the files so far, we redirect
logFilePath = documentDirectory.stringByAppendingString("/Console0.log")
if (isatty(STDIN_FILENO) == 0) {
freopen(logFilePath, "a+", stderr)
freopen(logFilePath, "a+", stdin)
freopen(logFilePath, "a+", stdout)
displayDebugString(DEBUG_Others, StringToAdd: "stderr, stdin, stdout redirected to \"\(logFilePath)\"")
} else {
displayDebugString(DEBUG_Others, StringToAdd: "stderr, stdin, stdout NOT redirected, STDIN_FILENO = \(STDIN_FILENO)")
}
}
// -----------------------------------------------------------------------------------------------------------
// cleanupOldConsoleFiles()
//
// delete all old consolfiles
func cleanupOldConsoleFiles() {
// Instance of a private filemanager
let myFileManger = NSFileManager.defaultManager()
// the path of the documnts directory of the app
let documentDirectory: String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first!
// maximum number of logfiles
let maxNumberOfLogFiles: Int = 10
// working string
var logFilePath: String = ""
// loop over all possible filenames
for i in 0 ... maxNumberOfLogFiles {
// look, if an old file exists, if so, rename it with an index higher than before
logFilePath = documentDirectory.stringByAppendingString("/Console\(i).log")
if myFileManger.fileExistsAtPath(logFilePath) == true {
// Yes, file exist, so delete it
do {
try myFileManger.removeItemAtPath(logFilePath)
} catch let error as NSError {
// something went wrong
print("ERROR deleting old logFile \"\(i)\": \(error.description)")
}
}
}
}
언급URL : https://stackoverflow.com/questions/7271528/how-to-nslog-into-a-file
'programing' 카테고리의 다른 글
RockyLinux 기반 맞춤형 MariaDB 도커 이미지 (0) | 2023.09.15 |
---|---|
프로세서의 워드 크기 확인 (0) | 2023.09.15 |
PowerShell 원격에서 "액세스 거부" 오류가 발생했습니다. (0) | 2023.09.10 |
PowerShell 스크립트를 통해 NuGet 설치 (0) | 2023.09.10 |
CSS에서 패딩 속성의 폭이나 높이가 변경되지 않도록 하려면 어떻게 해야 합니까? (0) | 2023.09.10 |