iOS

There are 13 entries in this Category.

WWDC 2012 predictions

phil_schiller_mac_pro

Now, I don’t have any clue about anything, nor inside knowledge, and I have a terrible track record at predicting Apple’s actions, but because it’s fun and almost a tradition, here’s my predictions for WWDC:

  • Mac OS X 10.8 – Pretty much as you’d expect, no big new stuff.
  • iOS 6 – The poster’s been leaked. I have no clue what’s in it.
  • No product-line-wide Mac revision. Maybe individual ones, but not all of them at once. My guess is the Mac Pro will die (but not at WWDC, that’s too many Mac pro users in one place), and iMac and Mac mini will get beefed up now that they can’t cannibalize Mac Pro sales anymore and Thunderbolt can be a replacement for most expansion slot devices. If it’s the MacBook (Pro) and MacBook Air, the lines will be unified into flat notebooks without optical drives.
  • App Store and SDK for the Apple TV.
  • No new iPhone. The 4S is only 8 months old.

Feel free to leave your counter-arguments, predictions, links to your prediction list on your blog etc. in the comments.

Update: Struck through the things that didn’t happen.

  • Yes, the whole product line wasn’t revised, and, yes, the new MacBook Pro became a MacBook Air as predicted, but the old MacBook Pros are still there, and Apple actually announced a new Mac Pro for next year, and slightly speed-bumped the current ones. I think the general road map I devised for the Mac Pro will still happen, but I obviously didn’t get it right.
  • Nothing Apple TV related at all. sniff!

Common Cocoa Coding Patterns: UITableView row index enum

One of the things pretty much every iPhone application has is a table view containing a pre-defined list of main menu items that lead to deeper sections. Many people just hard-code this list and the item indexes, only to later find out that they need to display some rows conditionally. The code becomes a mess of conditional statements duplicated all over the place to adjust the indexes in the case that a certain item does not apply.

But there is an easier way. The first thing you do, is create an enum with the item indexes:

enum
{
    kMainTableRowInbox = 0,
    kMainTableRowTrash,
    kMainTableRowSpam,
    kMainTableNumberOfRows
};

Whenever you would use the indexes, e.g. in your table view data source and delegate methods, use these constants instead. You have the same code as before, but if you want to add/insert a new item, you can just add the constant for it in the right spot, and the rest of your code magically updates itself.

If you have one source file that implements the main list for several similar products, you can even use the preprocessor to remove items that are only needed for one device. However, what do you do if you dynamically need to add/remove items at runtime? E.g. if your application can talk to two kinds of servers, and one has a kMainTableRowTrash, but the other kind doesn’t? Simple: You create a look-up-table:

static NSUInteger          sRowLookUpTable[kMainTableNumberOfRows] = { 0 };
static NSUInteger   sRowLookUpTableSize = 0;

-(void) rebuildRowLookUpTable
{
    NSUInteger  actualRowNumber = 0;
    for( NSUInteger virtualRowNumber = 0; virtualRowNumber < kMainTableNumberOfRows; virtualRowNumber++ )
    {
        if( virtualRowNumber == kMainTableRowTrash && ![self haveTrash] )
            continue;
        sRowLookUpTable[actualRowNumber] = virtualRowNumber;
        actualRowNumber++;
    }

    sRowLookUpTableSize = actualRowNumber;
}

Call this in your init method(s), or whenever some state changes that may affect which rows should be shown. Change your table view delegate methods to use sRowLookUpTableSize instead of kMainTableNumberOfRows for the number of rows. And whenever you look at an index to compare it to one of the row index constants, do

sRowLookUpTable[indexPath.row]

instead of just

indexPath.row

to translate the real row index into one of the constants that indicate what content you want displayed. This way, most of your code never needs to know in which order which items are actually shown in your table. It just needs to be able to display all kinds of rows, and only -rebuildRowLookUpTable needs to actually know which rows are hidden or visible.

Also, the constant names make it obvious what row a bit of code is dealing with. If, two years after you wrote an app on contract, the customer comes back and wants it updated for MacBook Airs with iOS, and remove the settings category, you can just search for a kMainTableRowSettings constant in the text editor and get rid of all that code. Or just move the constant below the kMainTableNumberOfRows constant. All the code is still there, compiles, but the index will never be added to the table.

Software ideas up for grabs

In case there are any programmers out there who have lots of time on their hands and don’t know what to program, here’s a few ideas that I’m surprised nobody has implemented, along with my suggestions on how you could fairly easily implement them.

Web Site Layouter

CSS supports absolute positioning of elements. However, most tools available for WYSIWYG site design restrict how you can position stuff. iWeb comes pretty close, but just doesn’t give you enough flexibility for themes, and Sandvox and RapidWeaver both only flow text and objects and don’t let you just position stuff by dragging.

So, my idea is pretty simple: Create a tool that takes HTML and renders it on the screen. Design this as “layers”, each of which has its own entry with absolute positions and the left/top values defaulting to 0. Use a WebView to correctly render each layer at 0,0 and draw it into an offscreen buffer (i.e. NSImage). Then draw all of these layers into your document window. When the user clicks, you loop over your layers in the reverse order as you’re drawing them, and check the pixel at the click position whether it’s opaque or transparent. If it’s opaque, that layer was just clicked.

Now, when the user clicks a layer, let them drag the layer, live. Save the position, and draw the buffered layer at that offset position. When the user requests to upload the page to a server, write that position to the CSS file.

WYSIWYG item positioning and correct HTML rendering the easy way.

Now, the hard part will be to actually edit each layer. You could do plugin-like objects that just output HTML to render that layer. E.g. a “table” plugin and a “styled text” plugin, and you could even use the new cool NSTextView features in Tiger to let users pretty nicely WYSIWYG-preview their images embedded in text. But really, positioning is key. If you’re a proficient CSS-maven, you might even manage to add other cool features, like Interface Builder’s “resize springs” etc., though that wouldn’t be as easy as what I outlined above.

Another neat feature would be a “block hierarchy”. What I mean by that is that users and plug-ins can define block types, a block simply being a chunk of HTML. Many of these blocks will do their thing to other blocks. E.g. the page would be a block that has one area for the navigation block, and another for the content block, and draws the design around those.

One block could be a “box block” that simply renders a box in the current theme and then puts another block with the actual contents inside it. Another block could be a table of image thumbnails in a folder, another a list of files in a folder, yet another block could be a box with a link to an RSS feed, that automatically adds the correct meta tags to get the blue ‘RSS’ button in Safari’s URL bar.

The neat part here would be that blocks generate their HTML based on the current theme. So I can have lots of boxes in my text for common elements like callouts, images with subtitles etc., and when I change the theme, they all change to match.

And as I mention above, there could be native-code plugins that are also blocks, doing all kinds of magic.

Simple Database

Basically, the code for this has already been written. You just link to libSQLite, stuff the database file and a layout description file into a document package and slap a GUI on top. If you look at AppleWorks’ database module, that’s the kinda structure I’m aiming for. You create fields, you can put them on one or more layouts, you can edit, view and print a layout, and search through the fields in the database and show the results using a layout of your choice.

Slapping a GUI on top would essentially mean you code a WYSIWYG UI editor that lets users place text fields, check-boxes, radio buttons, pop-up menus, list boxes, fields with stepper controls (“little arrows”) and any other UI element you can think of on the screen. Each of these would be hooked up to one particular database field in a table. Keep in mind that users may want different views on the same fields, though.

So while they want to be able to just compose a window full of controls, they may want to print as a table/list one day, and as a stick-on label the other day. So, you’ll want to have some simpler and fancier styles as well as standard controls, and you’ll want a table view and list view (i.e. several records shown on the screen, with their controls, not just one).

Also, the database may contain more information than you’d want to print on a label for shipping, so allow for not having all fields in a layout. You’ll also want to offer some drawing tools in case someone wants to draw separator lines, boxes, or put a logo on his disk labels, and don’t forget a text tool for e.g. labelling (groups of) fields with text that doesn’t come from the database. Of course, we also want to store text and styled text in the database.

You’ll probably want to have one object that owns all the controls for a particular field in a particular layout. That way, a user can change the display style of a field. E.g. you could have a number field which can be shown as a slider, an edit field (with or without stepper control), or as a radio button group, or as a list field, or… So, you’ll want to be able to show the same field with a new style just by changing a property, but without losing the actual data.

Main purpose of this: Just general keeping and searching data on-disk (user accounts, info on books I lent out, database of addresses to send my newspaper to…), but also printing of lists and labels.

And once you have that finished, there’s always advanced features: File references (i.e. store an AliasRecord as a BLOb) would be kinda nice, as well as references to records in other databases. If you give each entry a unique ID, you could probably just store this unique ID, and store the database file for that ID along with the field definitions and layouts “globally” in your document (i.e., I don’t think you’d need to be able to have a different database for each record).

In addition, you could add a little expression parser that lets you create field values calculated from other fields’ values (e.g. calculate someone’s age based on their birth year, or concatenate a “product prefix” and “product version” field to generate a product code, or whatever…).

You can also go wild with regard to search, import/export, trigger AppleScripts when a particular field is changed, put a plainly readable XML version of a database into your package to make it easier to spotlight and to allow third-party apps to read your databases without having to restrict yourself when changing the database format… there’s a lot of cool features in there, but the basics are pretty trivial to implement and only require some time and polish.

Audiobook/Theatre Lines/Podcast Recorder

This last one is probably niche, so I’m not too surprised it hasn’t been done in this form. Still, I think it crosses enough markets that it would be possible to make a viable product out of this:

Basically, it would be an audio-recording app. Feature set not unlike Audacity (or an updated version of Farallon’s SoundEdit), but with one distinction: A workflow that allows me to set chapter markers by pushing a button during recording, and perform other simple but common editing tasks while the recording is still going. What for? Well, several uses:

  • In Podcasts, add chapter markers or put bookmarks in spots where e.g. the Skype recording has broken up.
  • In audiobooks, mark the start of a new sentence. If I mis-pronounce, I simply click a button, and everything up to the last chapter marker is marked for deletion. I simply read the sentence again (and again, and again) until I get it right.

So, the editing that happens would only consist of marking up the recording with metadata, and updating the display (which would probably be some sort of wave-form display with selection). There would be no need for the delays often caused by stopping and restarting the recording, as it would just keep going. Only once the recording has finished would the actual sentences be deleted. Heck, it wouldn’t even have to delete them right away, it could keep the various versions of the same chapter and let me choose between alternatives.

While Garage Band has a vaguely similar feature, it is aimed at musicians: You can mark an area that is a certain time long, start recording, and start playing your instrument. Once recording hits the end of the time range, it will then restart recording from the beginning and let you play a new version of this particular range. But it is always of fixed length. When I’m reading a novel as an audiobook, there is no predefined length for a sentence. I might try reading it fast, realize that doesn’t work, then want to re-read it more slowly.

So, why do I mention theatre lines here? Well, when I learn my lines for a play, what I usually do is I record everything into an MP3 and then listen to that on the morning commute. By hearing my lines every day, having them repeated to me over and over again, I can much more quickly memorize everything, and I can learn the lines on occasions where I can’t have the textbook in front of me. The general workflow is the same as an audiobook, though: Read text out loud, and delete any sentence I screwed up and record it again until it’s OK.

Any takers?

If anyone happens to implement one of these ideas or knows of applications that already do this, let me know. (And no, FileMaker or MySQL with phpMyAdmin don’t count – I want something small and simple, like Tables, but for databases/web sites).

Update: Added mention of blocks to web app.