Saturday, May 29, 2010

MonoTouch - List Documents

Use the following MonoTouch code to easily list all the files in your Applications Documents folder. First create a regular IPhone Navigation based Project.


Open "RootViewController.xib.cs" and add the following code. I only added five lines of code. I've put a "//EDITED:" comment in front of each line that I added. Make sure to add a "using System.Linq" to the top of the file as well.


partial class RootViewController : UITableViewController
 {
   //EDITED: list to hold file names.
  private System.Collections.Generic.List<string> dataItems = null;

  public RootViewController (IntPtr handle) : base(handle)
  {
  }

  public override void ViewDidLoad ()
  {
   base.ViewDidLoad ();
   //Show an edit button
   //NavigationItem.RightBarButtonItem = EditButtonItem;
   
     //EDITED: build list of files.
   string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
     dataItems = System.IO.Directory.GetFiles(path).ToList();
   
   this.TableView.Source = new DataSource (this);
  }

  /*
  public override void ViewWillAppear (bool animated)
  {
   base.ViewWillAppear (animated);
  }
  */
  /*
  public override void ViewDidAppear (bool animated)
  {
   base.ViewDidAppear (animated);
  }
  */
  /*
  public override void ViewWillDisappear (bool animated)
  {
   base.ViewWillDisappear (animated);
  }
  */
  /*
  public override void ViewDidDisappear (bool animated)
  {
   base.ViewDidDisappear (animated);
  }
  */

  /*
  // Override to allow orientations other than the default portrait orientation
  public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
  {
   //return true for supported orientations
   return (InterfaceOrientation == UIInterfaceOrientation.Portrait);
  }
  */

  public override void DidReceiveMemoryWarning ()
  {
   // Releases the view if it doesn't have a superview.
   base.DidReceiveMemoryWarning ();
   
   // Release any cached data, images, etc that aren't in use.
  }

  public override void ViewDidUnload ()
  {
   // Release anything that can be recreated in viewDidLoad or on demand.
   // e.g. this.myOutlet = null;
   
   base.ViewDidUnload ();
  }

  class DataSource : UITableViewSource
  {
   RootViewController controller;

   public DataSource (RootViewController controller)
   {
    this.controller = controller;
   }

   public override int NumberOfSections (UITableView tableView)
   {
    return 1;
   }

   // Customize the number of rows in the table view
   public override int RowsInSection (UITableView tableview, int section)
   {
    //EDITED: return count of files.
    return controller.dataItems.Count();
   }

   // Customize the appearance of table view cells.
   public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
   {
    string cellIdentifier = "Cell";
    var cell = tableView.DequeueReusableCell (cellIdentifier);
    if (cell == null) {
     cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
    }
    
    // EDITED: Configure the cell.
       cell.TextLabel.Text = (new System.IO.FileInfo(controller.dataItems[indexPath.Row])).Name;
   
    return cell;
   }

   /*
   // Override to support conditional editing of the table view.
   public override bool CanEditRow (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
   {
    // Return false if you do not want the specified item to be editable.
    return true;
   }
   */
   /*
   // Override to support editing the table view.
   public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, MonoTouch.Foundation.NSIndexPath indexPath)
   {
    if (editingStyle == UITableViewCellEditingStyle.Delete) {
     controller.TableView.DeleteRows (new NSIndexPath[] { indexPath }, UITableViewRowAnimation.Fade);
    } else if (editingStyle == UITableViewCellEditingStyle.Insert) {
     // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
   }
   */
   /*
   // Override to support rearranging the table view.
   public override void MoveRow (UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
   {
   }
   */
   /*
   // Override to support conditional rearranging of the table view.
   public override bool CanMoveRow (UITableView tableView, NSIndexPath indexPath)
   {
    // Return false if you do not want the item to be re-orderable.
    return true;
   }
   */

   // Override to support row selection in the table view.
   public override void RowSelected (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
   {
    // Navigation logic may go here -- for example, create and push another view controller.
    // var anotherViewController = new AnotherViewController ("AnotherView", null);
    //controller.NavigationController.PushViewController (anotherViewController, true);
   }
  }
 }

By default your app won't have any files in the documents folder but you can manually add some. In you user accounts "~/Library/Application Support/IPhone Simulator/" directory there will be multiple folders for each version of IPhone OS you can test. Pick the one you'll be test and put some files in the "Documents" folder.


Once that is done you can run your application in the simulator and it should give you the list of files you added to the "Documents" folder. Pretty simple huh?



I'll be using this code in a prototype that uploads Cycorder recordings from my IPhone 3G (I have a separate app for 3GS to use the built-in video recording) to Qwikcast, my company's WebCast presentation software. I'll be using SSH to create a symbolic link so Cycorder saves it's recordings to my applications Documents folder. Then I'll be doing a HTTP Upload to the Qwikcast web server where the video will automatically be encoded, published to a streaming media server, and then available on a "catalog" page for viewing (iPad and iPhone compatible of course) !