2014-03-24 2 views
4

NSAttributedString 개체가 사용자 지정 개체의 속성으로 있습니다. 이 사용자 지정 개체를 JSON 형식의 디스크에 저장해야합니다. 나중에이 JSON 데이터를 네트워크를 통해 Java 서버로 보내야합니다.
NSSAttributedString 개체의 -(NSString) string 메서드를 사용할 수 없습니다. 디스크와 서버의 특성 문자열을 다시 구성 할 수 있어야하기 때문입니다.코코아 : JSON에 NSAttributedString을 저장하는 방법

+2

속성을 저장할 고유 한 형식을 정의 했습니까? 또는 바이너리 아카이브를 사용하고 싶습니까? – Wain

+0

아마도 dataFromRange를 수행 한 다음 데이터를 Base64 인코딩으로 변환하는 것이 가장 간단 할 것입니다. 그러나 그것은 조금 지저분합니다. –

+0

음, 확실하지 않습니다 ... 지금은 JSON 형식의 파일로 작성하여 네트워크를 통해 보내고 원래 형식으로 문자열을 재구성 할 수있는 한 무엇이든 열려 있습니다. JSON에서 문자열과 속성을 별도의 문자열로 저장하고 나중에 객체를 재구성하는 아이디어에 대해서도 열려 있습니다. –

답변

10

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); 
+0

예를 들어 설명해주세요. 나는 정말로 감사 할 것이다! –

+0

나는 모든 가능한 열거 형에 대한 루프를 실행하는 것에 대해 생각하고있다. (나는 잘 모르겠다!). 내가 알았더라도, 이것이 어떻게 모든 경우에 나를 도울 수 있는지 잘 모르겠습니다! 내 말은, 나는 문자열의 다른 부분에 대해 다른 속성을 가질 수 있습니다! –

+0

@ Marci-man'enumerateAttributesInRange : options : usingBlock :'은 루프를 실행하고 속성의 각 섹션에 대해 제공 한 블록을 실행합니다. 시연 할 답변을 업데이트하겠습니다. –

2

당신은 RTFFromRange로 시작하는 시도 할 수 : 문서에서

: RTF를 지원하는 OS X의 방법에 대한 정보를, ..., NSAttributedString은 애플리케이션 키트 추가 참조를 참조하십시오.

RTF는 자체 포함되어야합니다. RTFFromRange : NSData를 반환합니다. 아마도 인코딩의 문자 데이터가 NSString으로 변환하기 쉬워야한다고 생각합니다.

(죄송합니다. 그 방법은 MacOS X에서만 읽을 수 있습니다.)

+0

iOS 7부터는 iOS 버전이 있습니다. http : //developer.apple.com/library/ios/documentation/uikit/reference/NSAttributedString_UIKit_Additions /Reference/Reference.html –

+0

저는 RTF로 표현할 수없는 몇 가지 속성이 있다고 확신합니다. 그들이 무엇인지 잘 모르겠습니다. –

+0

@ChrisDevereux Mac 용으로 개발 중입니다. OS X –

2

당신은 실제로 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)'