2014-03-24 86 views
4

我有一個NSAttributedString對象作爲自定義對象的屬性。我需要將此自定義對象保存到磁盤中,格式爲JSON格式。後來我需要通過網絡將這個JSON數據發送到Java服務器。
我無法使用NSSAttributedString對象的-(NSString) string方法,因爲我需要能夠從磁盤和服務器上重建屬性字符串。可可:如何將NSAttributedString保存爲JSON

+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:

從文檔:有關Mac OS X的方法支持RTF信息,......,看到NSAttributedString應用開發包附加參考。

RTF應該是自包含的。 RTFFromRange:返回NSData;我認爲它在某些編碼中可能的字符數據應該很容易轉換爲NSString。

(對不起,剛剛閱讀的方法只是MacOS X)。

+0

從iOS 7開始,有一個iOS版本:http:// https://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)' 
相關問題