Join Steven Lipton for an in-depth discussion in this video Read and write text files, part of iOS Development Tips Weekly.
- [Instructor] In iOS, one of the simplest forms of persistent data and the basis for many file formats is the text file. I'm going to show you one simple way to set up text files. I'll be making our demo in Swift Playgrounds based on a starter file I created called ReadWriteText. If it starts to run, hold down the Play button and select Manually Run and then stop it. There's two parts to reading and writing a text file: getting a file's name and then reading or writing the file. For file names, you can use either a string of the complete file path or a URL.
You'll find the URL is a lot more flexible in use. I'll get the URL for the document directory of the app using a computed property I started here. We'll make this URL using the FileManager class, which controls the file system. It has a singleton, Default, to point to the default file system. Add a dot after that and type url, and you'll see a few more methods. Select the method url(for: FileManager.SearchPattern for: URL?, create, the one right here, which returns the URL of a directory.
The for parameter is an enumeration with several options. For saving user files, we'll be using the document directory. The in parameter is the domain of the file system. For most applications, you're going to want to use userDomainMask; appropriateFor is for replacing directories, so leave that nil. If the directory does not exist, create it by making create true. This method throws errors, though you're sure that this directory will either be there or will be created in the app.
Add a try!, with an exclamation point, in front of FileManager to quiet any error checking. Next, I'll add a function to append a file name and extension to the URL directory, which I started calling fileURL here. Then I'll add return, and I'll start it again with our document directory URL, and then I'll use the appendingPathComponent and the appendingPatExtension methods here, and I'm going to start with the appendingPathComponent, which will be our file name, and here's our file name and our parameter.
And then I'll put the extension: the appendingPathExtension using fileExtension. So now I have a function for my fileURL. So now it's time to write the file, and I started a function here, writeFile. It has a string that I'm going to write, a file name, and a file extension. You notice at the end here, I've included a default value of txt so I don't have to write that every single time.
Now, I'm going to first get a URL, so I'm going to do let url = my function fileURL, the file name will be fileName, and the file extension will be fileExtension. Now here's the cool part. There's a method on the string type that writes directly to the file system if we give it a URL. It does throw errors, so I'll need a try here. So I'm going to put try writeString.write, and you'll see one here that says to: URL, atomically, encoding, and that's the one we're going to use.
Our URL is url. Atomically makes a temporary file while the operation's completing. I'm going to set that to true. And encoding is the type of encoding you're going to use for the string. I keep it simple and use utf8. Now, this again is a try, so we're going to have to do some error handling here and I'm going to use a full do catch. So I got do.
Catch. And I'm going to catch the error, so I'm going to do let error as NSError, and then I'll print out my error, so I'll write out Failed writing to URL at the URL that I have, and then Error, and then I'll concatenate the localized description. We've now set code to write a file. It would be a good idea to read it. Much of this code is the same.
Let's just copy this with the command C, command V to read it, and then we'll make a few little changes here. First of all, well it's going to be it's reading, so I'll change this to reading. I'm also going to need a string to return so I'm going to put here var readString, and I'm just going to make a blank string here. And then in our try is our big change here. Instead of writing a string, I'm going to read a string. So I'm going to delete all that and put in readString = try, and I'm going to use an initializer on String called contentsOf: URL, and that just asks for my URL, and that will take my URL and convert it into a string that'll be placed into readString.
And it's that easy. All I'll need to do is return my string. So we're ready to use this. Under the class, which I'll move up here a little, I already instantiated ReadWriteText, and I created two strings, message and textFileName. I can go ahead and type rwt.writeFile, and you'll see there's two writeFiles here, one for the one with the extension and one for the one with the default extension. I'm going to use the one, the default extension, and writeString: message, to: textFileName.
And then I'm going to just print that out, so I'm going to do print, and then I'm going to do rwt, and I'll read the file from the textFileName. And I'm ready to run. And I get my Hello, Pizza message on the bottom. And you can see all over here that it's working quite well, so the field has written and read. This sends the files to the documents. You can change the URL to send it to other places, including the bundle.
The power of text files does not remain with text alone. XML, CSV, and HTML files are all text files which could be read or written this same way.