以编程方式将段落标题添加到UITextView

时间:2017-01-31 00:33:38

标签: ios swift xcode uitextview heading

我有一个包含UITextView的View Controller。此UITextView根据控制它的数据模型(大约30种不同的文本选项)以编程方式更新文本。 UITextView中的内容总是很长,每个大约450个单词。段落的范围是2 - 5.

这一切都很完美。我只需要一种视觉方式来分解段落。现在,我正在使用\ n \ n在段落之间创建几个换行符。虽然这有效,但我最终需要标题。

在IB中,我将text属性从Plain更改为Attributed。这允许我在Xcode中以类似WYSIWYG的方式修改文本。效果很好,但我没有使用IB来更改文本。

我尝试使用WebView(下面的代码)。我用H1和P标签创建了一个非常基本的HTML文件。遗憾的是,这将在我的项目中创建30多个HTML文件。从可管理性的角度来看,我不喜欢这样。文本也是不可选择的,它与webview一样(我不想诉诸CSS [-webkit-user-select]来缓解这个问题。)

    let path: String? = Bundle.main.path(forResource: "myHTML", ofType: "html")
    let file = try? String(contentsOfFile: path!, encoding: String.Encoding.utf8)
    let baseURL = URL(fileURLWithPath: Bundle.main.bundlePath)
    self.myWebView.loadHTMLString(file!, baseURL: baseURL)

我的理想解决方案

我可以坚持目前的设置吗?以编程方式使用我的数据模型更改UITextView文本,WHILE能够更改代码中的文本属性以创建我的段落标题吗?

This is my current UI without any attributed text This is my ultimate end-goal

编辑 - 尝试将其与MVC一起使用

allFormattedDescriptions: [ 
Formatted(heading: "heading 1", descriptionText: "Lorem Ipsum Paragraph 1"),
Formatted(heading: "heading 2", descriptionText: "Lorem Ipsum Paragraph 2"),
Formatted(heading: "heading 3", descriptionText: "Lorem Ipsum Paragraph 3")
]
// Ideal formatting; every paragraph will have a heading. Can handle that with one object that requires both a heading and description text (paragraph).

struct Formatted {

var heading: String!
var descriptionText: String!

var bodyParagraphStyle: NSMutableParagraphStyle = {
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 10
    style.paragraphSpacingBefore = 6
    style.paragraphSpacing = 6
    return style
}()

var headerParagraphStyle: NSMutableParagraphStyle = {
    let style = NSMutableParagraphStyle()
    style.paragraphSpacingBefore = 24
    return style
}()

var bodyAttributes: [String: AnyObject]!
var headerAttributes: [String: AnyObject]!

}

1 个答案:

答案 0 :(得分:4)

使用NS(Mutable)ParagraphStyleNS(Mutable)AttributedString。例如:

class ViewController: UIViewController {
    @IBOutlet weak var textView: UITextView!

    var allFormattedDescriptions = [
        Formatted(heading: "Introduction to Bacon Ipsum", descriptionText: "Bacon ipsum dolor amet jerky pig pastrami capicola biltong turkey, ball tip fatback andouille porchetta flank swine brisket bacon pork loin. Tongue shank cupim, pastrami spare ribs meatball drumstick pork pork chop. Sirloin flank tenderloin bresaola doner, cupim ribeye drumstick ham hock t-bone pork short ribs shoulder. Fatback ribeye pastrami pancetta, chuck turkey andouille boudin burgdoggen shoulder tongue kielbasa doner shankle turducken. Rump strip steak drumstick, shankle cupim prosciutto jerky bacon doner. Pork chop jowl burgdoggen, cow turkey ball tip doner. Cow ham meatball chuck flank meatloaf prosciutto."),
        Formatted(heading: "Kielbasa?", descriptionText: "Spare ribs boudin ham leberkas landjaeger filet mignon. Short loin fatback hamburger leberkas chicken. Frankfurter chuck short ribs ball tip, ground round cupim shank brisket venison turducken boudin. Pig sirloin pork loin meatloaf short loin turkey swine.")
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        let textContent = NSMutableAttributedString()
        for (index, desc) in allFormattedDescriptions.enumerated() {
            let includeLinebreak = index < allFormattedDescriptions.count - 1
            textContent.append(desc.attributeString(includeLineBreak: includeLinebreak))
        }
        textView.attributedText = textContent
    }
}

struct Formatted {
    var heading: String
    var descriptionText: String

    var bodyParagraphStyle: NSMutableParagraphStyle = {
        let style = NSMutableParagraphStyle()
        style.lineSpacing = 10
        style.paragraphSpacingBefore = 6
        style.paragraphSpacing = 6
        return style
    }()

    var headerParagraphStyle: NSMutableParagraphStyle = {
        let style = NSMutableParagraphStyle()
        style.paragraphSpacingBefore = 24
        return style
    }()

    var bodyAttributes: [NSAttributedStringKey: Any]
    var headerAttributes: [NSAttributedStringKey: Any]

    func attributeString(includeLineBreak: Bool = true) -> NSAttributedString {
        let result = NSMutableAttributedString()
        result.append(NSAttributedString(string: self.heading + "\n", attributes: self.headerAttributes))
        result.append(NSAttributedString(string: self.descriptionText, attributes: self.bodyAttributes))
        if includeLineBreak {
            result.append(NSAttributedString(string: "\n", attributes: self.bodyAttributes))
        }

        return result as NSAttributedString
    }

    init(heading: String, descriptionText: String) {
        self.heading = heading
        self.descriptionText = descriptionText
        self.bodyAttributes = [
             NSAttributedStringKey.font: UIFont(name: "Hoefler Text", size: 14)!,
            NSAttributedStringKey.paragraphStyle: bodyParagraphStyle
        ]
        self.headerAttributes = [
            NSAttributedStringKey.font: UIFont(name: "Avenir", size: 22)!,
            NSAttributedStringKey.paragraphStyle: headerParagraphStyle,
            NSAttributedStringKey.foregroundColor: UIColor.red
        ]
    }
}

结果:

Formatted text