সুইফট রেঞ্জ থেকে এনএসরেঞ্জ?


175

সমস্যা: আমি যখন রেফ ব্যবহার করে এমন একটি সুইফ্ট স্ট্রিং ব্যবহার করছি তখন এনএসএট্রিবিউটেড স্ট্রিং একটি এনএসরেঞ্জ নেয়

let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
    }
})

নিম্নলিখিত ত্রুটি উত্পাদন করে:

ত্রুটি: 'রেঞ্জ' 'NSRange' বৈশিষ্ট্যযুক্ত স্ট্রিং.এডিডিএট্রিবিউট (এনএসফোরগ্রাউন্ড কালারঅ্যাট্রিবিউটনেম, মান: এনএসকলার.রেডক্লোর (), ব্যাপ্তি: স্ট্রিংরেঞ্জ) এ রূপান্তরযোগ্য নয়)


4
সম্ভাব্য সদৃশ বিন্যাস <String.Index> এ NSRange
Suhaib

2
@ সুহাইব এটি অন্য পথে চলছে।
জিওফ 26'19

উত্তর:


262

সুইফট Stringরেঞ্জ এবং NSStringরেঞ্জগুলি "সামঞ্জস্যপূর্ণ" নয়। উদাহরণস্বরূপ, like এর মতো ইমোজিগুলি একটি সুইফ্ট চরিত্র হিসাবে গণনা করা হয়, তবে দুটি NSString চরিত্র হিসাবে (একটি তথাকথিত ইউটিএফ -16 সারোগেট জুটি)।

সুতরাং আপনার প্রস্তাবিত সমাধানটিতে স্ট্রিংতে এই জাতীয় অক্ষর থাকলে অপ্রত্যাশিত ফলাফল পাওয়া যাবে। উদাহরণ:

let text = "😄😄😄Long paragraph saying!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
    let start = distance(text.startIndex, substringRange.startIndex)
    let length = distance(substringRange.startIndex, substringRange.endIndex)
    let range = NSMakeRange(start, length)

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: range)
    }
})
println(attributedString)

আউটপুট:

Ong দীর্ঘ প্যারাগ্রা {
} পিএইচ বলুন {
    এনএস কালার = "এনএসক্যালাইব্রেটেড আরজিবিসিওলোরস্পেস 1 0 0 1";
} ING! {
}

আপনি দেখতে পাচ্ছেন, "পিএইচ বলুন" "গুণাবলি" নয়, গুণটি চিহ্নিত করা হয়েছে।

যেহেতু NS(Mutable)AttributedStringশেষ পর্যন্ত একটি NSStringএবং একটি প্রয়োজন NSRange, প্রকৃতপক্ষে প্রদত্ত স্ট্রিংটিকে NSStringপ্রথমে রূপান্তর করা ভাল । তারপরে এটি substringRange একটি NSRangeএবং আপনার আর রেঞ্জগুলি রূপান্তর করতে হবে না:

let text = "😄😄😄Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: nsText)

nsText.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
    }
})
println(attributedString)

আউটপুট:

Ong দীর্ঘ অনুচ্ছেদ {
} বলার অপেক্ষা রাখে না {
    এনএস কালার = "এনএসক্যালাইব্রেটেড আরজিবিসিওলোরস্পেস 1 0 0 1";
}! {
}

সুইফট 2 এর জন্য আপডেট:

let text = "😄😄😄Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)

nsText.enumerateSubstringsInRange(textRange, options: .ByWords, usingBlock: {
    (substring, substringRange, _, _) in

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: substringRange)
    }
})
print(attributedString)

সুইফট 3 এর জন্য আপডেট:

let text = "😄😄😄Long paragraph saying!"
let nsText = text as NSString
let textRange = NSMakeRange(0, nsText.length)
let attributedString = NSMutableAttributedString(string: text)

nsText.enumerateSubstrings(in: textRange, options: .byWords, using: {
    (substring, substringRange, _, _) in

    if (substring == "saying") {
        attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.red, range: substringRange)
    }
})
print(attributedString)

সুইফট 4 এর জন্য আপডেট:

সুইফট 4 (এক্সকোড 9) হিসাবে, সুইফ্ট স্ট্যান্ডার্ড লাইব্রেরিটি Range<String.Index>এবং এর মধ্যে রূপান্তর করার পদ্ধতি সরবরাহ করে NSRange। রূপান্তরকরণ NSStringআর প্রয়োজন হয় না:

let text = "😄😄😄Long paragraph saying!"
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstrings(in: text.startIndex..<text.endIndex, options: .byWords) {
    (substring, substringRange, _, _) in
    if substring == "saying" {
        attributedString.addAttribute(.foregroundColor, value: NSColor.red,
                                      range: NSRange(substringRange, in: text))
    }
}
print(attributedString)

এখানে substringRangeএকটি হল Range<String.Index>, এবং যে সংশ্লিষ্ট রূপান্তরিত হয় NSRangeসঙ্গে

NSRange(substringRange, in: text)

74
ওএসএক্সে ইমোজি অক্ষরগুলি টাইপ করতে ইচ্ছুক কারও জন্য - কন্ট্রোল-কমান্ড-স্পেস বার একটি চরিত্র চয়নকারী নিয়ে আসে
জয়

2
আমি একাধিক শব্দের সাথে মিলে গেলে এটি কাজ করে না এবং পুরো স্ট্রিংটি কী মিলবে তা নিশ্চিত। বলুন আমি একটি এপিআই থেকে একটি স্ট্রিং ফিরে পেয়েছি এবং এটি অন্য স্ট্রিংয়ের মধ্যে ব্যবহার করছি এবং আমি চাইছি এপিআই থেকে স্ট্রিংটি আন্ডারলাইন করা হোক, আমি গ্যারান্টি দিতে পারি না যে সাবস্ট্রিংগুলি এপিআই এবং অন্য দুটি স্ট্রিংয়ের মধ্যে থাকবে না স্ট্রিং! কোন ধারনা?
সাইমন্থাম্পার

এনএসমেকরেঞ্জ পরিবর্তিত str.substringWithRange (রেঞ্জ <স্ট্রিং.ইনডেক্স> (শুরু: str.startIndex, শেষ: str.endIndex)) // // হ্যালো, খেলার মাঠ "এই পরিবর্তনগুলি
হরিকৃষ্ণ.পি

(বা) স্ট্রিং কাস্টিং --- আসুন স্ট্রিং = (এনএসএসআরং হিসাবে স্ট্রিং)। সাবস্ট্রিংউইথর্যাঞ্জ (এনএসমেক্রেঞ্জ (শুরু, দৈর্ঘ্য))
হরিকৃষ্ণন.পি

2
আপনি এটি উল্লেখ করেছেন Range<String.Index>এবং NSStringউপযুক্ত নয়। তাদের সহকর্মীরাও কি বেমানান? আমি NSRangeএবং Stringবেমানান? অ্যাপলের একটি এপিআই বিশেষত দুটি সংযুক্ত করে কারণ: ম্যাচগুলি (ইন: বিকল্পগুলি: রেঞ্জ :)
সেনসফুল

56

আপনি বর্ণিত মত মামলার ক্ষেত্রে, আমি এটি কাজ করতে পেলাম। এটি তুলনামূলকভাবে সংক্ষিপ্ত এবং মিষ্টি:

 let attributedString = NSMutableAttributedString(string: "follow the yellow brick road") //can essentially come from a textField.text as well (will need to unwrap though)
 let text = "follow the yellow brick road"
 let str = NSString(string: text) 
 let theRange = str.rangeOfString("yellow")
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.yellowColor(), range: theRange)

11
বৈশিষ্ট্যযুক্ত
স্ট্রিং.এডিএডিট্রিবিউট

7
@ পালুদিস, আপনি সঠিক বলেছেন তবে এই সমাধানটি একটি সুইফ্ট পরিসর ব্যবহার করার চেষ্টা করছে না। এটি একটি ব্যবহার করা হয় NSRangestrএটি একটি NSStringএবং তাই str.RangeOfString()একটি প্রদান করে NSRange
tjpaul

3
আপনি লাইন 2 তে সদৃশ স্ট্রিংগুলি 2 এবং 3 লাইনগুলি এর সাথে প্রতিস্থাপন করেও সরাতে পারেন:let str = attributedString.string as NSString
জেসন মুর

2
এটি স্থানীয়করণের দুঃস্বপ্ন।
সুলতান

29

উত্তরগুলি ভাল, তবে সুইফট 4 এর মাধ্যমে আপনি আপনার কোডটি কিছুটা সহজ করতে পারেন:

let text = "Test string"
let substring = "string"

let substringRange = text.range(of: substring)!
let nsRange = NSRange(substringRange, in: text)

সতর্কতা অবলম্বন করুন, কারণ rangeফাংশনটির ফলাফলটি মোড়কজাতীয় হতে হবে।


10

সম্ভাব্য সমাধান

সুইফট দূরত্ব সরবরাহ করে () যা শুরু এবং শেষের মধ্যে দূরত্ব পরিমাপ করে যা এনএসরেঞ্জ তৈরি করতে ব্যবহার করা যেতে পারে:

let text = "Long paragraph saying something goes here!"
let textRange = text.startIndex..<text.endIndex
let attributedString = NSMutableAttributedString(string: text)

text.enumerateSubstringsInRange(textRange, options: NSStringEnumerationOptions.ByWords, { (substring, substringRange, enclosingRange, stop) -> () in
    let start = distance(text.startIndex, substringRange.startIndex)
    let length = distance(substringRange.startIndex, substringRange.endIndex)
    let range = NSMakeRange(start, length)

//    println("word: \(substring) - \(d1) to \(d2)")

        if (substring == "saying") {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: NSColor.redColor(), range: range)
        }
})

2
দ্রষ্টব্য: স্ট্রিংয়ে ইমোজি এর মতো অক্ষরগুলি ব্যবহার করা হলে এটি ভেঙে যেতে পারে - মার্টিনের প্রতিক্রিয়া দেখুন।
জয়

7

আমার জন্য এটি পুরোপুরি কাজ করে:

let font = UIFont.systemFont(ofSize: 12, weight: .medium)
let text = "text"
let attString = NSMutableAttributedString(string: "exemple text :)")

attString.addAttributes([.font: font], range:(attString.string as NSString).range(of: text))

label.attributedText = attString

5

সুইফট 4:

অবশ্যই, আমি জানি যে সুইফট 4 এর এনএসআরঞ্জের জন্য ইতিমধ্যে একটি এক্সটেনশন রয়েছে

public init<R, S>(_ region: R, in target: S) where R : RangeExpression,
    S : StringProtocol, 
    R.Bound == String.Index, S.Index == String.Index

আমি জানি বেশিরভাগ ক্ষেত্রে এই উদ্যোগটি যথেষ্ট। এর ব্যবহার দেখুন:

let string = "Many animals here: 🐶🦇🐱 !!!"

if let range = string.range(of: "🐶🦇🐱"){
     print((string as NSString).substring(with: NSRange(range, in: string))) //  "🐶🦇🐱"
 }

তবে রূপান্তর <স্ট্রিং.ইনডেক্স> থেকে সুইফট স্ট্রিংয়ের উদাহরণ ছাড়াই এনএসরেঞ্জে সরাসরি করা যেতে পারে।

জেনেরিক ডিআইডি ব্যবহারের পরিবর্তে আপনার পক্ষ থেকে স্ট্রিং হিসাবে লক্ষ্য পরামিতি প্রয়োজন এবং যদি আপনার কাছে লক্ষ্য স্ট্রিং না থাকে তবে আপনি সরাসরি রূপান্তর তৈরি করতে পারেন

extension NSRange {
    public init(_ range:Range<String.Index>) {
        self.init(location: range.lowerBound.encodedOffset,
              length: range.upperBound.encodedOffset -
                      range.lowerBound.encodedOffset) }
    }

অথবা আপনি নিজেই রেঞ্জের জন্য বিশেষায়িত এক্সটেনশন তৈরি করতে পারেন

extension Range where Bound == String.Index {
    var nsRange:NSRange {
    return NSRange(location: self.lowerBound.encodedOffset,
                     length: self.upperBound.encodedOffset -
                             self.lowerBound.encodedOffset)
    }
}

ব্যবহার:

let string = "Many animals here: 🐶🦇🐱 !!!"
if let range = string.range(of: "🐶🦇🐱"){
    print((string as NSString).substring(with: NSRange(range))) //  "🐶🦇🐱"
}

অথবা

if let nsrange = string.range(of: "🐶🦇🐱")?.nsRange{
    print((string as NSString).substring(with: nsrange)) //  "🐶🦇🐱"
}

সুইফট 5:

ডিফল্টরূপে encodedOffsetসুইট স্ট্রিংগুলি ইউটিএফ -8 এনকোডিং-এ স্থানান্তরিত হওয়ার কারণে, স্ট্রিংয়ের উদাহরণ না দিয়ে রেফারিকে অবহিত হিসাবে বিবেচনা করা হয় এবং রেঞ্জকে এনএসরেঞ্জে রূপান্তর করা যায় না, কারণ অফসেট গণনা করতে আমাদের উত্সের স্ট্রিংটি প্রয়োজন ইউটিএফ -8 এ এনকোড হয়েছে এবং অফসেট গণনার আগে এটি ইউটিএফ -16 এ রূপান্তর করা উচিত। তাই সর্বোত্তম পন্থা, আপাতত, জেনেরিক init ব্যবহার করা ।



3

সুইফট 4

আমি মনে করি, দুটি উপায় আছে।

1. এনএসআরঞ্জ (পরিসীমা, এতে:)

2. এনএসরেঞ্জ (অবস্থান: দৈর্ঘ্য:)

কোডের উদাহরণ:

let attributedString = NSMutableAttributedString(string: "Sample Text 12345", attributes: [.font : UIFont.systemFont(ofSize: 15.0)])

// NSRange(range, in: )
if let range = attributedString.string.range(of: "Sample")  {
    attributedString.addAttribute(.foregroundColor, value: UIColor.orange, range: NSRange(range, in: attributedString.string))
}

// NSRange(location: , length: )
if let range = attributedString.string.range(of: "12345") {
    attributedString.addAttribute(.foregroundColor, value: UIColor.green, range: NSRange(location: range.lowerBound.encodedOffset, length: range.upperBound.encodedOffset - range.lowerBound.encodedOffset))
}

স্ক্রিন শট: এখানে চিত্র বর্ণনা লিখুন



1

বিদ্যমান বৈশিষ্ট্যগুলি সংরক্ষণ করে সুইফট 3 এক্সটেনশন বৈকল্পিক

extension UILabel {
  func setLineHeight(lineHeight: CGFloat) {
    guard self.text != nil && self.attributedText != nil else { return }
    var attributedString = NSMutableAttributedString()

    if let attributedText = self.attributedText {
      attributedString = NSMutableAttributedString(attributedString: attributedText)
    } else if let text = self.text {
      attributedString = NSMutableAttributedString(string: text)
    }

    let style = NSMutableParagraphStyle()
    style.lineSpacing = lineHeight
    style.alignment = self.textAlignment
    let str = NSString(string: attributedString.string)

    attributedString.addAttribute(NSParagraphStyleAttributeName,
                                  value: style,
                                  range: str.range(of: str as String))
    self.attributedText = attributedString
  }
}

0
func formatAttributedStringWithHighlights(text: String, highlightedSubString: String?, formattingAttributes: [String: AnyObject]) -> NSAttributedString {
    let mutableString = NSMutableAttributedString(string: text)

    let text = text as NSString         // convert to NSString be we need NSRange
    if let highlightedSubString = highlightedSubString {
        let highlightedSubStringRange = text.rangeOfString(highlightedSubString) // find first occurence
        if highlightedSubStringRange.length > 0 {       // check for not found
            mutableString.setAttributes(formattingAttributes, range: highlightedSubStringRange)
        }
    }

    return mutableString
}

0

আমি সুইফট ভাষা পছন্দ করি, তবে NSAttributedStringএকটি সুইফ্টের Rangeসাথে সামঞ্জস্যপূর্ণ নয় এমনটি ব্যবহার NSRangeকরা আমার মাথার দীর্ঘকাল ধরে আঘাত করে। সুতরাং যে সমস্ত আবর্জনা কাছাকাছি পেতে আমি নিম্নলিখিত পদ্ধতি তৈরি একটি ফিরেNSMutableAttributedString আপনার রঙের সাথে সেট করা হাইলাইট শব্দগুলির সাথে ।

এটি ইমোজিদের জন্য কাজ করে না । আপনার প্রয়োজন হলে পরিবর্তন করুন।

extension String {
    func getRanges(of string: String) -> [NSRange] {
        var ranges:[NSRange] = []
        if contains(string) {
            let words = self.components(separatedBy: " ")
            var position:Int = 0
            for word in words {
                if word.lowercased() == string.lowercased() {
                    let startIndex = position
                    let endIndex = word.characters.count
                    let range = NSMakeRange(startIndex, endIndex)
                    ranges.append(range)
                }
                position += (word.characters.count + 1) // +1 for space
            }
        }
        return ranges
    }
    func highlight(_ words: [String], this color: UIColor) -> NSMutableAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        for word in words {
            let ranges = getRanges(of: word)
            for range in ranges {
                attributedString.addAttributes([NSForegroundColorAttributeName: color], range: range)
            }
        }
        return attributedString
    }
}

ব্যবহার:

// The strings you're interested in
let string = "The dog ran after the cat"
let words = ["the", "ran"]

// Highlight words and get back attributed string
let attributedString = string.highlight(words, this: .yellow)

// Set attributed string
label.attributedText = attributedString

-3
let text:String = "Hello Friend"

let searchRange:NSRange = NSRange(location:0,length: text.characters.count)

let range:Range`<Int`> = Range`<Int`>.init(start: searchRange.location, end: searchRange.length)

6
আপনার উত্তরটি কিছুটা ব্যাখ্যা করার, এবং পছন্দ মতো কোডটি সঠিকভাবে ফর্ম্যাট করার বিষয়ে কীভাবে?
সামাব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.