The general solution is to use stringWithFormat: to format each line. Presumably you are writing this to a file or socket, in which case you should write a data representation of each line (see dataUsingEncoding: in the file descriptor when you create it.
If you format many strings, you can use the initWithFormat: and explicit release messages to avoid running out of memory by piling up too many string objects in the autocomplete pool.
And always, always, always remember to avoid the correct values before passing them to the formatting method.
Escalation (along with cancellation) is a really good thing to write unit tests. Write the function in CSV format on one line and check the test cases that compare its result in order to correct the output. If you have a CSV parser, or you need it, or just want to make sure your escaping is correct, write unit tests to parse and undo, as well as escaping and formatting.
If you can start with a single record containing any combination of CSV special characters and / or SQL characters, format it, parse the formatted string and end up writing a record equal to the one you started with, you know your code is good.
(All of the above apply equally to CSV and HTML. If possible, you can use XHTML so you can use XML validation and analysis tools, including NSXMLParser.)
source share