2017-09-15 4 views
1

J'ai regardé autour de SO et n'a pas pu trouver ce problème exact, malgré quelques questions avec des titres similaires.NSAttributedString ne fonctionnait pas pour UILabel

Tout ce que je veux faire est d'avoir un texte correspondant sur UILabel être dessiné en gras. Je l'utilise quand je suis à la recherche d'objets, il devrait "bolden" le terme de recherche. À cette fin, j'ai écrit le code suivant:

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 

    } 
} 

Tout "semble" bien. La déclaration du journal crache ce que je m'attends et tout est bon. Cependant, quand il est dessiné sur UILabel, parfois une chaîne entière est mise en gras, et je ne comprends pas comment cela pourrait se produire. Rien dans le code ne suggère que cela devrait se produire.

Je mis le résultat de cette méthode ci-dessus dans une méthode de configuration UITableCell typique (ie tableView(cellForRowAt indexPath:....))

cell.titleLabel.attributedText = artist.displayName.emptyIfNil.boldenOccurrences(of: source.currentSearchTerm, baseFont: cell.titleLabel.font, textColor: cell.titleLabel.textColor)

+1

Pourriez-vous vérifier que la valeur parfois retournée par 'cell.titleLabel.font' est pas gras v Police de ersion (juste imprimer 'baseFont' chaque fois)? – Larme

+0

Je pense que vous devez passer dans 'cell.titleLabel.attributedText = artist.displayName.emptyIfNil.boldenOccurrences (de: source.currentSearchTerm, baseFont: cell.titleLabel.font, textColor: cell.titleLabel.textColor)' valeur statique UIFont comme base police, et devrait fonctionner –

+0

Testé sur Playground, mais 'myLabel.font = systemFont'. 'myLabel.attributedText = someAttributedStringWithABoldFontForTheWholeRangeNameFontBold;' alors 'myLabel.font == BoldFont'. Clairement, 'aLabel.font',' aLabel.color' sont UNIQUEMENT pour 'aLabel.text'. Ne pas mélanger avec 'aLabel.attributedText'. Je ne suis pas sûr si la police retournée avec un texte attribué retournera la police du premier caractère, mais cela ne me surprendrait pas. Et puisque les cellules sont réutilisées, et à un moment donné la gamme en gras inclus le premier caractère ... – Larme

Répondre

2

Votre principal problème est la réutilisation des cellules, peut-être quand une cellule est réutilisée à garder votre police en gras la police, et qui est la raison pour laquelle vous avez ce problème, vous pouvez résoudre dans votre méthode cellulaire prepareForReuse() vous pouvez ajouter

override func prepareForReuse() { 
     super.prepareForReuse() 
     //to fix ipad Error 
     self.titleLabel.font = UIFont(name: "YourBaseFont", size: yourFontSize) 
    } 
+1

You ninja! C'était définitivement la solution. – horseshoe7