Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing property values when initialiser is called

Tags:

This is a follow up from my previous question found here

I am using MarkdownTextView to add basic markdown to a UITextView. The TextView is a subclass of MarkdownTextView.

In my previous question when using copy and paste I got the following error

Fatal error: Use of unimplemented initializer 'init()' for class MarkdownTextStorage

Until I added the following initialiser to MarkdownTextStorage class

public override convenience init() {
    self.init(attributes: MarkdownAttributes())
}

public init(attributes: MarkdownAttributes = MarkdownAttributes()) {
    self.attributes = attributes
    super.init()
    commonInit()

    if let headerAttributes = attributes.headerAttributes {
        addHighlighter(MarkdownHeaderHighlighter(attributes: headerAttributes))
    }
    addHighlighter(MarkdownLinkHighlighter())
    addHighlighter(MarkdownListHighlighter(markerPattern: "[*+-]", attributes: attributes.unorderedListAttributes, itemAttributes: attributes.unorderedListItemAttributes))
    addHighlighter(MarkdownListHighlighter(markerPattern: "\\d+[.]", attributes: attributes.orderedListAttributes, itemAttributes: attributes.orderedListItemAttributes))

    // From markdown.pl v1.0.1 <http://daringfireball.net/projects/markdown/>

    // Code blocks
    addPattern("(?:\n\n|\\A)((?:(?:[ ]{4}|\t).*\n+)+)((?=^[ ]{0,4}\\S)|\\Z)", attributes.codeBlockAttributes)

    // Block quotes
    addPattern("(?:^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+", attributes.blockQuoteAttributes)

    // Se-text style headers
    // H1
    addPattern("^(?:.+)[ \t]*\n=+[ \t]*\n+", attributes.headerAttributes?.h1Attributes)

    // H2
    addPattern("^(?:.+)[ \t]*\n-+[ \t]*\n+", attributes.headerAttributes?.h2Attributes)

    // Emphasis
    addPattern("(\\*|_)(?=\\S)(.+?)(?<=\\S)\\1", attributesForTraits(.traitItalic, attributes.emphasisAttributes))

    // Strong
    addPattern("(\\*\\*|__)(?=\\S)(?:.+?[*_]*)(?<=\\S)\\1", attributesForTraits(.traitBold, attributes.strongAttributes))

    // Inline code
    addPattern("(`+)(?:.+?)(?<!`)\\1(?!`)", attributes.inlineCodeAttributes)
}

However once I did this then I got the following bug every time time I copy and paste.

enter image description here

It seems every time the user copy and pastes the initialiser is setting the default MarkdownAttributes before changing to font properties set in the ViewController. This screenshot is in between the text attributes being set.

This is how I use TextStorage in my ViewController to set the text attributes

let fonty = UIFont(name: font, size: fsize)

attributes.defaultAttributes[NSFontAttributeName] = fonty
attributes.orderedListAttributes?[NSFontAttributeName] = fonty
attributes.orderedListItemAttributes?[NSFontAttributeName] = fonty
attributes.unorderedListAttributes?[NSFontAttributeName] = fonty
attributes.unorderedListItemAttributes?[NSFontAttributeName] = fonty

let textStorage = MarkdownTextStorage(attributes: attributes)

Here is the MarkdownAttributes struct

public struct MarkdownAttributes {

let fonty = UIFont(name: "OpenSans", size: 30)

public var defaultAttributes: TextAttributes = [
    NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)

]

public var strongAttributes: TextAttributes?
public var emphasisAttributes: TextAttributes?

public struct HeaderAttributes {
    public var h1Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)
    ]

    public var h2Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)
    ]

    public var h3Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.headline)
    ]

    public var h4Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
    ]

    public var h5Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
    ]

    public var h6Attributes: TextAttributes? = [
        NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.subheadline)
    ]

    func attributesForHeaderLevel(_ level: Int) -> TextAttributes? {
        switch level {
        case 1: return h1Attributes
        case 2: return h2Attributes
        case 3: return h3Attributes
        case 4: return h4Attributes
        case 5: return h5Attributes
        case 6: return h6Attributes
        default: return nil
        }
    }

    public init() {}
}

public var headerAttributes: HeaderAttributes? = HeaderAttributes()

fileprivate static let MonospaceFont: UIFont = {
    let bodyFont = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
    let size = bodyFont.pointSize
    return UIFont(name: "Menlo", size: size) ?? UIFont(name: "Courier", size: size) ?? bodyFont
}()

public var codeBlockAttributes: TextAttributes? = [
    NSFontAttributeName: MarkdownAttributes.MonospaceFont
]

public var inlineCodeAttributes: TextAttributes? = [
    NSFontAttributeName: MarkdownAttributes.MonospaceFont
]

public var blockQuoteAttributes: TextAttributes? = [
    NSForegroundColorAttributeName: UIColor.darkGray
]

public var orderedListAttributes: TextAttributes? = [
    NSFontAttributeName: fontWithTraits(.traitBold, font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body))
]

public var orderedListItemAttributes: TextAttributes? = [
    NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body),
    NSForegroundColorAttributeName: UIColor.darkGray
]

public var unorderedListAttributes: TextAttributes? = [
    NSFontAttributeName: fontWithTraits(.traitBold, font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body))
]

public var unorderedListItemAttributes: TextAttributes? = [
    NSFontAttributeName: UIFont.preferredFont(forTextStyle: UIFontTextStyle.body),
    NSForegroundColorAttributeName: UIColor.darkGray
]

public init() {

}

}

Does anyone know how I can fix the bug so when the initialiser is called the values are set to the user defined values and not the default ones ?

like image 772
A.Roe Avatar asked Jan 09 '19 01:01

A.Roe


1 Answers

Add an init function that takes the user's defined values, and call your class or your superclass init() (depends what you want to do..)

You should add just one of the following functions, you don't want to add both of them:

public override init(attributes: MarkdownAttributes = MarkdownAttributes()) {
   super.init(attributes)
}

public override convenience init(attributes: MarkdownAttributes = MarkdownAttributes()) {
     init(attributes: attributes)
}

To call it, you can now use the code you showed above:

let fonty = UIFont(name: font, size: fsize)

attributes.defaultAttributes[NSFontAttributeName] = fonty
attributes.orderedListAttributes?[NSFontAttributeName] = fonty
attributes.orderedListItemAttributes?[NSFontAttributeName] = fonty
attributes.unorderedListAttributes?[NSFontAttributeName] = fonty
attributes.unorderedListItemAttributes?[NSFontAttributeName] = fonty

let textStorage = MarkdownTextStorage(attributes: attributes)
like image 91
Roee84 Avatar answered Oct 21 '22 04:10

Roee84