Reputation: 35
In my iOS/swift project I am loading a RTF document to a UITextView with the code below. The RTF itself contains styled text like "... blah blah [ABC.png] blah blah [DEF.png] blah..." which is loaded to the UITextView just fine.
Now, I want to replace all occurrences of [someImage.png] with an actual image as NSTextAttachment. How can I do that?
I am aware of the possibility to embed images in RTF documents, but I can not do that in this project.
if let rtfPath = Bundle.main.url(forResource: "testABC", withExtension: "rtf")
{
do
{
//load RTF to UITextView
let attributedStringWithRtf = try NSAttributedString(url: rtfPath, options: [.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
txtView.attributedText = attributedStringWithRtf
//find all "[ABC.png]" and replace with image
let regPattern = "\\[.*?\\]"
//now...?
}
}
Upvotes: 0
Views: 679
Reputation: 26096
Here is something that you could do.
Note: I'm not a Swift Developper, more an Objective-C one, so there may be some ugly Swift code (the try!
, etc.). But it's more for the logic on using NSRegularExpression
(which I used in Objective-C since it's shared in CocoaTouch)
So the main line directives:
Find where are the images placeholders.
Create a NSAttributeString
/NSTextAttachment
from it.
Replace the placeholder with the previous attributed string.
let regPattern = "\\[((.*?).png)\\]"
let regex = try! NSRegularExpression.init(pattern: regPattern, options: [])
let matches = regex.matches(in: attributedStringWithRtf.string, options: [], range: NSMakeRange(0, attributedStringWithRtf.length))
for aMatch in matches.reversed()
{
let allRangeToReplace = attributedStringWithRtf.attributedSubstring(from: aMatch.range(at: 0)).string
let imageNameWithExtension = attributedStringWithRtf.attributedSubstring(from: aMatch.range(at: 1)).string
let imageNameWithoutExtension = attributedStringWithRtf.attributedSubstring(from: aMatch.range(at: 2)).string
print("allRangeToReplace: \(allRangeToReplace)")
print("imageNameWithExtension: \(imageNameWithExtension)")
print("imageNameWithoutExtension: \(imageNameWithoutExtension)")
//Create your NSAttributedString with NSTextAttachment here
let myImageAttribute = ...
attributedStringWithRtf.replaceCharacters(in: imageNameRange, with: myImageAttributeString)
}
So what's the idea?
I used a modify pattern. I hard-wrote "png", but you could change it. I added some ()
to get easily the interesting parts. I thought that you may wanted to retrieve the name of the image, with or without the .png
, that's why I got all theses print()
. Maybe because you saved it in your app, etc. If you need to add the extension as a group, you may want to add it into parenthesis in your regPattern
and check what aMatch.range(at: ??)
to call. for using Bundle.main.url(forResource: imageName, withExtension: imageExtension)
I used the matches.reversed()
because if you modify the length of the "match" with a replacement of different length, the previous ranges will be off. So starting from the end could do the trick.
Some code to transform a UIImage
into NSAttributedString
through NSTextAttachment
: How to add images as text attachment in Swift using nsattributedstring
Upvotes: 1