2017-02-08 15 views
6

मैं एक पाठ एक API से आ रही के कुछ भागों रंग कर रहा हूँ (लगता ट्विटर पर के रूप में "@mention") NSAttributedString का उपयोग कर।NSAttributedString और emojis: पदों के साथ इस मुद्दे को और लंबाई

एपीआई मुझे पाठ और पाठ कर रहे हैं उल्लेख है कि के कुछ हिस्सों का प्रतिनिधित्व संस्थाओं (या लिंक, टैग, आदि) जो रंग का होना चाहिए की एक सरणी देता है।

लेकिन कभी कभी, रंगाई क्योंकि इमोजी ऑफसेट है।


उदाहरण के लिए, इस पाठ के साथ: "। कुछ पाठ @ericd @apero"

एपीआई देता है:

[ { " पाठ ":" ericd ", " लेन ": 6, " स्थिति ": 0 }, { "पाठ": "apero", "लेन": 6, "स्थिति": 18 } ]

जो मैं सफलतापूर्वक एक NSAttributedString से अनुवाद NSRange का उपयोग कर:

for m in entities.mentions { 
    let r = NSMakeRange(m.pos, m.len) 
    myAttributedString.addAttribute(NSForegroundColorAttributeName, value: someValue, range: r) 
} 

हम देखते हैं कि "pos": 18 सही है, यह वह जगह है जहां "@apero" शुरू होता है। रंगीन भागों "@ericd" और "@apero", के रूप में उम्मीद कर रहे हैं।

लेकिन जब इमोजी का कुछ विशिष्ट संयोजन पाठ में उपयोग किया जाता है, एपीआई NSATtributedString को अच्छी तरह से अनुवाद नहीं करता है, रंगाई ऑफसेट है:

"कुछ पाठ @ericd ✌ @apero।"

देता है:

[ { "पाठ": "ericd", "लेन": 6, "स्थिति": 0 }, { "पाठ": "apero", "लेन": 6, "स्थिति": 22 } ]

"pos": 22: एपीआई लेखक कहा गया है कि यह सही है, और मैं उनके नज़रिए को समझते हैं।

दुर्भाग्य से, NSAttributedString सहमत नहीं है, मेरे रंगाई बंद है:

enter image description here

दूसरा उल्लेख के लिए अंतिम अक्षर रंग नहीं कर रहे हैं (क्योंकि "स्थिति" क्योंकि इमोजी का बहुत छोटा है ?)।

जैसा कि आप पहले ही अनुमान लगा चुके हैं, मैं एपीआई व्यवहार के तरीके को किसी भी तरह से बदल नहीं सकता, मुझे क्लाइंट पक्ष पर अनुकूलित करना होगा।

इसके अलावा ... मुझे नहीं पता कि क्या करना है। क्या मुझे यह पता लगाने की कोशिश करनी चाहिए कि पाठ में किस तरह के इमोजी हैं और समस्याग्रस्त इमोजी होने पर उल्लेखों की स्थिति में मैन्युअल रूप से संशोधन करते हैं? लेकिन यह पता लगाने के मानदंड क्या होंगे कि इमोजी स्थिति को बदल देता है और कौन नहीं करता? और यह तय कैसे करें कि मुझे कितना ऑफ़सेट चाहिए? शायद समस्या NSAttributedString के कारण हुई है?

मैं समझता हूं कि यह अलग-अलग पात्रों के रूप में उनकी लंबाई की तुलना में बनाई गई भावनाओं की लंबाई से संबंधित है, लेकिन ... अच्छा ... मैं खो गया हूं (श्वास)।


ध्यान दें कि मैं एक समाधान this stuff के लिए इसी तरह लागू करने के लिए, क्योंकि मेरी एपीआई इस एक के साथ संगत है की कोशिश की है, लेकिन यह केवल आंशिक रूप से काम किया, कुछ देता है, इमोजी अभी भी अनुक्रमित तोड़ने गया:

enter image description here

उत्तर

9

एक स्विफ्ट String इसकी सामग्री पर विभिन्न "विचार" प्रदान करता है। एक अच्छा सिंहावलोकन स्विफ्ट ब्लॉग में "Strings in Swift 2" में दी गई है:

  • characters चरित्र मूल्यों, या बढ़ाया ग्रफीम समूहों का एक संग्रह है।
  • unicodeScalars यूनिकोड स्केलर मानों का संग्रह है।
  • utf8 यूटीएफ -8 कोड इकाइयों का संग्रह है।
  • utf16 यूटीएफ -16 कोड इकाइयों का संग्रह है।

के रूप में यह चर्चा में निकला, pos और len अपने एपीआई से यूनिकोड scalars दृश्य में सूचकांक कर रहे हैं।

दूसरी ओर, NSMutableAttributedString की addAttribute() विधि एक NSRange अर्थात रेंज एक NSString में इसी UTF-16 कोड अंक के सूचकांकों पर ले जाता है,।

String अलग विचारों के सूचकांकों के बीच "का अनुवाद" करने के लिए तरीके प्रदान (NSRange to Range<String.Index> तुलना):

let text = "@ericd Some text. ✌ @apero" 
let pos = 22 
let len = 6 

// Compute String.UnicodeScalarView indices for first and last position: 
let from32 = text.unicodeScalars.index(text.unicodeScalars.startIndex, offsetBy: pos) 
let to32 = text.unicodeScalars.index(from32, offsetBy: len) 

// Convert to String.UTF16View indices: 
let from16 = from32.samePosition(in: text.utf16) 
let to16 = to32.samePosition(in: text.utf16) 

// Convert to NSRange by computing the integer distances: 
let nsRange = NSRange(location: text.utf16.distance(from: text.utf16.startIndex, to: from16), 
         length: text.utf16.distance(from: from16, to: to16)) 

यह NSRange आप जिम्मेदार ठहराया स्ट्रिंग के लिए क्या जरूरत है:

let attrString = NSMutableAttributedString(string: text) 
attrString.addAttribute(NSForegroundColorAttributeName, 
         value: UIColor.red, 
         range: nsRange) 

स्विफ्ट 4 (एक्सकोड 9) के लिए अपडेट: एस में wift 4, मानक पुस्तकालय , स्विफ्ट के बीच परिवर्तित करने के लिए String पर्वतमाला और NSString पर्वतमाला तरीके प्रदान इसलिए गणना

let text = "@ericd Some text. ✌ @apero" 
let pos = 22 
let len = 6 

// Compute String.UnicodeScalarView indices for first and last position: 
let fromIdx = text.unicodeScalars.index(text.unicodeScalars.startIndex, offsetBy: pos) 
let toIdx = text.unicodeScalars.index(fromIdx, offsetBy: len) 

// Compute corresponding NSRange: 
let nsRange = NSRange(fromIdx..<toIdx, in: text) 
+1

दिलचस्प करने के लिए आसान बनाने! (जिस श्रेणी का मैं उपयोग कर रहा हूं वह पहले से ही एक एनएसआरेंज है, हालांकि, एक स्विफ्ट रेंज नहीं है)। मुझे इसका अध्ययन करने और परीक्षण चलाने के लिए कुछ समय चाहिए, देखें कि एपीआई की तुलना में यह कैसा व्यवहार करता है।धन्यवाद, जब संभव हो तो मैं प्रतिक्रिया दूंगा। – Moritz

+0

आपके उदाहरण में, पॉज़ 22 और लेन 6 का उपयोग करके मेरे एपीआई की तरह इस पाठ के लिए रिटर्न मिलता है, "@apero" केवल "@" के बाद शुरू होता है [पूरे उल्लेख के बजाए] [https://www.evernote.com/एल/AOznB6IhPzxJrbvva5Jxx24cyFv9MrhSqkI)। – Moritz

+0

@EricAya: लेकिन "@apero" से "@" स्थिति 21 पर है, 22 नहीं। या आप पात्रों की गणना कैसे करते हैं? –

संबंधित मुद्दे