简体   繁体   中英

String interpolation in attributed text from HTML (Swift 4)

I am displaying text in my app as an attributed string from local HTML files, populating a label, as this gives me formatting flexibility. Why is the usual string interpolation not working in this case, and is there a workaround? The aim is to allow the user-provided username to be contained within the string. It functions well except leaves "(user)" from the HTML file displayed in the label rather than interpolating the username as I expected. I'm still learning so if this is a strange and unworkable way to be doing things anyway then please let me know...

This is my code:

class ArticleViewController: UIViewController {

    @IBOutlet weak var contentField: UITextView!

    var articleID : String = ""

    var user = UserDefaults.standard.object(forKey: "user") ?? "user"

    override func viewDidLoad() {
        super.viewDidLoad()

        if let html = Bundle.main.path(forResource: "\(articleID)", ofType: "html") {
            let urlToLoad = URL(fileURLWithPath: html)
            let data = NSData(contentsOf: urlToLoad)

            if let attributedString = try? NSAttributedString(data: data as! Data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) {

                contentField.attributedText = attributedString

            }
        }
    } 
}

Thanks for your help!

You'll have to find and replace the occurrences of (user) in attributedString .

This should work:

import Foundation
import UIKit

var myString : NSAttributedString = NSAttributedString(string: "Hello (user), this is a message for you")
let regex = try! NSRegularExpression(pattern: "\\(user\\)", options: .caseInsensitive)
let range = NSMakeRange(0, myString.string.count)
let newString = regex.stringByReplacingMatches(in: myString.string, options: [], range: range, withTemplate: "CJDSW18")
let newAttribuetdString = NSAttributedString(string: newString, attributes: myString.attributes(at: 0, effectiveRange: nil))
print(newAttribuetdString.string)

Why is the usual string interpolation not working in this case

Usual string interpolation works on the String literals in the Swift source files, not on the content of general text files or html files.

You may need to replace the occurrences of (user) in the attributed string. (The basic concept is not different from Carpsen90's answer, but you need to be careful when replacing already attributed string.)

    if let htmlURL = Bundle.main.url(forResource: articleID, withExtension: "html") {
        do {
            let data = try Data(contentsOf: htmlURL)

            let attributedString = try NSMutableAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil)

            //### When you want to compare the result...
            //originalText.attributedText = attributedString

            let regex = try! NSRegularExpression(pattern: "\\(user\\)")
            let range = NSRange(0..<attributedString.string.utf16.count)
            let matches = regex.matches(in: attributedString.string, range: range)
            for match in matches.reversed() {
                attributedString.replaceCharacters(in: match.range, with: user)
            }

            contentField.attributedText = attributedString
        } catch {
            // Do error processing here...
            print(error)
        }
    }

Example.

article.html:

<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <i>(user)</i>😀<b>(user)</b>
</body>
</html>

What you can see in the text view:

屏幕图像

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM