我需要在nstextview中的所选文本中添加自定义属性。因此,我可以通过获取属性字符串作为选择,向其添加自定义属性,然后用我的新属性字符串替换选择。

因此,现在我将文本视图的属性字符串称为NSDATA,并将其写入文件。稍后,当我打开该文件并将其还原到文本视图时,我的自定义属性消失了!为我的自定义属性制定了整个方案后,我发现自定义属性并未为您保存。在这里查看重要说明: http://developer.apple.com/mac/library/documentation/cocoa/conceptual/conceptual/attribedstrings/tasks/rtfandattrstrings.html

因此,我不知道如何使用此自定义属性保存和还原文档。有帮助吗?

有帮助吗?

解决方案

保存的正常方式 NSAttributedString 是使用RTF,RTF数据是 -dataFromRange:documentAttributes:error: 的方法 NSAttributedString 生成。

但是,RTF格式不支持自定义属性。相反,您应该使用 NSCoding 存档您的属性字符串的协议,该字符串将保留自定义属性:

//asssume attributedString is your NSAttributedString
//encode the string as NSData
NSData* stringData = [NSKeyedArchiver archivedDataWithRootObject:attributedString];
[stringData writeToFile:pathToFile atomically:YES];

//read the data back in and decode the string
NSData* newStringData = [NSData dataWithContentsOfFile:pathToFile];
NSAttributedString* newString = [NSKeyedUnarchiver unarchiveObjectWithData:newStringData];

其他提示

有一种方法可以使用可可将自定义属性保存到RTF。它依赖于RTF是文本格式的事实,因此即使您不知道RTF的所有规则,也没有自定义RTF读取器/作者,也可以作为字符串操纵。我在写作和阅读时概述了下面的过程后处理RTF,我亲自使用了此技术。要小心的一件事是,您插入RTF的文本仅使用7位ASCII,并且不使用UNESCAPEL CONTROL字符,其中包括“ {}”。

您将如何编码数据:

NSData *GetRtfFromAttributedString(NSAttributedString *text)
{
    NSData *rtfData = nil;
    NSMutableString *rtfString = nil;
    NSString *customData = nil, *encodedData = nil;
    NSRange range;
    NSUInteger dataLocation;

// Convert the attributed string to RTF
    if ((rtfData = [text RTFFromRange:NSMakeRange(0, [text length]) documentAttributes:nil]) == nil)
        return(nil);

// Find and encode your custom attributes here. In this example the data is a string and there's at most one of them
    if ((customData = [text attribute:@"MyCustomData" atIndex:0 effectiveRange:&range]) == nil)
        return(rtfData); // No custom data, return RTF as is
    dataLocation = range.location;

// Get a string representation of the RTF
    rtfString = [[NSMutableString alloc] initWithData:rtfData encoding:NSASCIIStringEncoding];

// Find the anchor where we'll put our data, namely just before the first paragraph property reset
    range = [rtfString rangeOfString:@"\\pard" options:NSLiteralSearch];
    if (range.location == NSNotFound)
        {
        NSLog(@"Custom data dropped; RTF has no paragraph properties");
        [rtfString release];
        return(rtfData);
        }

// Insert the starred group containing the custom data and its location
    encodedData = [NSString stringWithFormat:@"{\\*\\my_custom_keyword %d,%@}\n", dataLocation, customData];
    [rtfString insertString:encodedData atIndex:range.location];

// Convert the amended RTF back to a data object    
    rtfData = [rtfString dataUsingEncoding:NSASCIIStringEncoding];
    [rtfString release];
    return(rtfData);
}

该技术之所以起作用,是因为所有兼容的RTF读者都会忽略他们不认识的关键字的“星级群体”。因此,您要确保您的控制词不会被任何其他读者识别,因此请使用可能是唯一的东西,例如您的公司或产品名称的前缀。如果您的数据很复杂或二进制,或者可能包含您不想逃脱的非法RTF字符,请在Base64中对其进行编码。确保在关键字之后放置一个空间。

同样,在阅读RTF时,您可以搜索控制单词,提取数据并还原属性。此例程作为参数采用属性字符串及其创建的RTF。

void RestoreCustomAttributes(NSMutableAttributedString *text, NSData *rtfData)
{
    NSString *rtfString = [[NSString alloc] initWithData:rtfData encoding:NSASCIIStringEncoding];
    NSArray *components = nil;
    NSRange range, endRange;

// Find the custom data and its end
    range = [rtfString rangeOfString:@"{\\*\\my_custom_keyword " options:NSLiteralSearch];
    if (range.location == NSNotFound)
        {
        [rtfString release];
        return;
        }
    range.location += range.length;

    endRange = [rtfString rangeOfString:@"}" options:NSLiteralSearch
        range:NSMakeRange(range.location, [rtfString length] - endRange.location)];
    if (endRange.location == NSNotFound)
        {
        [rtfString release];
        return;
        }

// Get the location and the string data, which are separated by a comma
    range.length = endRange.location - range.location;
    components = [[rtfString substringWithRange:range] componentsSeparatedByString:@","];
    [rtfString release];

// Assign the custom data back to the attributed string. You should do range checking here (omitted for clarity)
    [text addAttribute:@"MyCustomData" value:[components objectAtIndex:1]
        range:NSMakeRange([[components objectAtIndex:0] integerValue], 1)];
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top