I'm trying to parse html text that contains a youtube video. To display this video I use a preview image.
Initial text:
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>\n<p><iframe loading=\"lazy\" title=\"Forza Horizon 5 : RTX 4090 24GB ( 8K Maximum Settings RTX ON / DLSS ON )\" width=\"500\" height=\"281\" src=\"https://www.youtube.com/embed/NcHyE_N1QDI?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen></iframe></p>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
And then it looks like these:
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p>\n<p><a href=\'https://www.youtube.com/watch?v=NcHyE_N1QDI\'><img src=\"https://img.youtube.com/vi/NcHyE_N1QDI/maxresdefault.jpg\" alt=\"\" width=\"393.0\"/></a></p>\n<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
Then I use NSMutableAttributedString and assign new value to the UITextView's attributedText property.
The question is how to overlay an image with a play button on top of the preview image so that the user understands that this is a video. I assume this can be done using CSS, but don't know how to properly embed it in the code.
My code:
private func formatStringWithYTVideo(text: String, with width: Float) -> String {
let iframeTexts = matches(for: ".*iframe.*", in: text)
var newText = text
if !iframeTexts.isEmpty {
for iframeText in iframeTexts {
let iframeId = matches(for: "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)", in: iframeText);
if !iframeId.isEmpty {
let htmlString = """
<p><a href='https://www.youtube.com/watch?v=\(iframeId[0])'><img src="https://img.youtube.com/vi/\(iframeId[0])/maxresdefault.jpg" alt="" width="\(width)"/></a></p>
"""
newText = newText.replacingOccurrences(of: iframeText, with: htmlString)
}
}
}
return newText
}
It looks like this can't be achieved via
UITextViewand CSS becauseUITextViewdoesn't support the required attributes. I see at least two solutions.1: Using
WKWebViewinstead ofUITextView.2: Using the
enumerateAttributes(in:options:using:)method. Get a list of attributes, find the desired image among them and replace it. You can create an image with an overlay usingUIImageViewand then convert it to anUIImageusingUIGraphicsImageRenderer.