(Update from September 2014: it turns out simply calling the "string" method on the NSAttributedString works fine. For some reason it wasn't back when I first tried this and had to come up with this alternate approach. The alternate approach mostly works, but fails if you try adding attachments to the AttributedString. So - instead of all of the below, just use [richTextString string] and get on with the rest of your coding.)
I'm working on a major update to Remembary to support iOS7 and beyond. One of the most important new features is having the diary support full rich text and embedded attachments, with iOS7's enhanced use of NSAttributedString. Apple's rich text libraries are powerful, but they're quite complicated and seem to have accumulated a lot of extra cruft over the years.
After digging through the tutorials at raywenderlich.com, and even buying their book and going through the appropriate chapters, I've finally started getting the hang of working with NSAttributedStrings. I could add and remove formatting, and could even embed images.
There was one thing that continued to evade me, though: to ensure quick and easy searching and such, I need to be able to extract just the plain unformatted text from an NSAttributedString. The class has a handy "string" method, but the result includes all of the attribute information as well. I just wanted to get the plain text out.
Searching the internet and Stack Overflow didn't help me at all. People seemed to want to convert plain strings to attributed strings or attributed strings into HTML, but not to plain text. I thought I might be going crazy - surely I can't be the only one who has ever needed to do this?
I finally looked through some advice on turning attributed text into HTML, just to see the approach they used. Turns out it involves calling dataFromRange on an NSAttributedString while specifying a document type of NSHTMLTextDocumentType. I searched the official documentation for the document type values, and discovered it also included NSPlainTextDocumentType!
So after weeks of false starts and messy code and frustrating web searches, the solution turned out to be a mere four lines of code:
This is so simple it's hardly worth even mentioning - but I'm putting this here in case anyone else is similarly stuck. Warning: I just figured this out, so it's possible this doesn't work for everybody in all cases.