didSelectRowAt indexPath method called after long pressing the UITableViewCell - uitableview

I'm developing a simple shopping app. There I used UITableView for listing the product but when I select the listed product in the particular cell, "didSelectRowAt indexPath" method has not been called/triggered, so I tried with long pressing UITableViewCell the method is working good and also triggered properly but I don't need this solution.
In the product listing page, I just used UISegmentedControl in the navigation bar and dynamic prototyped UITableView in the UIView. Even I didn't use any kind of UIGestures in this page.
This question may be duplicated and already asked in Stack Overflow, but there were none of the answers solved my problem. I need to continue working the UITableViewCell without long pressing.
Note: I tried switching off the "Delays Content Touches" in TableView, and I surf through Stack Overflow and web but I couldn't find any solutions.
Update
"cellForRowAt indexPath" code are as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ProductCell
let vendor = array_list_vendor[indexPath.row] as? String
let orgPrice = array_list_price[indexPath.row] as? Int
let starDealPrice = array_list_stardealPrice[indexPath.row] as? Int
let url = array_list_image[indexPath.row] as! String
cell.productTitle.text = array_list_title[indexPath.row] as? String
if url == "" {
cell.productImg.image = UIImage(named: "no-img")
}
else {
cell.productImg.image = nil
ImageLoader.sharedLoader.imageForUrl(urlString: (url), completionHandler:{(image: UIImage?, url: String) in
//cell.productImg.frame.width =
cell.productImg.image = image!
})
}
if vendor == "amazon" {
cell.sellerImg.image = UIImage(named: "prodicon-amazon")
}
else if vendor == "flipkart" {
cell.sellerImg.image = UIImage(named: "prodicon-flipkart")
}
else {
cell.sellerImg.image = UIImage(named: "prodicon-amazon")
}
cell.starDealImg.image = UIImage(named: "prodicon-stardeal")
let rupee = "\u{20B9}"
let text = String(format: "%# %d", rupee, orgPrice!)
let linkTextWithColor = String(rupee)
let range = (text as NSString).range(of: linkTextWithColor!)
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black , range: range)
//Seller price
cell.sellerPrice.attributedText = attributedString
let text1 = String(format: "%# %d", rupee, starDealPrice!)
let linkTextWithColor1 = String(rupee)
let range1 = (text1 as NSString).range(of: linkTextWithColor1!)
let attributedString1 = NSMutableAttributedString(string:text1)
attributedString1.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 127.0/255.0, green: 63.0/255.0, blue: 152.0/255.0, alpha: 1.0) , range: range1) //Purple color
//Stardeal price
cell.starDealPrice.attributedText = attributedString1
let cashBack = orgPrice! - starDealPrice!
let text2 = String(format: "Save %#", rupee)
let linkTextWithColor2 = String(rupee)
let range2 = (text2 as NSString).range(of: linkTextWithColor2!)
let attributedString2 = NSMutableAttributedString(string:text2)
attributedString2.addAttribute(NSForegroundColorAttributeName, value: UIColor.white , range: range2)
let text3 = String(format: "%d", cashBack)
let linkTextWithColor3 = String(cashBack)
let range3 = (text3 as NSString).range(of: linkTextWithColor3)
let attributedString3 = NSMutableAttributedString(string:text3)
attributedString3.addAttribute(NSForegroundColorAttributeName, value: UIColor.white , range: range3)
//Attributed string with multiple words
attributedString2.append(attributedString3)
cell.productCashBack.attributedText = attributedString2
return cell
}

Related

Format data content in Tableviewcell in Swift

How it should look like.
How it currently look like.
I'm trying to display information on my tableview cell.
The first cell information on the image above looks good, but only when the table view is on edit mode - and I only want the same display in normal mode for all my cells.
Here is my code below
//cellForRow method
var cell = UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: celliD)
cell?.textLabel?.numberOfLines = 0
cell?.detailTextLabel?.numberOfLines = 0
cell?.accessoryView = nil
cell?.tintColor = UIColor.cmoOrangeColor
cell?.textLabel?.textColor = UIColor.darkGray
cell?.detailTextLabel?.textColor = UIColor.lightGray
let animalEntity = self.newSaleSelectedAnimalsManagedObject[indexPath.row] as? AnimalEntity
cell?.textLabel?.attributedText = AnimalFacade.animalTitleAttributedText(animalEntity: animalEntity!, withHolding: false)
cell?.detailTextLabel?.attributedText = AnimalFacade.animalDetails()
return cell!
//textLabel formating data
class func animalTitleAttributedText(animalEntity: AnimalEntity, withHolding: Bool) -> NSMutableAttributedString {
//AttributedText
let attributedTitle = NSDictionary(object: UIFont.tableViewCellTitle as Any, forKey: NSFontAttributeName as NSCopying) as? [String : Any]
let attributedSubtitle = NSDictionary(object: UIFont.tableViewCellSubtitle as Any, forKey: NSFontAttributeName as NSCopying) as? [String : Any]
//TextLabel
let titleAttributedText = NSMutableAttributedString()
//officialTag
let officialTag = animalEntity.officialTag //UK 123456 123456
let mgtTag = animalEntity.managementTag //WER3456
let age = DateUtil.calculateAge(dateTime: animalEntity.dob! as Date) //13 y
let animalCategory = animalEntity.animalTag //Heifer Calf
let breed = animalEntity.breed //AB
titleAttributedText.append(NSAttributedString(string: officialTag! + "\n", attributes: attributedTitle))
titleAttributedText.append(NSAttributedString(string: "Mgmt Tag: \(mgtTag!), \(age), \(animalCategory!), \(breed!) \n", attributes: attributedSubtitle))
return titleAttributedText
}
//detailLabel formatting data
class func animalDetails() -> NSMutableAttributedString {
let attributedSubtitle = NSDictionary(object: UIFont.tableViewCellSubtitle as Any, forKey: NSFontAttributeName as NSCopying) as? [String : Any]
//detailsLabel
let detailsAttributedText = NSMutableAttributedString()
let price = "1234.85"
let lotNumber = "TREPOU123"
detailsAttributedText.append(NSAttributedString(string: price + "\n\n", attributes: attributedSubtitle))
detailsAttributedText.append(NSAttributedString(string: lotNumber, attributes: attributedSubtitle))
return detailsAttributedText
}

How to display dynamic multiple label in tableview cell swift?

I'm trying with NSMutableAttributedString but not getting perfect resolution and also underline for each string.
Now It's display like this:
But I want like this:
I m trying with this code in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) for displaying the cell:
let arrSearchTag = search_detail?.value(forKey: "search_tags") as! NSArray
if arrSearchTag.count > 0
{
let str : NSMutableAttributedString = NSMutableAttributedString(string: "")
for string in arrSearchTag
{
let myString = string
let myString1 = " "
let myAttribute = [NSBackgroundColorAttributeName : UIColor.init(red: 94.0/255.0, green: 94.0/255.0, blue: 94.0/255.0, alpha: 1.0)]
let myAttribute1 = [NSBackgroundColorAttributeName : UIColor.clear]
let range = (myString as! NSString).range(of: myString as! String)
let myAttrString = NSMutableAttributedString(string: myString as! String, attributes: myAttribute)
let myAttrString1 = NSMutableAttributedString(string: myString1 , attributes: myAttribute1)
myAttrString.addAttribute(NSForegroundColorAttributeName, value: UIColor.white, range: range)
str.append(myAttrString)
str.append(myAttrString1)
}
cell.lblSearchTags.attributedText = str
}

Get word that was tapped in UILabel instead of character [iOS]

I am trying to extract the word that was tapped in a UILabel using tap gesture recognizer. I am able to get the character that was tapped, as well as the range of the character, but I am not able to extract the full word. Is there a way to get the full string of the word that was tapped instead of the character?
if let label = descriptionLabel, tapGestureRecognizer != nil {
if label.attributedText == nil {
return
}
let storage = NSTextStorage(attributedString: label.attributedText ?? NSAttributedString())
let textContainer = NSTextContainer(size: label.bounds.size)
let layoutManager = NSLayoutManager()
layoutManager.addTextContainer(textContainer)
storage.addLayoutManager(layoutManager)
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = (label.lineBreakMode)
textContainer.maximumNumberOfLines = label.numberOfLines
let location: CGPoint = tapGestureRecognizer!.location(in: label)
let characterIndex: Int = layoutManager.characterIndex(for: location, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if characterIndex < storage.length {
print("Character Index: \(Int(characterIndex))")
let range = NSRange(location: characterIndex, length: 1)
let substring: String? = (label.attributedText?.string as NSString?)?.substring(with: range)
//prints out one character, how do I get the full word of this character
print(substring)
}
}
Much appreciated
I don't like this way, but it works. Place the following after the print(substring) statement. Why doesn't UIKit have a method to extract the full string at a Range? Ridiculous.
let afterWords: [Any] = (afterString.components(separatedBy: " "))
let beforeWords: [Any] = (beforeString.components(separatedBy: ", "))
var attachmentString = ""
if let stringBeforeLocation = beforeWords.last as? String, let stringAfterLocation = afterWords.first as? String {
attachmentString = stringBeforeLocation
if stringAfterLocation.count > 0 {
let choppedString = (stringAfterLocation as NSString).substring(from: 1)
attachmentString = attachmentString + choppedString
print("FULL STRING TAPPED \(attachmentString)")
}
}

NSAttributedString not working for UILabel

I looked around SO and couldn't find this exact problem, despite there being a few questions with similar titles.
All I want to do is have some matching text on UILabel be drawn in BOLD. I'm using it when I'm searching for objects, it should 'bolden' the search term. To this aim, I wrote the following code:
extension String {
func boldenOccurrences(of searchTerm: String?, baseFont: UIFont, textColor: UIColor) -> NSAttributedString {
let defaultAttributes: [String : Any] = [NSForegroundColorAttributeName : textColor,
NSFontAttributeName: baseFont]
let result = NSMutableAttributedString(string: self, attributes: defaultAttributes)
guard let searchTerm = searchTerm else {
return result
}
guard searchTerm.characters.count > 0 else {
return result
}
// Ranges. Crash course:
//let testString = "Holy Smokes!"
//let range = testString.startIndex ..< testString.endIndex
//let substring = testString.substring(with: range) // is the same as testString
var searchRange = self.startIndex ..< self.endIndex //whole string
var foundRange: Range<String.Index>!
let boldFont = UIFont(descriptor: baseFont.fontDescriptor.withSymbolicTraits(.traitBold)!, size: baseFont.pointSize)
repeat {
foundRange = self.range(of: searchTerm, options: .caseInsensitive , range: searchRange)
if let found = foundRange {
// now we have to do some stupid stuff to make Range compatible with NSRange
let rangeStartIndex = found.lowerBound
let rangeEndIndex = found.upperBound
let start = self.distance(from: self.startIndex, to: rangeStartIndex)
let length = self.distance(from: rangeStartIndex, to: rangeEndIndex)
log.info("Bolden Text: \(searchTerm) in \(self), range: \(start), \(length)")
let nsRange = NSMakeRange(start, length)
result.setAttributes([NSForegroundColorAttributeName : textColor,
NSFontAttributeName: boldFont], range: nsRange)
searchRange = found.upperBound ..< self.endIndex
}
} while foundRange != nil
return result
}
}
Everything "looks" fine. The log statement spits out what I expect and it's all good. However, when drawn on the UILabel, sometimes an entire string is set to bold, and I don't understand how that could be happening. Nothing in the code suggests this should be happening.
I set the result of this above method in a typical UITableCell configuration method (i.e. tableView(cellForRowAt indexPath:.... ) )
cell.titleLabel.attributedText = artist.displayName.emptyIfNil.boldenOccurrences(of: source.currentSearchTerm, baseFont: cell.titleLabel.font, textColor: cell.titleLabel.textColor)
Your primary issue is the cell reuse, maybe when a cell is reused keep your font bold as font, and that is why you have this issue, you can solve this in your cell prepareForReuse() method you can add
override func prepareForReuse() {
super.prepareForReuse()
//to fix ipad Error
self.titleLabel.font = UIFont(name: "YourBaseFont", size: yourFontSize)
}

Make part of a string bold that matches a search string

I have a table of items and each item has a label. I also have a search bar that is used to filter the items in the table based on whether mySearchBar.text is a substring of myLabel.text.
That is all working fine, but I'd like to bold the portions of label text that match the search string.
The end product would be something similar to Google Maps search.
Swift 4 : XCode 9.x
private func filterAndModifyTextAttributes(searchStringCharacters: String, completeStringWithAttributedText: String) -> NSMutableAttributedString {
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: completeStringWithAttributedText)
let pattern = searchStringCharacters.lowercased()
let range: NSRange = NSMakeRange(0, completeStringWithAttributedText.characters.count)
var regex = NSRegularExpression()
do {
regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options())
regex.enumerateMatches(in: completeStringWithAttributedText.lowercased(), options: NSRegularExpression.MatchingOptions(), range: range) {
(textCheckingResult, matchingFlags, stop) in
let subRange = textCheckingResult?.range
let attributes : [NSAttributedStringKey : Any] = [.font : UIFont.boldSystemFont(ofSize: 17),.foregroundColor: UIColor.red ]
attributedString.addAttributes(attributes, range: subRange!)
}
}catch{
print(error.localizedDescription)
}
return attributedString
}
How to use :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle , reuseIdentifier: "Cell")
cell.textLabel?.attributedText = self.filterAndModifyTextAttributes(searchStringCharacters: self.textFromSearchBar, completeStringWithAttributedText: searchResultString)
return cell
}
Here's a sample of what I ended up implementing:
#IBOutlet weak var mySearchBar: UISearchBar!
#IBOutlet weak var myLabel: UILabel!
...
func makeMatchingPartBold(searchText: String) {
// check label text & search text
guard
let labelText = myLabel.text,
let searchText = mySearchBar.text
else {
return
}
// bold attribute
let boldAttr = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: myLabel.font.pointSize)]
// check if label text contains search text
if let matchRange: Range = labelText.lowercased().range(of: searchText.lowercased()) {
// get range start/length because NSMutableAttributedString.setAttributes() needs NSRange not Range<String.Index>
let matchRangeStart: Int = labelText.distance(from: labelText.startIndex, to: matchRange.lowerBound)
let matchRangeEnd: Int = labelText.distance(from: labelText.startIndex, to: matchRange.upperBound)
let matchRangeLength: Int = matchRangeEnd - matchRangeStart
// create mutable attributed string & bold matching part
let newLabelText = NSMutableAttributedString(string: labelText)
newLabelText.setAttributes(boldAttr, range: NSMakeRange(matchRangeStart, matchRangeLength))
// set label attributed text
myLabel.attributedText = newNameText
}
}

Resources