12

Can somebody help me to load an rtf text into UITextView with Swift 2? The answers I've gotten are old and out of date. The text is instructions on how to play the game I'm writing in an app. So far, all I've been able to do is to copy and paste all the rtf text into the placeholder box. This works for iPhones in the simulator, but when trying it in the iPad simulator or iPhone 6 Plus there appears double vertical scroll bars when I do this. It looks messy.

I also now have a real plain text of the same file, so we can try that too.

Edward_JS
  • 149
  • 1
  • 6

4 Answers4

40

Swift 3

        if let rtfPath = Bundle.main.url(forResource: "SomeTextFile", withExtension: "rtf") {
            do {
                let attributedStringWithRtf:NSAttributedString = try NSAttributedString(url: rtfPath, options: [NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType], documentAttributes: nil)
                self.textView.attributedText = attributedStringWithRtf
            } catch let error {
                print("Got an error \(error)") 
            }
        }

Swift 4 & 5

    if let rtfPath = Bundle.main.url(forResource: "someRTFFile", withExtension: "rtf") {
        do {
            let attributedStringWithRtf: NSAttributedString = try NSAttributedString(url: rtfPath, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
            self.textView.attributedText = attributedStringWithRtf
        } catch let error {
            print("Got an error \(error)")
        }
    }
MikeG
  • 3,745
  • 1
  • 29
  • 51
  • 1
    thanks! works for "html" files as well with .DocumentType.html – ursa Feb 12 '18 at 16:55
  • On macOS, I got ```Value of type 'NSTextView' has no member 'attributedText'```. Maybe just use ```textView.string``` instead. – RoyRao Dec 21 '21 at 07:54
1
if let rtfPath = NSBundle.mainBundle().URLForResource("description_ar", withExtension: "rtf") 
{
    let attributedStringWithRtf = NSAttributedString(fileURL: rtfPath, options: [NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType], documentAttributes: nil, error: nil)
    self.textView.attributedText = attributedStringWithRtf
}
Charmi Gheewala
  • 818
  • 7
  • 9
  • I have tried this code and the compiler tells me that it cannot invoke initializer for NSAttributedString with the argument list provided. What am I missing? – Edward_JS Mar 02 '16 at 03:55
1

You can read rtf file use following code in Swift 2.

Load RTF file

    let path = NSBundle.mainBundle().pathForResource("sample-rtf", ofType: "rtf")

    let contents: NSString
    do {
        contents = try NSString(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
    } catch _ {
        contents = ""
    }

    let array : NSArray = contents.componentsSeparatedByString("\n");

    self.textView.text  = (array.objectAtIndex(0) as! String);

    //self.textView.text  = contents as String

Try using a plain text (txt) file instead of rtf. RTF files contain formatting information about the text as well. Thats the unnecessary stuff that you see after reading the content.

Open the rtf file in Mac TextEdit and press Cmd+Shift+T (this will convert it to plain text and remove all formatting) then save as a txt.

Load Text file

    let path = NSBundle.mainBundle().pathForResource("sample-text", ofType: "txt")

    let contents: NSString
    do {
        contents = try NSString(contentsOfFile: path!, encoding: NSUTF8StringEncoding)
    } catch _ {
        contents = ""
    }

     self.textView.text  = contents as String
Vignesh Kumar
  • 598
  • 4
  • 11
  • I added the above code and I still received errors. – Edward_JS Mar 02 '16 at 02:45
  • I received errors in the do - catch code that said "expected declaration", and I had to write code as 'let contents: NSString = "" ' because if I did not do so, compiler said the class has no initializers. So far, I can't test the code because it won't compile, and if I initialize contents variable, the error above arises – Edward_JS Mar 02 '16 at 02:55
  • I have made adjustments, putting the path constant below the @IBOutlet declaration, and the rest in ViewDidLoad() function, and made progress, but now the compiler has told me it found a nil while unwrapping an optional, for a fatal error. Why? – Edward_JS Mar 02 '16 at 03:53
  • The code compiles, and the problem is isolated to a "nil" value, and when I hover my mouse over the "path" variable, it tells me that it is nil. It follows with a bad instruction in the do --- catch code block. It seems that "path" is nil and is defined as nil in the let statement declaration. Why is it doing so? – Edward_JS Mar 03 '16 at 16:48
  • Whr you keep ur rtf file?? And what's ur xcode version?? – Vignesh Kumar Mar 03 '16 at 17:50
  • Further update: seems that the file was found, and I am no longer getting a nil message. The file is scrolling well, however, now I have all these format backslashes appearing instead just plain text. It looks like this: "\if a player \ rolls a three in his turn\" instead it should be "if a player rolls a three in his turn". How do I remove the "\" and such so it only displays the text? – Edward_JS Mar 03 '16 at 18:15
  • Further update again: I think I mis-spelled the original rtf file, and that's why the nil, because the program could not find the file due to the file not being spelled correctly in the code. I created another project using a plain text file and replaced the ofType with "txt", and the text came out fine. Thank you very much for your help! – Edward_JS Mar 03 '16 at 19:02
  • I have created sample project for you. can you try this..? https://www.dropbox.com/s/duj0jy9qknviwhb/LoadFile.zip?dl=0 – Vignesh Kumar Mar 04 '16 at 04:37
  • Don't use RTF file. Try to use text file. – Vignesh Kumar Mar 04 '16 at 04:37
  • Indeed, I used a text file and it worked fine. I learned that if I add a file to my project, Xcode puts it in my bundle, and I must not move it, because Xcode expects to find it where it put it. The code works fine. Thank you again, and it scrolls nicely as well. – Edward_JS Mar 05 '16 at 01:04
1

Swift 3 Code:

if let rtfPath = Bundle.main.url(forResource: "description_ar", withExtension: "rtf") {
    do {
        let attributedStringWithRtf:NSAttributedString = try NSAttributedString(url: rtfPath, options: [NSDocumentTypeDocumentAttribute:NSRTFTextDocumentType], documentAttributes: nil)
            self.textView.attributedText = attributedStringWithRtf
        } catch {
            print("We got an error \(error)") //or handle how you want
        }
}

Edits and updates inspired by @MikeG
October 21 update inspired by @RAJAMOHAN-S and @biomiker

Chucky
  • 398
  • 3
  • 15
  • This isn't proper Swift 3 code, see my posted answer – MikeG May 23 '17 at 20:41
  • @MikeG I apologize if it looks like I plagiarized, I honestly didn't :) Take a look at the edit, it'll show that i actually changed the relevant lines instead of just doing a full copy/paste. But yes, even though I didn't do that, thanks for pointing out the error in my code :) I do appreciate that. – Chucky May 30 '17 at 21:54
  • 1
    `let attributedStringWithRtf = try NSAttributedString(url: rtfPath, options: [:], documentAttributes: nil)` works in swift 3.0.2 – Rajamohan S Jun 17 '17 at 03:37
  • Still not correct for Swift 3. Use the MikeG's answer. The error: parameter isn't valid anymore. – biomiker Oct 19 '17 at 18:19