NSAttributedString
개체가 사용자 지정 개체의 속성으로 있습니다. 이 사용자 지정 개체를 JSON 형식의 디스크에 저장해야합니다. 나중에이 JSON 데이터를 네트워크를 통해 Java 서버로 보내야합니다.
NSSAttributedString
개체의 -(NSString) string
메서드를 사용할 수 없습니다. 디스크와 서버의 특성 문자열을 다시 구성 할 수 있어야하기 때문입니다.코코아 : JSON에 NSAttributedString을 저장하는 방법
답변
NSAttributedString은 두 가지 속성이 있습니다
- 문자열을
- 속성의 배열은 "실행"
각 "실행"이 있습니다
- 정수 범위를 그 그것을 에 적용됨
- 키/값 attrib 사전 utes
enumerateAttributesInRange:options:usingBlock:
을 사용하여 JSON으로 표현하는 것은 매우 쉽습니다. 같은
뭔가 :
{
"string" : "Hello World",
"runs" : [
{
"range" : [0,3],
"attributes" : {
"font" : {
"name" : "Arial",
"size" : 12
}
}
},
{
"range" : [3,6],
"attributes" : {
"font" : {
"name" : "Arial",
"size" : 12
},
"color" : [255,0,0]
}
},
{
"range" : [9,2],
"attributes" : {
"font" : {
"name" : "Arial",
"size" : 12
}
}
}
]
}
편집 : 여기에 구현 한 예이다 :
// create a basic attributed string
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:@"Hello World" attributes:@{NSFontAttributeName: [NSFont fontWithName:@"Arial" size:12]}];
[attStr addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(3, 6)];
// build array of attribute runs
NSMutableArray *attributeRuns = [NSMutableArray array];
[attStr enumerateAttributesInRange:NSMakeRange(0, attStr.length) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
NSArray *rangeArray = @[[NSNumber numberWithUnsignedInteger:range.location],
[NSNumber numberWithUnsignedInteger:range.length]];
NSMutableDictionary *runAttributes = [NSMutableDictionary dictionary];
[attrs enumerateKeysAndObjectsUsingBlock:^(id attributeName, id attributeValue, BOOL *stop) {
if ([attributeName isEqual:NSFontAttributeName]) { // convert font values into a dictionary with the name and size
attributeName = @"font";
attributeValue = @{@"name": [(NSFont *)attributeValue displayName],
@"size": [NSNumber numberWithFloat:[(NSFont *)attributeValue pointSize]]};
} else if ([attributeName isEqualToString:NSForegroundColorAttributeName]) { // convert foreground colour values into an array with red/green/blue as a number from 0 to 255
attributeName = @"color";
attributeValue = @[[NSNumber numberWithInteger:([(NSColor *)attributeValue redComponent] * 255)],
[NSNumber numberWithInteger:([(NSColor *)attributeValue greenComponent] * 255)],
[NSNumber numberWithInteger:([(NSColor *)attributeValue blueComponent] * 255)]];
} else { // skip unknown attributes
NSLog(@"skipping unknown attribute %@", attributeName);
return;
}
[runAttributes setObject:attributeValue forKey:attributeName];
}];
// save the attributes (if there are any)
if (runAttributes.count == 0)
return;
[attributeRuns addObject:@{@"range": rangeArray,
@"attributes": runAttributes}];
}];
// build JSON output
NSDictionary *jsonOutput = @{@"string": attStr.string,
@"runs": attributeRuns};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonOutput options:NSJSONWritingPrettyPrinted error:NULL];
NSLog(@"%@", [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
exit(0);
예를 들어 설명해주세요. 나는 정말로 감사 할 것이다! –
나는 모든 가능한 열거 형에 대한 루프를 실행하는 것에 대해 생각하고있다. (나는 잘 모르겠다!). 내가 알았더라도, 이것이 어떻게 모든 경우에 나를 도울 수 있는지 잘 모르겠습니다! 내 말은, 나는 문자열의 다른 부분에 대해 다른 속성을 가질 수 있습니다! –
@ Marci-man'enumerateAttributesInRange : options : usingBlock :'은 루프를 실행하고 속성의 각 섹션에 대해 제공 한 블록을 실행합니다. 시연 할 답변을 업데이트하겠습니다. –
당신은 RTFFromRange로 시작하는 시도 할 수 : 문서에서
: RTF를 지원하는 OS X의 방법에 대한 정보를, ..., NSAttributedString은 애플리케이션 키트 추가 참조를 참조하십시오.
RTF는 자체 포함되어야합니다. RTFFromRange : NSData를 반환합니다. 아마도 인코딩의 문자 데이터가 NSString으로 변환하기 쉬워야한다고 생각합니다.
(죄송합니다. 그 방법은 MacOS X에서만 읽을 수 있습니다.)
iOS 7부터는 iOS 버전이 있습니다. http : //developer.apple.com/library/ios/documentation/uikit/reference/NSAttributedString_UIKit_Additions /Reference/Reference.html –
저는 RTF로 표현할 수없는 몇 가지 속성이 있다고 확신합니다. 그들이 무엇인지 잘 모르겠습니다. –
@ChrisDevereux Mac 용으로 개발 중입니다. OS X –
당신은 실제로 NSAttributedString
을 구문 분석하지 않고 XML로 NSAttributedString
를 변환하는 간단한 코드를 사용할 수 있습니다. 자세한 텍스트 출력을 허용 할 수 있다면 사람이 읽을 수있는 JSON의 대안이 될 수 있습니다.
NSAttributedString
으로 디코딩 할 때도 사용할 수 있습니다.
let data = NSMutableData()
let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
archiver.outputFormat = .XMLFormat_v1_0
textView.attributedText.encodeWithCoder(archiver)
archiver.finishEncoding()
let textAsString = NSString(data: data, encoding: NSUTF8StringEncoding)'
속성을 저장할 고유 한 형식을 정의 했습니까? 또는 바이너리 아카이브를 사용하고 싶습니까? – Wain
아마도 dataFromRange를 수행 한 다음 데이터를 Base64 인코딩으로 변환하는 것이 가장 간단 할 것입니다. 그러나 그것은 조금 지저분합니다. –
음, 확실하지 않습니다 ... 지금은 JSON 형식의 파일로 작성하여 네트워크를 통해 보내고 원래 형식으로 문자열을 재구성 할 수있는 한 무엇이든 열려 있습니다. JSON에서 문자열과 속성을 별도의 문자열로 저장하고 나중에 객체를 재구성하는 아이디어에 대해서도 열려 있습니다. –