David Janes' Code Weblog

March 27, 2009

The Three20 Project: Photo viewer and more for the iPhone

ideas,iphone · David Janes · 4:59 am ·

This code could be very useful for iPhone developers:

The name of the new project is Three20, after the 320-pixel-wide screen of the iPhone. The code is all hosted on github for your cloning pleasure. There is an excellent sample app called TTCatalog which lets you play with all of the various UI components. Documentation? Well… there are instructions for how to add Three20 to your project, but I am still working on comprehensive documentation for each of the classes. For now, the sample app and the code itself are your documentation.

The projects are:

  • Photo viewer
  • Message composer
  • Web image views
  • Internet-aware table view
  • Better text fields (including type-ahead)
  • HTTP disk cache
  • URL-based navigation (this could be interesting)

The source base is under the Apache license.

March 26, 2009

How to: create a MySQL database and user

db · David Janes · 6:02 am ·

I always seem to forget this:

$ mysql -u root -p
Enter password: enter mysql-root-user passwd
mysql> CREATE DATABASE DATABASENAME
mysql> GRANT ALL PRIVILEGES ON DBNAME.* to "DBUSER"@"localhost" IDENTIFIED BY "DBPASSWORD";
mysql> FLUSH PRIVILEGES;
mysql> EXIT
$

March 23, 2009

iPhone How To: create a Simple Table

code fragments,iphone · David Janes · 8:08 am ·

If you have not created a XIB, do the following:

  • select Resources in the Interface Building
  • press ⌘N
  • select User Interfaces in iPhone OS
  • select View XIB … and create in the normal way

To create the Simple Table in the Interface Builder

  • open the XIB in Resources
  • drag the Table View from the Library to the View … it should resize to the full extent of the View
  • select the Table View object and press ⌘2
  • from the Outlets section, drag
    • dataSource to File’s Owner
    • delegate to File’s Owner
  • save

Make your Controller.h a data source and delegate for the table:

@interface ThemesController : UIViewController
<UITableViewDelegate, UITableViewDataSource>
{
}

Add the following basic code to the Controller.m file:

#pragma mark -
#pragma mark Table View Data Source Methods

- (NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger) section
{
  return  ... the number of rows ...;
}

- (UITableViewCell*) tableView:(UITableView*) tableView
  cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
  static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";

  UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
      reuseIdentifier: SimpleTableIdentifier] autorelease];
  }

  NSUInteger row = [indexPath row];
  cell.text = ... an NSString containing what to display for row row ...;
  // cell.image = [UIImage imageNamed:@"star.png"];

  return  cell;
}

#pragma mark -
#pragma mark Table Delegate Methods

- (void) tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
}

Compile and run.

iPhone How To: load a plist

code fragments,iphone · David Janes · 6:46 am ·

Property Lists – plists – are a standard way of storing data in iPhone and MacOS programs. Here’s how you use them on the iPhone.

Add this code to Controller.m to populate member listData with the data from plist dwarves.plist:

- (void) viewDidLoad
{
	NSBundle* bundle = [NSBundle mainBundle];
	NSString* plistPath = [bundle pathForResource:@"dwarves" ofType:@"plist"];

	NSArray* dwarves = [[NSArray alloc] initWithContentsOfFile:plistPath];
	self.listData = dwarves;
	[dwarves release];

	[super viewDidLoad];
}

To create the plist:

  • open and select the Resources folder in Interface Builder
  • right-click and select Add > New File…
  • select Other in the popup (at the bottom)
  • select the Property List icon and then press the Next button
  • choose your name and Finish

To edit the plist:

  • select it in the Resources Folder
  • right-click and select Open with Finder

Make sure:

  • the name of the plist in the code (dwarves) is the same as the plist you created
  • the type of the plist in the code (NSArray) is the same as the plist you created – by default it is actually NSDictionary, which is the other common option

March 13, 2009

AUAPI: how to encode geographic location

auapi · David Janes · 7:55 am ·

Geographic location is a little more problematic to encode than other data types we’ve looked at for the Almost Universal API. The issue is that standards for adding geographic information are either overly complicated or they encode information in a hard-to-use-from-JSON manner.

Using GeoRSS

GeoRSS provides two ways (well, way more I’m sure) of adding geographic point information to a blog post (which is essentially the same as AUAPI item). From the webpage:

<georss:point>45.256 -71.92</georss:point>

which would be encoded as:

{
 "georss:point" : "45.256 -71.92"
}

and

<georss:where>
   <gml:Point>
      <gml:pos>45.256 -71.92</gml:pos>
   </gml:Point>
</georss:where>

which would be encoded as:

{
 "georss:where" : {
  "gml:Point" : {
   "gml:pos" : "45.256 -71.92",
  }
 }
}

Neither of these look particularly satisfying because the lat/lon is encoded as a string. We could encode as an array of numbers, but then we have to write a custom transcriber for converting to XML.

Using hCard

Another option would be to use the geo.latitude, geo.longitude attributes in hCard. Unfortunately, hCard requires elements such as FN and in general imply that we are talking about a person or organization, so this isn’t really satisfying either.

How AUAPI recommends geographic information should be encoded

'geo': {
   'latitude': 34.743763,
   'longitude': -86.572568
}

This in fact, is exactly the microformat’s geo standard.

March 3, 2009

PortableContacts and the Atom syndication standard

auapi · David Janes · 6:56 am ·

Thanks to Kevin Marks, I’ve just stumble onto the Portable Contacts effort. They seem to have thought quite a bit about the hCard/vCard serialization issue. I’ve added my two bits, in particular making the claim that they should consider making there proposal more compatible with existing consumers and infrastructure by piggybacking on top of the Atom syndication format, rather than requiring PC consumers to redevelop all this infrastructure around their format. This, in essence, is what the Almost Universal API idea is about.


I’ve been thinking and writing recently about how APIs can be made compatible with each other – that is, the same consumers can be used with the results from different APIs – and Kevin Marks pointed me this way, as I had written about hCard serialization.

However, it occurs to me that PC could be made to overlay the Atom syndication standard with very few changes (by the looks of it, you’re fairly late into the design cycle though). For example, this:

{
  "id": "703887",
  "displayName": "Mork Hashimoto",
  "name": {
    "familyName": "Hashimoto",
    "givenName": "Mork"
  },
  "birthday": "0000-01-16",
  "gender": "male",
  "drinker": "heavily",
  "tags": [
    "plaxo guy",
    "favorite"
  ],
}

Could be encoded like:

{
  "id": "703887",
  "title": "Mork Hashimoto",
  "updated" : "2008-...",
  "published" : "2007-...",
  "category" : [
   { "term" : "plaxo guy", },
   { "term" : "favorite", },
  ],
  "contact" : {
    "name": {
      "familyName": "Hashimoto",
      "givenName": "Mork"
    },
    "birthday": "0000-01-16",
    "gender": "male",
    "drinker": "heavily",
  }
}

Which is almost the same, except now that your XML serialization can be Atom (noting of course there will be changes for the paging elements, etc. that you’ve defined). The immediate implication of this is that you’re working within a large existing infrastructure that knows about update notification, has tools for display, and so forth.

March 2, 2009

AUAPI: encode images using media:rss

auapi · David Janes · 4:34 pm ·

MediaRSS is the way to encode images in the Almost Universal API (AUAPI). Because MediaRSS encodes its values in attributes, we use the @ symbol to prefix keys.

Example 1 – a single image

'media:content': {
    '@medium': 'image',
    '@type': 'image/jpeg',
    '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_m.jpg'
}

Example 2 – thumbnail

'media:thumbnail': {
    '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_t.jpg'
}

Example 3 – multiple images in different sizes

'media:group': {
    'media:content': [
        {'@medium': 'image',
        '@type': 'image/jpeg',
        '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_m.jpg'},
        {'@medium': 'image',
        '@type': 'image/jpeg',
        '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_s.jpg'},
        {'@medium': 'image',
        '@type': 'image/jpeg',
        '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_b.jpg'}
    ],
    'media:thumbnail': {
        '@url': u'http://farm3.static.flickr.com/2165/2271778128_b59c01a695_t.jpg'
    }
}

AUAPI: encoding hCards in JSON

auapi,aumfp,semantic web · David Janes · 9:15 am ·

The best model for describing people is the vCard standard, RFC 2425 and RFC 2426. The microformats community has adapted the vCard standard for serialization into HTML using hCard. In the Almost Universal API (AUAPI), people and organizations should almost always be described using a JSON-encoded hCard.

It is difficult to describe, without going into great minutiae, what the difficulties are in transforming the hCard and vCard standards into a pleasant looking and more importantly an easy-to-use hierarchy: there are certainly a number of edge cases that one would have to deal with it! There’s certainly an argument for just encoding hCard/vCards as a straight vCard serialization – at least in terms of simplicity of encoding. The issue is that the end consumer (which I believe should be the strongest focus) really has to do the dirty work in grouping everything together themselves.

Algorithm

This algorithm is destructive to the data structure it works upon, so generally you’ll be make a copy first.

  • note that though we reference to all upper, mixed case, camel case and so forth hCard attributes, all attributes are actually physically encoded in lower case with “-” separators
  • let the “groupers” be ADR, GEO, N, ORG, TEL. Groupers group together attributes that are related (such as FirstName and LastName)
  • let the “narrowers” be Home, Work, Parcel, Postal (and no-narrower). Narrowers assign a specific meaning to a value, i.e. this a Work phone number.
  • assume each value is described by a number of attributes, i.e. “416-515-5555″ can be described by ( TEL, Work, Mobile )

Then:

  • for Narrower, then for each Grouper
    • create a dictionary ‘subd’
    • for each values that is described by the ( Narrower, Grouper )
      • for each remaining attribute (besides Narrower and Grouper), add to subd
      • if the value was fully described by ( Narrower, Grouper ), add to subd under the key ‘@’
    • for key, value in subd
      • add to the final result
      • if narrower is not ‘no-narrower’, add ‘@narrower = narrower’
    • add subd to the result under the key Grouper
  • add all remaining values from the original hCard to the result, noting that
    • if the value is described by a Narrower, we encoded it as a dictionary with ‘@narrower = narrower’

Clear? Well, the examples below will help. We the “416-515-5555″ above we would get:

{
 "hcard:hcard" : {
  'tel' : {
   '@work' : 'work',
   'mobile' : '416-515-5555',
  }
 }
}

Code

The source code for this algorithm is in the AUMFP tree, in file vcard.py function decompose (see around line 1083)

Namespace

All JSON encoded hCards are in the namespace hcard:. In the AUAPI serialization, this namespace should only be on the enclosing element, all children will be assumed to be in the namespace. I am currently using the URI http://purl.org/uF/hCard/1.0/ for this namespace (when XML serializing); this may change in the future.

Example 1 – home phone number from whitepages.com

{
 'hcard:hcard': {'adr': {'country-name': u'United States',
                         'locality': u'Huntsville',
                         'postal-code': '35801-2908',
                         'region': 'Alabama',
                         'street-address': u'1114 Humes Avenue NE'},
                 'fn': u'Jack Smith',
                 'geo': {'latitude': 34.743763000000001,
                         'longitude': -86.572568000000004},
                 'n': {'family-name': u'Smith', 'given-name': u'Jack'},
                 'tel': {'voice': u'256-539-8788'}},
}

Example 2 – work phone number from whitepages.com

{ 'hcard:hcard': {'adr': {'country-name': u'United States',
                         'locality': u'Gurley',
                         'postal-code': '35748-8715',
                         'region': 'Alabama',
                         'street-address': u'148 Little Cove Road'},
                 'fn': u'Jack Smith',
                 'geo': {'latitude': 34.698258000000003,
                         'longitude': -86.383027999999996},
                 'n': {'family-name': u'Smith', 'given-name': u'Jack'},
                 'org': {'organization-name': u'Alldyne Powder Technoliges'},
                 'tel': {'@work': 'work', 'voice': u'256-776-1238'}},
}

Example 3 – hCard directly to JSON

{ 'hcard:hcard': {
                 'adr': {u'country-name': u'United States of America',
                         u'locality': u'San Francisco',
                         u'region': u'CA'},
                 u'fn': u'Tantek \xc7elik',
                 u'logo': u'icon-2007-128px.png',
                 'n': {'family-name': u'\xc7elik',
                       'given-name': u'Tantek'},
                 u'photo': u'http://tantek.com/icon-2007-128px.png',
                 u'url': u'http://feeds.technorati.com/contact/tantek.com/#hcard'},
}

March 1, 2009

AUAPI: JSON to XML serialization

auapi,ideas,tips · David Janes · 8:40 am ·

Here is a brief outline of how one would “naively” transform Almost Universal API‘s (AUAPI) JSON into XML. We say “naive” because in general one wants to make a transformation into a specific XML application: Atom, RSS, OPML, KML, etc.. In those cases, one has to rename and rework certain elements first for standards compliance, then complete the naive transformation for remaining elements.

Walking

Walking JSON objects is done depth first. Most of the complexity involved is in handling dictionaries, which can be valued as being comprised of ( key, value ) pairs. For each dictionary, we are creating an XML node whose properties are defined as follows:

  • keys beginning with @@ are ignored
  • the key @ means “the text” of the  node (the examples will make this more clear)
  • other keys beginning with @ are attributes of the node
  • all other keys are defining children of the node

There are number of complexities that have to be addressed; for this I suggest looking at the examples or source code.

Namespace handling

  • collect all the namespaces used in the JSON and add to the root XML node
  • if any JSON element has a namespace, assume that namespace is inherited by its children

Code

You can see the code for this in the AUAPI source base in api.py in XMLAPIWriter.TranscribeNode.

Example 1

{
    "numbers" : [ 1, -0.23, ],
    "strings" : [ "bob", "caf\xe9", ],
    "booleanish" : [ True, False, None, ],
}
<root>
    <numbers>1</numbers>
    <numbers>-0.23</numbers>
    <booleanish>True</booleanish>
    <booleanish>False</booleanish>
    <booleanish />
    <strings>bob</strings>
    <strings>caf\xc3\xa9</strings>
</root>

Example 2

{
    "a1" : {
        "b1" : 1,
        "b2" : 2,
    },
    "a2" : {
        "b3" : "hi",
        "b4" : "there",
    },
}
<root>
    <a1>
        <b1>1</b1>
        <b2>2</b2>
    </a1>
    <a2>
        <b4>there</b4>
        <b3>hi</b3>
    </a2>
</root>

Example 3

{
    "@attribute" : "hello",
    "@bttribute" : "there",
    "a" : "some string",
},
<root attribute="hello" bttribute="there">
    <a>some string</a>
</root>

Powered by WordPress

Switch to our mobile site