开发者

Set line-terminator string in NSDocument?

(This question has been rewritten from an issue with NSTextView following some further research)

UPDATE: You can download a very basic project that displays the issue here:

http://w3style.co.uk/~d11wtq/DocumentApp.tar.gz

(Do a grep -c "\r" file.txt on the file you save to get a line count where \r occurs... repeat for \n).

I've realised all files created by NSDocument have \r is line endings, not the standard \n, even though the NSData my document subclass returns does not contain \r, it only contains \n. Is there a way to configure this?

I thought Macs used UNIX line endings these days, so it seems weird that AppKit is still using the antiquated Mac endings. Weirder is that NSDocument asks for NSData, then rather unkindly corrupts that NSData by transforming the line endings.

The switch to \r is happening after producing NSData, so NSDocument itself is doing some replacements on the bytes:

 const char *bytes = [data bytes];
 int i, len;
 for (i = 0, len = [data length]; i < len; ++i) {
  NSLog(@"byte %d = %02x", i, bytes[i]);
 }

Outputs (note 0a is the hex value of \n):

> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 0 = 66
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 1 = 6f
> 2010-12-17 12:45:59.076
> MojiBaker[74929:a0f] byte 2 = 6f
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 3 = 0a
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 4 = 62
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 5 = 61
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 6 = 72
> 2010-12-17 12:45:59.077
> MojiBaker[74929:a0f] byte 7 = 0a

If NSDocument is going to ask for NSData then it should respect that and not modify it.

Here's the full code from the method: -dataOfType:error: method in my document:

    -(NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
 NSString *string = [textView string];

 // DEBUG CODE...
 NSArray *unixLines = [string componentsSeparatedByString:@"\n"];
 NSArray *windowsLines = [string componentsSeparatedByString:@"\r\n"];
 NSArray *macLines = [string componentsSeparatedByString:@"\r"];

 NSLog(@"TextView has %d LF, %d CRLF, %d CR", [unixLines coun开发者_如何转开发t] - 1, [windowsLines count] - 1, [macLines count] - 1);

 NSData *data = [NSData dataWithBytes:[string cStringUsingEncoding:NSUTF8StringEncoding]
          length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];

 const char *bytes = [data bytes];
 int i, len;
 for (i = 0, len = [data length]; i < len; ++i) {
  NSLog(@"byte %d = %02x", i, bytes[i]);
 }

 if (data != nil) {
  [textView breakUndoCoalescing];
 }

 return data;
}


NSDocument doesn’t care about line termination; it’s a semi-abstract class, designed to be subclassed. By itself it imposes nothing on a file format.

It’s the particular implementation of an NSDocument subclass - one that happens to read and write plain text - that will care about line termination characters.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜