假设您有一个 Cocoa 应用程序的代码,它通过 NSlogs 和 printfs 将自己的消息记录到控制台输出。我的目标是将所有这些输出重定向到 NSView 中的单独 NSWindow 中。
我怎样才能以某种方式实现这一目标
- 最小化要重写的代码量
- 可以恢复
- 最大限度地重用书面代码
(通常的软件工程指南)?
假设您有一个 Cocoa 应用程序的代码,它通过 NSlogs 和 printfs 将自己的消息记录到控制台输出。我的目标是将所有这些输出重定向到 NSView 中的单独 NSWindow 中。
我怎样才能以某种方式实现这一目标
(通常的软件工程指南)?
Soon after your program starts use the dup(2) call to make duplicate File Descriptors for fd 1 (stdout) and 2 (stderr). Save the returned values for later.
Call close(2) on FD 1 and FD 2.
Call openpty(2) twice. The first master returned should be FD 1 (because it is the first avaiable FD), and the second master should be 2. Save the two slave FDs for later. Don't worry about saving the name parameter. Now whenever your program printf(2) to stdout, or NSLogs to stderr the data will be written to your slave FDs.
Now you must choose wether you want to poll the slave FDs or setup a signal when there is data to be read.
For polling use an NSTimer. In your timer use select(2) on your two slave FDs to see if they have data. If they do read(2) it and then output it to your window. You can also get the two slave FDs to use non blocking IO (use fcntl(2) to F_SETFL the slave FDs to O_NONBLOCK). Then you don't need select(2), you just read(2) and it will return zero if there is nothing to read.
For signaling, use fcntl(2) to F_SETFL the slave FDs to O_ASYNC. Then use signal(3) to install a signal handler for SIGIO. When your signal handler is called use one of the two methods I describe in the polling section.
If at run time you want to discard all these changes and set everything back to normal do this:
Call close(2) on FD 1, and FD 2.
Call dup(2) on the two FDs saved from step 1 in the first section, above. Do the dup(2) in the correct order so stdout uses FD 1 and stderr uses FD 2.
Now anything written to stdout and stderr will go to the original FDs.
如何编写自己的日志方法,将日志消息通知某些控制器(以便它可以将其放入您的(NSTextView?)视图中,然后依次调用 NSLog()?
这是我想出的解决方案:
readInBackgroundAndNotify
),它封装了一个 A 对象,并提供了一些方法,通过使用from读取文件(包含所有日志记录)将字符串发送到 A(将其附加到其 NSTextView)NSFileHandle
。当收到通知时,它会调用附加方法。它也有一种启动文件日志记录的方法,该方法用于freopen(3)
将某些流(stderr 和 stdout atm)重定向到附加模式的文件。该解决方案是考虑到 Joshua Nozzi 的答案和 tlindner 的答案而创建的,并将它们结合起来。我有并封装了尊重问题中三个请求的解决方案(我只需要添加一行代码,我可以轻松恢复,我也可以在其他应用程序中使用这个解决方案)。我注意到有时以这种方式封装 NSWindowController 可能是错误的(而所有其他的都由某个超级控制器管理)。
我最终选择了文件解决方案,因为它很容易实现,并且比 tlindner 的解决方案更像 Cocoa。它还提供了保留在磁盘上的日志文件的机会。但是当然我可能错过了一些东西,请在评论中指出我^^