Tuesday, December 11, 2012
HOWTO: MonoTouch Enterprise Deployment
Step 1.
First, you'll need to make sure that you've created and installed your "In-House" Distribution Certificate via Apple's iOS Provisioning Portal.
Step 2.
Open your Project Options in MonoDevelop and navigate to the iPhone Bundle Signing section.
If you've got MonoDevelop 3.1.0 or later, you'll be able to set your configuration to:
Otherwise you'll simply have to select your Provisioning Profile manually.
Once you've selected your signing certificate and provisioning profile, click the OK button to dismiss the Project Options dialog.
Step 3.
In MonoDevelop, click on the Build menu and select Archive. This will build your project and archive it in a location that Xcode will be able to see it in its Organizer window.
Step 4.
Launch Xcode and then click on the Window menu and select Organizer. At the top of Xcode's Organizer window, you will see an array of icons. Click on the one labeled Archives.
Find your application in the list of archives and select it.
Step 5.
Now click on the Distribute... button in the top-right area of the window and select Save for Enterprise or Ad-Hoc Deployment.
The next screen will prompt you for your code-signing certificate, providing you with a drop-down menu listing your available options.
Clicking Next will cause an action sheet to slide into view, prompting you for the location to save the AppName.ipa package and the AppName.plist file.
Important: Make sure to toggle the Save for Enterprise Distribution checkbox.
Once you've finished filling out all of the fields, click on the Save button.
Step 6.
You'll need to upload the saved AppName.ipa and AppName.plist files to your corporate web server in the location that you specified in the previous step. You'll also need a web page that will link to your app using a hyperlink similar to the one below:
<a href="itms-services://?action=download-manifest&url=http://internal.mycompany.com/Applications/AppName.plist">Install AppName!</a>
That's it! You're done!
Thursday, August 30, 2012
A Better Alternative to the TSA?
Most everyone agrees that going through airport security and being groped by the TSA is not only offensive, but also a major nuisance.
How about replacing the TSA with privately run airport security?
It sounds like San Francisco travelers much prefer their privately run airport security than the TSA at all other US airports.
Sunday, June 17, 2012
Beware Inflation
By a continuing process of inflation, government can confiscate, secretly and unobserved, an important part of the wealth of their citizens.
-- John Maynard Keynes, The Economic Consequences of the Peace
Wednesday, May 2, 2012
Saturday, March 17, 2012
Introducing MonoTouch.SQLite
I've been working on a personal side-project writing an app for the iPad that makes use of SQLite-Net, displaying that data in a UITableView.
Up until this past week, I had been using Miguel de Icaza's wonderful MonoTouch.Dialog library for displaying my data. Unfortunately, I wanted search filtering to be persistent, which means that I really needed to use Apple's UISearchDisplayController but I couldn't find an easy way to retrofit that onto MonoTouch.Dialog's DialogViewController to replace the simpler UISearchBar API that it currently uses. Since I had to look at creating an alternate solution, I figured I might as well solve the other potential problem I had with MonoTouch.Dialog, which is that my app really needed to be able to handle tables with a massive number of items. This brings us to...
MonoTouch.SQLite
MonoTouch.Dialog really made using UITableViews in iPhone and iPad apps trivial and I wanted to try and repeat at least some of that with MonoTouch.SQLite.
The first thing I had to do was to figure out a way of modeling the data in such a way as to allow a generic class to do most of the work for the developer. After a few sleepless nights of hacking last weekend, I figured out a fairly simple approach that seems to work pretty well. I started off thinking that I wouldn't be able to get around having to have a subclassable model, so I made most everything virtual. This is the public API that I came up with:
public class SQLiteTableModel<T> : IDisposable where T : new () { public SQLiteTableModel (SQLiteConnection sqlitedb, int pageSize, SQLiteOrderBy orderBy, string sectionExpr); // 2 ways of setting the search criteria public SQLiteWhereExpression SearchExpression { get; set; } public string SearchText { get; set; } // Gets the total number of table rows public int Count { get; } // Gets the number of table sections public int SectionCount { get; } // Gets the section titles public string[] SectionTitles { get; } // Gets the row count for a particular section public int GetRowCount (int section); // Get the index of an item public int IndexOf (T item, IComparer<t> comparer); // Convert item index into a section and row public bool IndexToSectionAndRow (int index, out int section, out int row); // Convert section and row into an item index public int SectionAndRowToIndex (int section, int row); // 2 ways of getting an item public T GetItem (int section, int row); public T GetItem (int index); // Reset the state of the model public void ReloadData (); }
You can see the full class implementation here.
It turns out, though, that it really isn't necessary to subclass my model unless you want to have finer control over the specific SQL query commands that it makes (all of those methods are virtual).
SQLiteTableViewController<T>
As I started porting my iPad app to use my SQLiteTableModel class, I started to realize that I could abstract a lot of my usage of the model into a reusable base class. What I came up with will blow your mind.
Are you ready?
In order to populate a UITableView with the contents of an SQLite table, all you have to do is subclass SQLiteTableViewController<T> and implement 1 method:
protected UITableViewCell GetCell (UITableView tableView, NSIndexPath path, T item)
That's it.
I've written up a sample iPhone app that illustrates just how easy this is.
But wait! There's more!
If you order in the next 30 minutes, you can also get this free complimentary Sham-Wow!
Okay, just kidding about that Sham-Wow! bit, but I wasn't kidding about there being more:
Remember when I said one of the problems I wanted to solve was persistent search filtering? Yea, well, I did it. SQLiteTableViewController handles all of that for you as well. In fact, give searching a try in that sample above.
At this point I bet you're thinking, "wow, how could this get any better?"
I'll tell you. Remember how SQLiteTableModel had 2 methods for setting the search criteria? Well, the one that takes a string parses it to create a SQLiteWhereExpression allowing the user to match against specific fields. For example, if you had the following data item:
public class Contact { public string FirstName; public string LastName; public string PhoneNumber; public string Address; public string Comments; }
...the user could type:
address:"Newton, MA"
and SQLiteTableModel would construct a query to match "Newton, MA" against only the Address field.
If the user, instead, types:
address:"Newton, MA" firstname:Jane
then the matches that would display in the list would be limited to contacts with a first name of "Jane" who live also in "Newton, MA".
I've also taken the liberty of implementing a SQLiteSearchAliasAttribute that allows you to specify aliases for your fields (or even the same alias to multiple fields!). For example, you could do this:
public class Contact { [SQLiteSearchAlias ("first")][SQLiteSearchAlias ("name")] public string FirstName; [SQLiteSearchAlias ("last")][SQLiteSearchAlias ("name")] public string LastName; [SQLiteSearchAlias ("phone")] public string PhoneNumber; public string Address; public string Comments; }
This would allow your users to use "name" to match against either FirstName or LastName!
It also means they can type "first" instead of "firstname" to match against only the first name, as in the above example.Where Can I Find This Awesome Library?
Glad you asked! You can find it on my GitHub page: MonoTouch.SQLite.
Well? What are you waiting for? Get hacking!
Sunday, February 12, 2012
Meet the Hackers
This past week, I've started to get back into photography a bit more (thanks, Nina!) and started taking my camera into the office with me every day to remind myself to take photos. As a result, I've taken a bunch of photographs of my co-workers in the office.
Would you like to meet the hackers?
The Founders
Most of you would probably recognize the infamous Miguel de Icaza, Xamarin's CTO:
Next up is our very own Steve Jobs, Nat Friedman, our CEO and the man who reminds us to pay attention to the details:
Another person many of you will recognize is our very own COO, Joseph Hill:
MonoDevelop Team
Well, okay, I've only got a photo of the famous Michael Hutchinson, but he's a very important player in the development of MonoDevelop.
QA Team
Next up, we have the QA team. They do their best to make sure that we, the developers, didn't break anything. When they aren't testing a specific application before a launch, they hammer away at our products and try to find weak spots in our code (but we still love them anyway!)
This is PJ, and as you can see, he's demonstrating how to QA popcorn corn cobs:
(Did it pass the test, PJ?)
Next up is Lindsey. She's been working on writing automated tests to make it less likely for releases to include regressions. Let's hope she's successful!
Release Team
Alex Corrado is the man behind the curtain. He's our head Release Team engineer and also the brilliant mastermind that started CXXI, the Mono C++ interop project that we hope to give him time to finish someday soon.
Web Team
The newest addition to our ranks (just this week, in fact!), but long-time contributor to the Mono project, is Bojan Rajković. You can see we've already put him to work (he is no doubt puzzling over some ASP.NET code on his screen).
Documentation Team
Nina is the only Cambridge resident on our Docs Team. Specifically, she hacks on our Documentation Portal. She's also the one who has encouraged me to get back into taking photographs, so she'll have to put up with me using her as a guinea pig the most. Here she is taunting me with her hot cup of Chaider: