Text File Workshop: Read Directory

When you tell the app to read a directory, you are in essence telling the app to fetch all content of a specific folder or subfolder and dump it in an array variable. The app will have to filter the array. Because it may contain items you aren’t interested in; for example, hidden files, hidden folders, PDF files, and so forth.

In our case we are only interested in files that have the extension, txt. So the app will have to loop through the results array, pluck files that have that extension and dump them in another array. Lets call that array filteredResults. At this point we can do what ever we want with the filteredResults array; for example, we can print it in the console or display it in a table view cells.

Code presented on this page assume you are using Xcode 7.0 and Swift version 2.0. So if you are using a older or newer version of Swift, it may produce errors. Fix them by using Xcode’s Fix-it tool. Also, I assume you aren’t a newbie to the Swift Programming Language and you know your way around Xcode Integrated Development Editor.

The User Interaction Table

Today, you will configure the NiftyTextFile project so the app can read the Documents directory, filter the results for text files and display them in a table view cells. Here is a User Interaction of the read a directory operation and output it will produce on the File List view.

User Action App Response
The user launch the app

niftytextfile-part3-2

The app respond by doing the following:

  • Declare two variables: fetchedResults and filteredResults.
  • Read the Documents directory and dump results in the fetchedResults array.
  • Loop through the fetchedResults array and check each item to see if they have the extension, txt. If so add it o the filteredResults array.
  • Display the File List view on the user’s device.
  • Loop through the filteredResults array and display each element (text file) in the File List’s table view cells.

Add a Scene and Class File in The Project

Since the app will read the Documents directory and display only text files in a table view; you’ll have to drag a View Controller from the object library and drop it on the left side of the Save File View Controller scene. Next, make the new scene the initial scene. Next, add a Cocoa Touch Class in the project and connect it to the new scene.

niftytextfile-part3-1

Configure The Scene

Use this table as a guide to configure the File List View Controller scene.

Control Attribute Outlet Note
Label Text: File List N/A
Alignment: center N/A
Font: System Bold 17.0 N/A
Table View Prototype Cells: 1 dataSource, delegate, tableView You’ll have to use the Assistance editor to create the tableView outlet. In the FileListViewController class file, it will look like this:
@IBOutlet weak var tableView: UITableView!
Table View Cell Style: Basic
Accessory: None
Identifier: cell
N/A

Once you’ve configured the File List View Controller scene, it should look like this:

niftytextfile-part3-0

Now, modify the FileListViewController class to look like this:

import UIKit

class FileListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    let File = TextFileManager()
    var fileList = [String]() // The tableView's dataSource
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Print the sandbox's Documents directory path in the console.
        print(File.getDocumentsDirectory())
    }

    override func viewWillAppear(animated: Bool) {
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Navigation

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    }

    @IBAction func unwindToMainView(segue: UIStoryboardSegue) {
    }
    
    // MARK: - tableView's data source functions
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return fileList.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell")!
        let currentFile = fileList[indexPath.row]
        
        cell.textLabel!.text = currentFile
        return cell
    }
    
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
        if editingStyle == .Delete {
            
            fileList.removeAtIndex(indexPath.row)
            tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
        }
    }
}

When you run the app on your real device or the Simulator, you will see an empty table view staring back at you. Also, you’ll see the full path to the Documents directory in the console.

The Read Directory Code

As you can see in above User Interaction table shown earlier on, you have to enter code in the FileListViewController class to read the Documents directory. Here is a function to perform that task. Put it in the TextFileManager class.

// This function fetch and return only text files to its caller
func readDocumentsDir() -> [String] {
  var textFileList = [String]()
  let docsDir = getDocumentsDirectory()
        
  do {
    let directoryItems: Array = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(docsDir)
            
    for item in directoryItems as [String] {
      if item.hasSuffix("txt") {
        textFileList.append(item)
      }
    }
            
  } catch let readError as NSError {
    print("Fetch files from the Documents directory failed for this reason:\n\(readError)")
  }
        
  return textFileList
}

Switch over to the FileListViewController.swift file and enter code shown below in the viewWillAppear() function. The code populate the dataSource of the File List’s table view and refresh its cells.

fileList = File.readDocumentsDir()
tableView.reloadData()

 Test The Read Directory Code

You’ve already entered code in the FileListViewController.swift file to populate the table view cells. So all you have to do now is run the app on your real device or the Simulator. The File List’s table view will now display filtered results fetched from he app’s Documents folder. If you did not add text files in the Documents folder, the table view cells will be empty.

niftytextfile-part3-2

Add a Buttons on The Scenes

Xcode is issuing this warning: “Scene is unreachable due to lack of entry points and does not have an identifier…” To make it go away, you’ll have to add a + button on the File List View Controller scene and connect it to the Save File View Controller scene, via a “show” segue. Also, set the segue’s Identifier attribute to “showSaveFileView”.

Next, add a Back button on the Save File View Controller scene and connect it to the scene’s Exit object. You do that by control-dragging from the Back button to the scene’s Exit object. When prompted, select the “unwindToMainView” Action Segue. Don’t forget to reset both scene’s constraints. The storyboard should look like this now.

niftytextfile-part3-3

Finally, run the app on the Simulator or your real device and test the add button (+) and Back button. They should work as intended.

What’s Next?

next-iconThat’s it. Now  you know how to read the Documents directory and display filtered results in a table view cells. Next week, you will implement the read a text file operation, in the NiftyTextFile project. Until then, comments are welcomed. 🙂