Reputation: 746
I am trying to replace a substring with attributed String. Following is my code.
let searchText = self.searchBar.text!
let name = item.firstName ?? ""
let idNo = "Employee Id. \(item.employeeId ?? "NA")"
if let range = name.range(of: searchText, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)
{
let attributedSubString = NSAttributedString.init(string: name.substring(with: range), attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
let normalNameString = NSMutableAttributedString.init(string: name)
normalNameString.mutableString.replacingCharacters(in: range, with: attributedSubString)
cell.name.attributedText = normalNameString
}
else
{
cell.name.text = name
}
I am getting compile time error:
"Cannot convert value of type 'Range' (aka 'Range') to expected argument type 'NSRange' (aka '_NSRange')".
What should I change here?
Upvotes: 20
Views: 23712
Reputation: 20804
You can use NSString
and NSRange
, also you need to change this line normalNameString.mutableString.replacingCharacters(in: range, with: attributedSubString)
and use this one instead normalNameString.replaceCharacters(in: nsRange, with: attributedSubString)
because mutableString is NSMutableString, and replacingCharacters
expect String and not NSAttributtedString
Full code (Updated for Swift5)
let nsRange = NSString(string: name).range(of: searchText, options: String.CompareOptions.caseInsensitive)
if nsRange.location != NSNotFound
{
let attributedSubString = NSAttributedString.init(string: NSString(string: name).substring(with: nsRange), attributes: [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 17)])
let normalNameString = NSMutableAttributedString.init(string: name)
normalNameString.replaceCharacters(in: nsRange, with: attributedSubString)
cell.name.attributedText = normalNameString
}
else
{
cell.name.text = name
}
Upvotes: 25
Reputation: 6564
You have to create NSRange
instance using Range<String.index>
lowerBound
and UpperBound
position values as below.
let searchText = "Kiran"
let name = "Kiran Jasvanee"
let idNo = "Employee Id. \("24")"
if let range = name.range(of: searchText, options: String.CompareOptions.caseInsensitive, range: nil, locale: nil)
{
let attributedSubString = NSAttributedString.init(string: name.substring(with: range), attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
let normalNameString = NSMutableAttributedString.init(string: name)
let startPos = name.distance(from: searchText.characters.startIndex, to: range.lowerBound)
let nsrange = NSMakeRange(startPos, searchText.characters.count)
normalNameString.replaceCharacters(in: nsrange, with: attributedSubString)
labelName.attributedText = normalNameString
}
else
{
labelName.text = name
}
add, self.searchBar.text!
instead of "Kiran"
in searchtext constant
and
add item.firstName ?? ""
instead of "Kiran Jasvanee"
in name constant
according to your requirement.
I've tried it in a demo, and code I posted working fine as below. Please check.
If name = "AKiranJasvanee"
If name = "KiranJasvanee"
Upvotes: 2
Reputation: 1956
Please do like that,
First,
extension String {
func nsRange(from range: Range<String.Index>) -> NSRange {
let from = range.lowerBound.samePosition(in: utf16)
let to = range.upperBound.samePosition(in: utf16)
return NSRange(location: utf16.distance(from: utf16.startIndex, to: from),
length: utf16.distance(from: from, to: to))
}
}
after that you have one lable and string like that,
private func setAttributedLabel() {
let lableText = UILabel()
let strTitle = "Basic string Double tap" // your main string
let title:NSMutableAttributedString = NSMutableAttributedString(string: strTitle)
// give attribute to basic string
title.addAttributes([NSForegroundColorAttributeName:UIColor.blue ,NSFontAttributeName:UIFont.boldSystemFont(ofSize: 15)], range: NSRange.init(location: 0, length: title.length))
lableText.attributedText = title
// give attribute to your range string
let rangeOfString = lableText.text?.range(of: "Double tap") // this string is subString of strTitle
title.addAttributes([NSForegroundColorAttributeName:UIColor.gray,NSFontAttributeName:UIFont.systemFont(ofSize: 15)], range: strTitle.nsRange(from: rangeOfString!))
lableText.attributedText = title
}
I hope it will help.
Upvotes: 5
Reputation: 772
In Swift Range
is not a NSRange
type. Here you are passing Swift Range
type where a NSRange
is expected, that why you got an error.
The one workaround can be you can cast your name
to NSString
to get the range of type NSRange
, like this:
let range = (name as NSString).range(of: searchText, options: String.CompareOptions.caseInsensitive)
let subString = NSString(string: name).substring(with: range)
let attributedSubString = NSAttributedString.init(string:subString, attributes: [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 17)])
let normalNameString = NSMutableAttributedString.init(string: name)
normalNameString.replaceCharacters(in: range, with: attributedSubString)
Upvotes: -1