Planet Cocoa

October 06, 2008

waffle

dynamic

It’s been kicking around for a while, but the first C# 4.0 keyword has been confirmed: dynamic. (In the slides to Anders Hejlsberg’s “Where Are Programming Languages Going?” keynote at JAOO.)

The code sample presented is this:

dynamic calc = GetCalculator(); 
int sum = calc.Add(10, 20);

The slide presents calc as being “statically typed to be dynamic”, the second row’s assignment as being a “dynamic conversion [to int]” and involving a “dynamic method invocation”. I can step to most of that. The parts that worry me are:

  • The var keyword and anonymous types worked perfectly with the existing type systems — the types exist and they are reproducibly the same at compile-time unless you change the initial assignment, you just can’t name them. Dynamism, on the other hand… What does dynamic calc; var type = typeof(calc); return?

  • Can you make methods that pass dynamic parameters? Can you make a generic class with dynamic parameters? (If not, are you just supposed to stuff these into ArrayLists or List<object>s.)

  • Consider a dynamic method that returns an array of two objects, both of distinct types. Chain the method call to an extension method on IEnumerable<T> that returns either the first or last object randomly — what type is a variable that calls this method? If you were to call this again, would the variable type change?

  • Can you write code that calls plain old CLR objects using dynamic? — crippling the code of everything that’s useful and efficient, sure, but avoiding a rift in the type system.

The big question is eventually “is this a compile-time alias (like var) or something that delivers a deeper change (invokedynamic-like) to the CLR?” My guess is that the usage suggests a generated interface. For the code sample above, there might be something like — and at any rate this might be what the IntelliSense store needs to remember:

interface <>_GeneratedDynamicInterface { int Add(int a, int b); }

(The int parameter types are simply because integer literals are 32-bit integers if they don’t exceed the range or carry suffixes like ‘u’ or ‘L’.)

Meanwhile, other parts of the slides suggests that it’s just going to wind up as the same thing rewritten in reflection calls (to things like InvokeMethod, only resolved a lot more resolutely thanks to the information the compiler can deduce in the same way that it finds the correct overloads for, uh, non-dynamic method invocation).

I have absolutely no idea how it’s going to work, though. It’s going to be very interesting to find out.

Moreover, I advise that the iPhone software platform must be opened.

by Jesper at October 06, 2008 09:46 PM

Uli's Web Site

CocoaHeads München

Ich habe gerade erfahren, dass eine CocoaHeads-Gruppe in München in der Planung ist. Treffen sind jeden zweiten Donnerstag im Monat also ist diesen Donnerstag das erste Treffen. Da gehe ich doch glatt mal hin. Würde mich freuen, die von Euch Mac-Programmierern, die auch im Raum München sind, dort zu treffen!

October 06, 2008 05:49 PM

Parmanoir

SseCGSConvertXXXX8888TransposePermute crash

When getting a CGImage via [myNSBitmapImageRep CGImage] to feed a CALayer, Core Animation may crash as detailed here : Changing CALayer's contents too rapidly causes CoreAnimation to implode. The given solution is to keep myNSBitmapImageRep around, retaining it.

Another workaround is to render the bitmap now : after creating your layer and setting its contents , use [CATransaction commit] and CA will draw it right away. CA will then display everything correctly, and you can forget about myNSBitmapImageRep.

by Patrick Geiller at October 06, 2008 12:50 PM

toxicsoftware.com

TouchMap

I was going to make a more in-depth posting about TouchMap, but then something kind of big happened. The code is however in the TouchCode google code repository. So have at it. (You’ll probably want to check out all of TouchCode, TouchMap currently depends on other code within the repository).

by schwa at October 06, 2008 12:31 AM

October 05, 2008

waffle

Brick

Please, let the “Brick” rumor be the one where they cut strong endurable laptop enclosures out of hunks of /alumini?um/ with water jets. Not only is it unspeakably cool, it would reduce the need for infrastructure like screws holding the thing together, which means it’d be slimmer and more solid.

Moreover, I advise that the iPhone software platform must be opened.

by Jesper at October 05, 2008 09:56 PM

October 04, 2008

toxicsoftware.com

Looking for iPhone Software Professionals?

The problem:

I make my living by writing iPhone and Mac OS X for hire. I’ve been doing this for a while with some level of success. But ever since the iPhone SDK was announced earlier this year I’ve been getting many, many more work enquiries than I could possibly handle. I’ve often referred enquiries to friends who I have either worked with in the past or whose work I respect. But this ad-hoc system doesn’t scale very well.

The Solution:

To try and make this informal referral approach work I’ve set up a private invite only Google Group called “iPhone Software Professionals”. Currently this group is made up of a handful (more than 10 less than 1000) software developers who specialise in iPhone development (although I’d say all are equally capable on Mac OS X). The group is made up of either people I have worked with personally (and would love to work with again) or people whose work has generated such a reputation that I would have no problem recommending them to a potential client.

The list is currently made up of software developers but I would like to open it open it up to any independent professional involved in the production of iPhone software. This includes, but is not limited to usability experts, graphic designers, quality assurance experts and so on.

The group will probably remain quite small, with new members invited and referred only by current members. There is no commission or finder’s fee involved, the group is just an informal group of professionals forwarding work that would otherwise be rejected.

Looking for an iPhone Software Professional?

So if you have some iPhone software that needs to be written then I think I might be able to find someone to help you out. I might be able to help you myself, but if I have more work than I can handle (which currently is very likely) I’ll forward your request to the group. Either way contact me directly at iphoneswpro@toxicsoftware.com and I’ll try make sure your software gets written.

by schwa at October 04, 2008 09:38 PM

Cocoa Is My Girlfriend

Announcement: Marcus will be a Panelist at O’Reilly’s iPhoneLive conference

Now that the NDA has been lifted we can all finally come out of the closet :)

If you have not heard, O’Reilly is hosting a conference on November 18, 2008 to discuss all things iPhone. I have been invited to attend the conference as a Panelist.

Please come and join the conference, if nothing else, to heckle me :)

iPhone Live

The list of speakers (as opposed to panelists), is quite impressive and definitely worth the trip.

Speakers

by Marcus Zarra at October 04, 2008 04:34 PM

Cocoa With Love

Sliding UITextFields around to avoid the keyboard

It's an iPhone post because I finally can. Here's a good way to slide your view around when editing UITextFields so that they never get trapped under the onscreen keyboard.

I'll be giving a talk at the Brisbane Cocoaheads meeting this Monday evening (Oct 6). Come along and heckle.

Hidden text fields

The iPhone's onscreen keyboard occupies the bottom 216 pixels on screen (140 in landscape mode). That's around half the screen, so if you ever have a text field you want to edit in the bottom half of the screen, it needs to move or it will get covered.

You can just animate the whole window upwards by the height of the keyboard when editing a text field in the bottom half but this doesn't work well for text fields in the middle (they can get moved too far up).

Instead, I'm going to show you a method which divides the window as follows:

slidingsections.png

Everything in the top section will stay still when edited. Everything in the middle section will animate upwards by a fraction of the keyboard's height (proportional to the field's height within the middle section). Everything in the bottom section will animate upwards by the keyboard's full height.

Implementing the delegate methods

All of the methods shown here should go into a view controller probably the "main" view controller for the current screen (i.e. the visibleViewController of the current UINavigationController, your RootViewController or other top-level view controller).

You will need to make this view controller the delegate (in Interface Builder) for every UITextField you want to animate.

Your view controller will need the following instance variable:

CGFloat animatedDistance;

The following constants should also be declared somewhere (likely the top of the view controller's implementation file):

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 140;
Animate upwards when the text field is selected

Get the rects of the text field being edited and the view that we're going to scroll. We convert everything to window coordinates, since they're not necessarily in the same coordinate space.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect textFieldRect =
        [self.view.window convertRect:textField.bounds fromView:textField];
    CGRect viewRect =
        [self.view.window convertRect:self.view.bounds fromView:self.view];

So now we have the bounds, we need to calculate the fraction between the top and bottom of the middle section for the text field's midline:

    CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;
    CGFloat numerator =
        midline - viewRect.origin.y
            - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
    CGFloat denominator =
        (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
            * viewRect.size.height;
    CGFloat heightFraction = numerator / denominator;

Clamp this fraction so that the top section is all "0.0" and the bottom section is all "1.0".

    if (heightFraction  0.0)
    {
        heightFraction = 0.0;
    }
    else if (heightFraction > 1.0)
    {
        heightFraction = 1.0;
    }

Now take this fraction and convert it into an amount to scroll by multiplying by the keyboard height for the current screen orientation. Notice the calls to floor so that we only scroll by whole pixel amounts.

    UIInterfaceOrientation orientation =
        [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
    }
    else
    {
        animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
    }

Finally, apply the animation. Note the use of setAnimationBeginsFromCurrentState: — this will allow a smooth transition to new text field if the user taps on another.

    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y -= animatedDistance;
    
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    
    [self.view setFrame:viewFrame];
    
    [UIView commitAnimations];
}
Animate back again

The return animation is far simpler since we've saved the amount to animate.

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y += animatedDistance;
    
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    
    [self.view setFrame:viewFrame];
    
    [UIView commitAnimations];
}
Since we're writing the delegate methods...

This next method has nothing to do with animation but since we're writing the delegate methods for a UITextField, this is essential. It dismisses the keyboard when the return/done button is pressed.

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

Result

For a window that looks like this:

textfieldwindow.png

Editing text fields in the top, middle and bottom sections will look like the following:

slidingpositions.png

Notice in particular how the middle section remains in the middle of the visible area after the keyboard appears. This is the primary benefit of the presented approach.

by Matt Gallagher (noreply@blogger.com) at October 04, 2008 05:26 PM

October 03, 2008

Gus Mueller

Acorn free for registered DrawIt 3 users

Pieter Omvlee: Compensating for Bitmap: Acorn for registered DrawIt users

'''Those of you who read my previous post will know that I removed the bitmap editing from DrawIt Pro. It’s fairly uncommon to remove features, especially if they are this important, but DrawIt’s bitmap editing has never been that good.
...
When I decided to remove it, I knew I had to compensate the current users and I think I succeeded here and I’m sure you’ll agree. Some time ago I contacted Flying Meat’s Gus Mueller with a shy attempt at maybe getting a discount for Acorn for current DrawIt users. To my joy he even proposed to give away a free licenses of Acorn to all registered DrawIt users.'''

October 03, 2008 06:32 PM

waffle

Helpful

Omni Group releases their Python Help Book builder scripts. Takes OmniOutliner files and emits an Apple Help Book, apparently. Awesome. Huge. It’s a great move.

(And I don’t know if my recent posts had anything to do with tipping the scale, but I assume not; they were about code documentation, not help generation. )

by Jesper at October 03, 2008 06:20 PM

Kupuk

The Future of TV

Is this the future of TV? An endless stream of Twitter chatter overlaying everything everyone says?

debate_twitter.png

by Paul Robinson at October 03, 2008 11:32 AM

toxicsoftware.com

Obama 08

Well, the project I was so excited about last week has now officially seen the light of day and is on the iPhone AppStore. The project is the Official iPhone application for the Obama/Biden ‘08 campaign (Direct link to AppStore!).

The application was created in less than three weeks by an all volunteer team of ten developers, artists, web designers, quality assurance specialists and project managers. You can see the name of everyone who worked on it in the credits of the application itself.

I started work on the application the day after C4[2] after some very clandestine meetings in Chicago. After about a week of writing TouchRSS code on my own, the project suddenly jumped into high gear, with the indomitable Mike Lee, Tristan O’Tierney and incredibly talented Louie Mantia (responsible for the application’s amazing and distinctive look).

I feel really honoured to have worked with such a great team (see Raven Zachary’s blog posting for links to everyone). The project was a sprint and of course suffered from a lot of ups and downs. But I think we managed to create a really great application in a very short space of time.

Here are some blog postings from the other team members

Official Links:

by schwa at October 03, 2008 04:54 AM

October 02, 2008

Fun Script

Alpha 6


You can now download F-Script 2.0 alpha 6. It contains the latest developments, including:

  • Better error detection and reporting when defining new classes
  • Support in the runtime for subclassing F-Script classes in Objective-C
  • A literal syntax for hexadecimal numbers (finally!). Standard Smalltalk syntax; e.g., 16rFF5A.
  • Support for using the ~~ message with nil as a receiver
  • Various internal improvements

In addition, there will be a couple of language adjustments in F-Script 2.0, and this alpha contains one of them, as described below.

In F-Script 1.x, equality and inequality operators (i.e., = and ~=) are provided for all objects. They are implemented in a category of NSObject, and rely on the standard Cocoa isEqual: method to determine equality.

This is convenient but leads to a small amount of added conceptual complexity in a few situations related to array programming. Since life is better when even the slightest unneeded complexity is taken away, F-Script 2.0 changes this (remember that F-Script integrates array programming and Cocoa together and we want to do it with zero impedance mismatch). In F-Script 2.0, = and ~= are no longer provided at the NSObject level. The standard generic method for testing objects equality in Cocoa is isEqual:, and you can use it with F-Script too.

Of course, just removing = and ~= and be done with it would horribly break compatibility between F-Script 2.x and code written for F-Script 1.x. In addition, we would really miss these nice operators…

Well, don’t panic. While these operators are no longer provided by default for all objects, they are implemented for a number of objects, such as NSString, NSNumber, NSDate, NSValue, FSBoolean… This covers the vast majority of current and desirable usage and you can also implement them for your own classes if that make sense.

In addition, F-Script 2.x comes with the magic needed to maintain backward compatibility with existing code in the few remaining cases where your F-Script 1.x code might send = or ~= messages to objects that relied on the default implementation provided by the NSObject category in F-Script 1.x. In such cases, all will work as usual and F-Script will log a warning suggesting you change your code to use isEqual:.

If you want to, you can turn off this magic backward compatibility system by using the MaintainFScript1EqualityOperatorsSemantics user default, on an per application basis. For instance, to turn it off for the F-Script application, type the following in the Mac OS X terminal:


defaults write org.fscript.fscriptapp MaintainFScript1EqualityOperatorsSemantics NO

To reactivate it, type:


defaults write org.fscript.fscriptapp MaintainFScript1EqualityOperatorsSemantics YES
      

by Philippe Mougin at October 02, 2008 07:38 PM

waffle

Buzzword Bingo

Microsoft is running a feature week on Channel 9 in honor of Visual Studio Team System 2010.

I live in Visual Studio at work. I should be excited at at least something. I’m not.

Update: This is a bit more like it.

by Jesper at October 02, 2008 05:32 PM

Matt Legend Gemmell

Logbook for Backpack Journal

Just a quick note that Logbook by SignalApps has been released today. It’s a client for the Backpack Journal from 37signals (part of Backpack), and lets you manage your tasks and status right from your Mac OS X menubar.

Logbook screenshot

Instinctive Code (my OS X/iPhone development persona) is pleased to have been part of the development team for Logbook, providing custom UI work amongst other things.

If you’re a Backpack user, be sure to check it out - and keep an eye out for future releases from SignalApps to integrate with your favorite other 37signals web apps.

Clarification: please contact SignalApps themselves (support at signalapps.com) with any enquiries or comments regarding Logbook - I’m not actually part of the company. :)

by Matt Legend Gemmell at October 02, 2008 04:37 PM

MGTwitterEngine works on iPhone

Now that the iPhone SDK is to be lifted, this is just a brief official announcement that MGTwitterEngine works on both OS X and on iPhone - as has quietly been the case for quite some time.

Previously, in order to ensure that MGTwitterEngine did not violate the NDA, iPhone developers needed to change a few constants to valid iPhone SDK values in order to make the code compile for that platform, but this is now thankfully no longer necessary. The ReadMe file included with the source now makes explicit reference to the iPhone, and restores Craig Hockenberry’s original notes on linking to libxml on each platform.

I’m sure you’d all discovered all this for yourselves already, but it’s nice to no longer have to obfuscate the code or avoid mentioning a significant benefit - that of being dual-platform. I have some other iPhone code I plan to release soon too, once I get a chance to clean it up a bit, so stay tuned.

by Matt Legend Gemmell at October 02, 2008 04:29 PM

Red Sweater Blog

I’ve Been Macbroken

I was honored this week to be invited as a guest host on the excellent MacBreak Weekly podcast.

MacBreak Weekly 108: Pull My iTunes

I listen to the show regularly so it was a bit strange to record with the guys I’m normally listening to passively. Every so often I had to remind myself that I could actually open my mouth and add something to the conversation!

A particularly well-timed (or poorly-timed, depending how you look at it) topic was that of the iPhone developer NDA, which we discussed a bit, carefully tip-toeing around any actual violation of the NDA, which was still in effect when we recorded, but was lifted a day later.

Developer Austin Meyer of X-Plane fame was also on the show, and one of the points we disagreed upon was whether or not it is productive for people outside Apple to present dissenting opinions or otherwise make a fuss about the inner workings of the company.

Austin tended to believe that we should trust Apple to work its magic in secrecy and with autonomy. I believe those of us on the outside can offer a unique perspective which Apple is itself sometimes blind to. A number of positive changes have happened in the past few years only after the public collectively agreed that Apple was taking the wrong course. It’s possible that Apple’s decision-making process has always been completely independent of outside influences, but I prefer to believe that they value the collective wisdom of their customer base, and are at least taking it into consideration as they develop their products and services.

I really appreciate Leo Laporte’s letting me take part in the show this week. If you haven’t given MacBreak Weekly a try before, this would be a great week to start!

by Daniel Jalkut at October 02, 2008 04:19 PM

Cocoa With Love

Implementing countByEnumeratingWithState:objects:count:

If you want to use fast enumeration on your own classes, you must implement countByEnumeratingWithState:objects:count:. Unfortunately, it's a confusing method. Here are two sample implementations that show the steps needed to implement this method in most cases.

Some sample NSFastEnumeration implementations

You need to implement NSFastEnumeration if you want to use your own classes in the Objective-C 2.0 "for...in" fast-enumeration language feature.

The documentation for its only method (countByEnumeratingWithState:objects:count:) is pretty cryptic and overwhelming — mostly because the method needs to be flexible and Apple don't want to tell you how to write your code. I have no such qualms and since there aren't many examples on the Internets at the moment I thought I'd show you some easy approaches for implementing it in your own programs.

There are two different ways to enumerate. The first is where your class already has, or is willing to create, a C array of Objective-C id values which point to the objects being enumerated. The second is where you don't have this storage and want to use storage passed to you.

Warning: These examples do not use the mutationsPtr and are therefore only safe for use with immutable collections. If the enumerated collection is mutable, you will need to point mutationsPtr to an appropriate mutation guard value (normally a mutations count value).

First case: already have a C array of storage

Our class looks like this:

@interface SimpleStringArray : NSObject <NSFastEnumeration>
{
    NSString *stringArray[ARRAY_LENGTH];
}

In this case, the implementation of countByEnumeratingWithState:objects:count: would look like this:

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
{
    if (state->state >= ARRAY_LENGTH)
    {
        return 0;
    }

    state->itemsPtr = stringArray;
    state->state = ARRAY_LENGTH;
    state->mutationsPtr = (unsigned long *)self;
    
    return ARRAY_LENGTH;
}

Quick explanation:

  • we've ignored stackbuf and count (because we already have storage)
  • as required, we've set state->state to a non zero value (the iteration index after the current items are iterated)
  • as required, we've set state->mutationsPtr to a non zero value (the self pointer since we have no "array has changed" flag that we can point it to)
  • we've returned the complete length of the array, so it will all be iterated in one pass (on the second pass, state->state will equal ARRAY_LENGTH and we'll return "0", ending the loop)

Second case: need storage

If our class' data is a collection of NSString objects stored in a list of linearly connected C structs, then we might have no C array value to return.

Assume our list is declared like this:

typedef struct
{
    NSString * stringPtr;
    struct MyList * nextNode;
} MyList;

and our class is declared like this:

@interface StringList : NSObject <NSFastEnumeration>
{
    MyList * _startOfListNode;
    MyList * _endOfListPlusOneNode;
}

This is more complicated example because we need to actually gather the data from the list and store our traversal state between iterations. Here is how it might look:

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
{
    MyList *currentNode;
    if (state->state == 0)
    {
        // Set the starting point. _startOfListNode is assumed to be our
        // object's instance variable that points to the start of the list.
        currentNode = _startOfListNode;
    }
    else
    {
        // Subsequent iterations, get the current progress out of state->state
        currentNode = (struct MyList *)state->state;
    }
    
    // Accumulate nodes from the list until we reach the object's
    // _endOfListPlusOneNode
    NSUInteger batchCount = 0;
    while (currentNode != _endOfListPlusOneNode && batchCount  len)
    {
        stackbuf[batchCount] = currentNode->stringPtr;
        currentNode = currentNode->nextNode;
        batchCount++;
    }

    state->state = (unsigned long)currentNode;
    state->itemsPtr = stackbuf;
    state->mutationsPtr = (unsigned long *)self;

    return batchCount;
}

Explanation of this example:

  • We now use stackbuf to store the data accumulated from the list and we return it in state->itemsPtr.
  • len is used now because it is the maximum number of objects we can accumulate in stackbuf each time.
  • When executed the first time (when state->state == 0), we set the currentNode to our object's private _startOfListNode — that we assume we have correctly set to the start of our list.
  • Every other time we are run, state->state will hold our currentNode, saved from the last iteration.
  • The fast enumeration will repeatedly invoke this method until we reach a currentNode == _endOfListPlusOneNode at the end of the list — remember that state->state is not allowed to be nil, which is why we use this non-nil end marker node. If you use a list that ends in nil, then you should detect this and set state->state to a special non-nil "end" flag so that you won't get trapped in an infinite loop.

by Matt Gallagher (noreply@blogger.com) at October 02, 2008 04:02 PM

rentzsch.com : tales from the red shed

PSIG 118: Thu Oct 2 2008

When:
Thursday, October 2nd, 2008 @ 7pm
Where:
Hotel Indigo (pic, directions from the Arlington Park Metra station).
Schedule:
Show & Tell
We'll start out the meeting by going around the table and talking about what we're currently working on or learning about. Handouts are welcome, or bring along your Mac and we'll hook it up to the projector.

Book Reports
Bring along the book you're currently reading, or one of your old favorites. Hopefully the book would have some relevance to programming, but we're fairly open-minded. Just give us an overview the book's topic, and what you liked (or disliked) about it.

Topics
Celebrating the death of the iPhone NDA, Tom Swift will present "iPhone Development: Zero to Sixty". Tom will walk us through all the steps of creating a new app, including the tricky parts of actually getting it loaded on your iPhone/iPod Touch. Brace yourself, it's a bumpy ride.

Dinner
If you want pizza, bring along three dollars and we'll all chip in.

Looking for Presenters:
I'm always on the look-out for folks to want to give a talk for a meeting. The talk doesn't need to be long (10 minutes is fine if your topic is small or you just want to tease the group) and you don't need to be an expert (just tell us why you think your topic is cool or your experiences). Toss me an email and I'll assign you a chunk of time.

October 02, 2008 05:02 AM

October 01, 2008

fiam

Apple removes the NDA!!

Apple has just lifted the NDA for released software, so we can now publicly talk about it. Over the last few weeks, I've been writing the iPhone client for byNotes, so I have a good amount of things to write about. Expect some iPhone entries soon ;).

October 01, 2008 09:37 PM

toxicsoftware.com

TouchMap Teaser

A quick teaser for TouchMap. I’m hoping to release this on TouchCode later today.

TouchMap.mov

by schwa at October 01, 2008 08:58 PM

Red Sweater Blog

Apple Lifts iPhone Developer NDA

Apple made the right choice today, in choosing to publicly lift the non-disclosure agreement which has, for the past several months, prevented iPhone developers from discussing specifics of the platform and development process.

I’m sure most of you have already heard the news, it’s being shouted from the rooftops on venues such as Twitter, but I wanted to make my own announcement, as I think many developers should do.

Why? Because as much as we cry and whine in the face of Apple’s misguided actions and policies, we should be prepared to turn around and laud them when they do the right thing. Today, Apple deserves to be lavished with praise from all corners of the iPhone developer world.

You go, Apple.

Apple’s statement, reproduced here in entirety because the page has a temporary look to it:

To Our Developers

We have decided to drop the non-disclosure agreement (NDA) for released iPhone software.

We put the NDA in place because the iPhone OS includes many Apple inventions and innovations that we would like to protect, so that others don’t steal our work. It has happened before. While we have filed for hundreds of patents on iPhone technology, the NDA added yet another level of protection. We put it in place as one more way to help protect the iPhone from being ripped off by others.

However, the NDA has created too much of a burden on developers, authors and others interested in helping further the iPhone’s success, so we are dropping it for released software. Developers will receive a new agreement without an NDA covering released software within a week or so. Please note that unreleased software and features will remain under NDA until they are released.

Thanks to everyone who provided us constructive feedback on this matter.

No longer any need to ask forgiveness, now that we’ve got permission to productively discuss the development process. Thanks again, Apple!

by Daniel Jalkut at October 01, 2008 04:50 PM

Uli's Web Site

The NDA is dead! long live the ... err...

The iPhone NDA has been taken down . Or rather, will be in a bit. At least for released stuff, which approaches normalcy. Thanks, Apple! We love you again. Well, except for that review process, but this is better than nothing.

October 01, 2008 04:32 PM

Matt Legend Gemmell

iPhone NDA to be lifted

Apple has today updated its iPhone Developer Program portal with a message indicating that the NDA (non-disclosure agreement) for the iPhone SDK is to be “dropped for released iPhone software” (which presumably means versions of the iPhone SDK which correspond to publicly released versions of the iPhone firmware - at time of writing, this would be the iPhone SDK for firmwares 2.0 and 2.1). I’ve archived the text of the message here.

This change is to take place within a week or so of the date of this post (Wednesday 1st October 2008), when developers will receive an updated agreement with the new terms. This new state of affairs should allow public discussion of iPhone SDK APIs, the publication of books on iPhone development, iPhone SDK development training courses, open source code releases, and more. Unreleased (beta) versions of future iPhone firmwares will remain under NDA until they are released, as is the case with beta version of Mac OS X.

Surely another strong indication that, as I previously asserted, Apple is listening to our concerns.

by Matt Legend Gemmell at October 01, 2008 03:44 PM

toxicsoftware.com

Cocoa Is My Girlfriend

Cocoa Touch Tutorial: iPhone Application Example

Similar to one of my first blog posts on building a basic application for Mac OS X using xcode 3.0, I am going to explain for beginning iPhone/iPod Touch developers how to build the most basic Cocoa Touch application using Interface Builder and an application delegate in xcode 3.1. This tutorial post is really to provide a quick how-to. I won’t go into any depth explaining why things are done the way they are done, but this should help you get up and running with your first application pretty quickly so that you too can clog the App Store with useless superfluous apps (kidding… just kidding).

If you are a visual learner, it may be helpful to you to instead watch a video presentation of this tutorial. I’ve posted it on the site, but you’ll have to click the link to see my Cocoa Touch Video Tutorial.

Understanding Cocoa programming is much simpler if you learn MVC, Model, View, Controller. You can probably step through code examples and figure some things out without learning MVC, but I wouldn’t recommend it. Go Google it and read up on it.

I will say as an introduction to MVC for those who are not familiar that it should probably be called (Model --> Controller --> View) or (View --> Controller --> Model) as the controller always sits between the other two. Your controller is either telling your model to update its data or it is telling the view to update its display. That’s the crux of the whole paradigm. The details run much deeper, but that’s how I will nutshell it for you.

Create Your Application

Let’s get started. Create a Cocoa Application using the following steps:

  1. Select File > New Project…, under the iPhone OS templates choose Window-Based Application in the ensuing dialog. Click Choose…
  2. iPhone Project Templates

  3. Enter ‘Basic iPhone App’ as the project name. Click Save

You should see a project workspace like the following:

Basic iPhone Application

The next thing you should do is create a class to act as your controller or delegate.

Delegate == Controller

The words delegate and controller can be used synonymously. You’ll see later that we delegate the work of the different controls we create in Interface Builder to a delegate or controller class. In the iPhone template projects, this application delegate is created for you. Our app delegate has been named Basic_iPhone_AppAppDelegate.

In our app delegate class we need to add what Cocoa developers refer to as outlets and actions. I could spend an entire post explaining these two things in depth, but for the sake of brevity and walking you through the steps to build your first application, the definition will have to suffice.

Outlets represent controls in your user interface that can have some action performed upon them. Action are functions in your code that are connected to controls in your user interface such as a button or a drop down list. When connected to a button for instance, the action code will be run when the user clicks the button.

In xcode, open your app delegate header file Basic_iPhone_AppAppDelegate.h. Add an outlet for the text field and the label below the window outlet as in the following snippet:

1
2
3
4
5
@interface Basic_iPhone_AppAppDelegate : NSObject <UIApplicationDelegate> {
    IBOutlet UIWindow *window;
    IBOutlet UITextField *textField;
    IBOutlet UILabel *label;
}

You will also want to add an action that will be performed when our button is clicked. Add that below the property for our window:

1
2
3
4
5
6
7
8
9
@interface Basic_iPhone_AppAppDelegate : NSObject <UIApplicationDelegate> {
    IBOutlet UIWindow *window;
    IBOutlet UITextField *textField;
    IBOutlet UILabel *label;
}
 
@property (nonatomic, retain) UIWindow *window;
 
- (IBAction)click:(id)sender;
  • Now switch over to the implementation file, Basic_iPhone_AppAppDelegate.m. Add the click: action below our applicationDidFinishLaunching: function:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    - (void)applicationDidFinishLaunching:(UIApplication *)application {	
     
        // Override point for customization after app launch	
        [window makeKeyAndVisible];
    }
     
    - (IBAction)click:(id)sender;
    {
     
    }

    We will actually add some code to do something in the click: action handler, but first we need to hook it up to the user interface in Interface Builder.

  • Interface Builder And Controller/Delegate Implementation

    Now that you’ve specified the outlets–a UITextField and a UILabel and an action called click:, you will see these items available for connecting to the UI in Interface builder. Let’s open Interface Builder and make the connections we need using the following steps:

    1. In your xcode workspace, expand the folder in the tree view called Resources and double click the file called ‘MainMenu.xib’.

      Note:: A .xib is a .nib that uses XML for the internal data structure.

      This will open the xib file in Interface Builder

    2. Once Interface Builder loads, you will notice that there is an object representation of our app delegate in the MainWindow.xib window. This is the object you will use to create connections for your actions and outlets.

      MainWindow.xib

    Design The User Interface

    Now you simply need to add the controls to the main window in Interface Builder and then we can connect the action and outlet accordingly. To finish the interface, complete the following steps:

    1. Drag a TextField, a Label, and a Button to the main window so that the user interface looks like the screenshot below:

      iPhone Application UI

    2. Control-Click and drag from the Button to your app delegate object in the ‘MainWindow.xib’ window.

      Button Connection

      A pop-up will display. Select click:

    3. Control-Click the app delegate object and drag it to the text field in the main window.

      Textfield Connection

      A pop-up will display. Select textField

    4. Control-Click the app delegate object and drag it to the label in the main window.

      Label Connection

      A pop-up will display. Select label

    That’s it for Interface Builder. You can quit interface builder and return to xcode. We have one more piece of code to add and then our application will be finished.

    Finishing Up

    When the button is clicked, it will simply grab the text from the text field and place it into the label. That’s all the application does. Here’s the code you need. Just make your implementation of the click: action in the Basic_iPhone_AppAppDelegate.m file look like this:

    1
    2
    3
    4
    
    - (IBAction)click:(id)sender;
    {
        [label setText:[textField text]];
    }

    Notice we are grabbing the text from the text field, and setting the text in our label with it. Now all you need to do is click “Build and Go”. When the application runs the iPhone Simulator will be started. You will see the application load. Type some text into the text field and click the Change button. You will see the label update with the text from the text field.

    Conclusion

    The limit with iPhone development is really just your imagination. It is an extremely fun platform to develop on and the resulting applications are very rewarding. Have fun with it and learn as much as you can. Just do me a favor and don’t clog the App Store with any more flashlight apps or tip calculators… Seriously ;-) . Until next time.

    xcode.png
    Basic iPhone Application Demo Project

    by Matt Long at October 01, 2008 03:34 PM

    Cocoa Samurai

    Thank Goodness the F'ing iPhone NDA is being lifted

    Apple FINALLY did the right thing today and publicly recognized what pretty much all iPhone developers and the public that have been paying attention to the news have known for a long time now, that the iPhone NDA was doing much more harm than good. From their page ( http://developer.apple.com/iphone/program/ ) "To Our Developers We have decided to drop the non-disclosure agreement (NDA) for

    by Colin Wheeler (noreply@blogger.com) at October 01, 2008 01:10 PM

    Surfin' Safari

    Web Inspector Redesign

    It has been nine months since our last Web Inspector update and we have a lot of cool things to talk about. If you diligently use the Web Inspector in nightly builds, you might have seen some of these improvements, while other subtle changes might have gone unnoticed.

    Some of the Web Inspector improvements were contributed by members of the WebKit community. We really want to get the whole community involved with making this the best web development tool available. Remember, most of the Web Inspector is written in HTML, JavaScript, and CSS, so it’s easy to get started making changes and improvements.

    Redesigned Interface

    First and foremost, the Web Inspector is now sporting a new design that organizes information into task-oriented groups — represented by icons in the toolbar. The toolbar items (Elements, Resources, Scripts, Profiles and Databases) are named after the fundamental items you will work with inside the respective panels.

    Console

    The Console is now accessible from any panel. Unlike the other panels, the Console is not just used for one task — it might be used while inspecting the DOM, debugging JavaScript or analyzing HTML parse errors. The Console toggle button is found in the status bar, causing it to animate in and out from the bottom of the Web Inspector. The Console can also be toggled by the Escape key.

    Error and warning counts are now shown in the bottom right corner of the status bar. Clicking on these will also open the Console.

    In addition to the visual changes to the Console, we have also greatly improved usability by adding auto-completion and tab-completion. As you type expressions, property names will automatically be suggested. If there are multiple properties with the same prefix, pressing the Tab key will cycle through them. Pressing the Right arrow key will accept the current suggestion. The current suggestion will also be accepted when pressing the Tab key if there is only one matched property.

    Our compatibility with Firebug’s command line and window.console APIs has also been greatly improved by Keishi Hattori (服部慶士), a student at The University of Tokyo (東京大学) who tackled this area as a summer project.

    Elements Panel

    The Elements panel is largely the same as the previous DOM view — at least visually. Under the hood we have made number of changes and unified everything into one DOM tree.

    • Descend into sub-documents — expanding a frame or object element will show you the DOM tree for the document inside that element.
    • Automatic updates — the DOM tree will update when nodes are added to or removed from the inspected page.
    • Inspect clicked elements — enabling the new inspect mode lets you hover around the page to find a node to inspect. Clicking on a node in the page will focus it in the Elements panel and turn off the inspect mode. This was contributed by Matt Lilek.
    • Temporarily disable style properties — hovering over an editable style rule will show checkboxes that let you disable individual properties.

    • Style property editing — double click to edit a style property. Deleting all the text will delete the property. Typing or pasting in multiple properties will add the new properties.
    • Stepping for numeric style values — while editing a style property value with a number, you can use the Up or Down keys to increment or decrement the number. Holding the Alt/Option key will step by 0.1, while holding the Shift key will step by 10.

    • DOM attribute editing — double click to edit a DOM element attribute. Typing or pasting in multiple attributes will add the new attributes. Deleting all the text will delete the attribute.
    • DOM property editing — double click to edit a DOM property in the Properties pane. Deleting all the text will delete the property, if allowed.
    • Metrics editing — double click to edit a any of the CSS box model metrics.
    • Position metrics — the Metrics pane now includes position info for absolute, relative and fixed positioned elements.

    Resources Panel

    The Resources panel is a supercharged version of the previous Network panel. It has a similar looking timeline waterfall, but a lot has been done to make it even more useful.

    • Graph by size — click Size in the sidebar to quickly see the largest resources downloaded.
    • Multiple sorting options — there are many sorting methods available for the Time graph, including latency and duration.
    • Latency bars — the Time graph now shows latency in the bar with a lighter shade. This is the time between making the request and the server’s first response.
    • Unified resource views — clicking a resource in the sidebar will show you the data pulled from the network (not downloaded again), including the request and response headers.
    • View XHRs — the time and size graphs also show XMLHttpRequests. Selecting an XHR resource in the sidebar will show the XHR data and headers.

    Scripts Panel

    The previous standalone Drosera JavaScript debugger has been replaced with a new JavaScript debugger integrated into the Web Inspector. The new integrated JavaScript debugger is much faster than Drosera, and should be much more convenient.

    From the Scripts panel you can see all the script resources that are part of the inspected page. Clicking in the line gutter of the script will set a breakpoint for that line of code. There are the standard controls to pause, resume and step through the code. While paused you will see the current call stack and in-scope variables in the right-hand sidebar.

    The Web inspector has a unique feature regarding in-scope variables: it shows closures, “with” statements, and event-related scope objects separately. This gives you a clearer picture of where your variables are coming from and why things might be breaking (or even working correctly by accident).

    Profiles Panel

    The brand new JavaScript Profiler in the Profiles panel helps you identify where execution time is spent in your page’s JavaScript functions. The sidebar on the left lists all the recorded profiles and a tree view on the right shows the information gathered for the selected profile. Profiles that have the same name are grouped as sequential runs under a collapsible item in the sidebar.

    There are two ways to view a profile: bottom up (heavy) or top down (tree). Each view has its own advantages. The heavy view allows you to understand which functions have the most performance impact and the calling paths to those functions. The tree view gives you an overall picture of the script’s calling structure, starting at the top of the call-stack.

    Below the profile are a couple of data mining controls to facilitate the dissection of profile information. The focus button (Eye symbol) will filter the profile to only show the selected function and its callers. The exclude button (X symbol) will remove the selected function from the entire profile and charge its callers with the excluded function’s total time. While any of these data mining features are active, a reload button is available that will restore the profile to its original state.

    WebKit’s JavaScript profiler is fully compatible with Firebug’s console.profile() and console.profileEnd() APIs, but you can also specify a title in console.profileEnd() to stop a specific profile if multiple profiles are being recorded. You can also record a profile using the Start/Stop Profiling button in the Profiles panel.

    Databases Panel

    The Databases panel lets you interact with HTML 5 Database storage. You can examine the contents of all of the page’s open databases and execute SQL queries against them. Each database is shown in the sidebar. Expanding a database’s disclosure triangle will show the database’s tables. Selecting a database table will show you a data grid containing all the columns and rows for that table.

    Selecting a database in the sidebar will show an interactive console for evaluating SQL queries. The input in this console has auto-completion and tab-completion for common SQL words and phrases along with table names for the database.

    Search

    Accompanying the task-oriented reorganization, the search field in the toolbar now searches the current panel with results being highlighted in the context of the panel. Targeting the search to the current panel allows each panel to support specialized queries that are suited for the type of information being shown. The panels that support specialized queries are Elements and Profiles.

    The Elements panel supports XPath and CSS selectors as queries in addition to plain text. Any search you perform will be attempted as a plain text search, a XPath query using document.evaluate() and a CSS selector using document.querySelectorAll(). All the search results will be highlighted in the DOM tree, with the first match being revealed and selected.

    The Profiles panel supports plain text searches of the function names and resource URLs. Numeric searches are also supported that match rows in the profile’s Self, Total and Calls columns. To facilitate powerful numeric searching, there are a few operators and units that work to extend or limit your results. For example you can search for “> 2.5ms” to find all the functions that took longer than 2.5 milliseconds to execute. In addition to “ms”, the other supported units are: “s” for time in seconds and “%” for percentage of time. The other supported operators are “ ”, “=”, “>=” and “=”. When no units are specified the Calls column is searched.

    In all the panels pressing Enter in the search field or ⌘G (Ctrl+G on Windows and Linux) will reveal the next result. Pressing ⇧⌘G (Ctrl+Shift+G on Windows and Linux) will reveal the previous result. In the Resources, Scripts and Profiles panels the search will be performed on the visible view first and will automatically jump to the first result only if the visible view has a match.

    Availability and Contributing

    All of these things are available now in the Mac and Windows nightly builds. Give them a try today, and let us know what you like (or don’t like).

    If you would like to contribute, there are some really interesting tasks in the list of Web Inspector bugs and enhancements, and other contributors in the #webkit chat room are pretty much always available to provide help and advice.

    by Timothy Hatcher at October 01, 2008 12:06 AM

    September 30, 2008

    waffle

    Docudrama

    Now that we’ve established how code documentation sucks, let’s start by deducing how code documentation could be made great.

    The first thing we do is we kill the idea of documenting the API inline with the code. Yes. I’m serious. I know the allure of this. But I also know how it’s holding back documentation.

    Here’s what it means:

    • You have to make your way around bigger files when editing either code or documentation. The other content is a nuisance. Yes, in competent editors you can “fold” those blocks; not an excuse.

    • Plain-text formatting doesn’t play well with comments, especially multiline comments, code formatting standards, and indent depths where this plays a role.

    • Documentation copy editing bloats the file versioning history.

    • It is work to figure out which methods (every method has code; some have documentation) are documented. With creative header file use, this is less of a problem in some languages.

    The second thing we do is we integrate code documentation into our IDE with editor integration but without embedding the documentation into the code. Imagine a button in the breakpoint/line number/warning gutter for creating an entry. This is a shortcut to a new documentation panel with a dedicated editor (maybe even a limited form of rich text) with capabilities to add cross references to other methods or types.

    From this panel, you can arrange a bunch of topics in a hierarchy, including on which page the documentation for these types go, with a sensible default of one type per page. And of course you can create conceptual material and relate back and forward between that and code elements. (This is Wiki-like, but you control the hierarchal structure, you get things generated for you in a smart way and code elements are handled in a block-wise fashion.) Everything is stored in a plain format, and can be generated into a HTML web site, zip, maybe PDF or in a form suited for the IDE’s documentation browser. And of course, the documentation is (generation or not) shown in your IntelliSense or your Research Assistant or your generic contextual what-have-you as you browse code.

    As relieving as it was, whiningventing about how the code documentation generators of today, er, yesterday worked is not going to solve anything. Presenting a clear idea of a more bearable way to document is much more like it; perhaps you’ll now see what I’m getting at.

    by Jesper at September 30, 2008 07:14 PM

    September 29, 2008

    Unixjunkie Blog

    Update Engine




    Today we announced a new open source project called Update Engine. Update Engine is a framework to help developers keep their software up-to-date. See the Google Mac blog post for a quick overview and a link to some demo movies explaining Update Engine [and yes, I knew I sounded like kermit when I recorded the video—I even told my wife but she didn't think so... oh well ;-)].

    Also, we did not build Update Engine to compete with Sparkle. We built Update Engine to solve different problems. If you're interested, here's my reply about this in the Google Group for the project.

    by Greg (noreply@blogger.com) at September 29, 2008 09:11 PM

    Red Sweater Blog

    Core Intuition 8: For The Good Of The Country

    Manton and I sat down to record another episode of Core Intuition, speaking as usually on a variety of topics including the C4 conference, Android, and Apple’s “elevated user experience.”

    Hope you enjoy the show!

    by Daniel Jalkut at September 29, 2008 07:58 PM

    Gus Mueller

    Ceramic Notepad

    Yoyo Ceramics: "Plain Jotter" ceramic notepad.

    Looks neat, not sure how well it would stay clean though. Might as well just use Acorn anyway :)

    September 29, 2008 07:22 PM

    SousChef

    Congrats to Ben Lachman for releasing SousChef, "A digital cooking assistant".

    '''Most cooking software stops at letting you organize your recipes. SousChef helps you cook, start to finish. Find a recipe, cook it, modify it and share it with friends & family—all in one application.'''

    September 29, 2008 06:47 PM

    Official Google Mac Blog

    Revving software with Update Engine



    We ship a wide variety of Mac software ranging from simple Cocoa applications that anyone can use to sophisticated ones that require admin privileges. The complicated requirements of each application, combined with the need to occasionally update more than one at a time, made for a tall order. We realized that we were not the only ones facing these issues, so in true Google fashion, we set out to build a solution that we could open-source for everyone to use.

    So today, we're announcing Update Engine, a Mac OS X framework that can help developers keep their software up-to-date. Update Engine can update all the usual suspects, like Cocoa apps, preference panes, and screen savers. But it can also update oddballs like arbitrary files, and even things that require root—like kernel extensions. On top of that, it can update multiple products as easily as it can update one.

    In most cases, programmers can make use of Update Engine simply by using one of the sample command-line programs called EngineRunner. However, if you need more control over the update process, you can use the Objective-C API directly and link with the provided framework.

    A couple of us engineers decided to take a break from the code for a bit and try our hands at movie-making. We came up with two demos for Update Engine: The first one gives an overview of Update Engine, and the second presents an orientation of the source and shows a "Hello Engine" example. We had fun, but I think we'll keep our day jobs.

    Update Engine Overview

    by Scott Knaster (noreply@blogger.com) at September 29, 2008 05:40 PM

    Introducing Top Draw



    Top Draw is an image generation program just launched in the Google Mac Playground. By using simple text scripts, based on JavaScript, Top Draw can create surprisingly complex and interesting images. Even cooler is that the program has built-in support for installing any image of yours as your desktop image. There's a Viewer application you can install in the menu bar to automatically run with the parameters (such as script and update interval) that you've specified. And there's even a Screen Saver to display the scripts when your computer is taking a break.

    The Top Draw scripting language leverages Apple's Quartz and CoreImage rendering engines for graphical muscle. In addition to the drawing commands that are supported by the HTML canvas tag, there is support for particle systems, plasma clouds, random noise, multi-layer compositing and much more.

    Because it uses JavaScript in a safe sandbox, you can run any script without fear of malicious action.

    Here's the download: http://topdraw.googlecode.com/files/Top%20Draw.zip. Have fun!

    Here are some sample images created by Top Draw:





    by Scott Knaster (noreply@blogger.com) at September 29, 2008 10:30 AM

    Cocoa With Love

    Streaming and playing an MP3 stream

    This week, I present a sample application that streams and plays an audio file from a URL. I'll show how the application was written by expanding upon Apple's AudioFileStreamExample, including a work-around for an Audio File Stream Services' crash bug when handling streaming MP3s.

    Introduction

    Playing an MP3 stream seems like it should be a straightforward task that the Cocoa APIs would handle easily. Unfortunately, the normal approach to handling media (i.e. "Let Quicktime Handle It") fails here — a quick attempt to play streaming MP3s in Apple's QTKitPlayer example results in a few seconds of no response, followed by a "-2048" error.

    Of course, there's a way to play an MP3 stream without using QTKit. I'll show you how and the final result will be a sample application that looks like this:

    audiostreamer.png
    Since I link to their stream by default in the application, I should probably point out that Triple J is an Australian radio station.

    You can download the XCode 3.1 project for the StreamingAudioPlayer here. If you only have XCode 3.0, you'll need to register as a developer with Apple (free) and download a newer version from the Mac Dev Center.

    AudioToolbox

    There is probably a way to make QTKit play streaming MP3s. I decided to go a different way instead.

    In Mac OS X 10.5 (Snowless Leopard), Apple introduced the AudioToolbox framework which contains the Audio File Stream Services and Audio Queue Services that we'll use to solve the problem. These are pure C APIs: not as clean and simple to use as the Cocoa Objective-C APIs, but once written, should get the job done.

    Audio File Stream reads the raw bytes and finds audio packets within them. The Audio Queue takes packets and plays them on the sound hardware. Between the two, they should handle streaming playback.

    AudioFileStreamExample

    At the moment, the AudioToolbox doesn't have any beginner-friendly "Guide" documentation. The only detailed introduction is the afsclient.cpp file in the AudioFileStreamExample that Apple provide (you'll find it in /Developer/Examples/CoreAudio/Services/AudioFileStreamExample).

    Sadly, this example is missing a few things to make it work as a proper player:

    • Doesn't wait for audio to finish (the program quits when the data finishes loading, not when it finishes playing)
    • Never plays the final audio buffer
    • Only plays variable bit-rate data
    • Doesn't provide "hints" about the data format (many file types won't be recognized)

    Addressing the issues

    Waiting until the playback is finished

    Immediately after the Audio Queue is created in the MyPropertyListenerProc, you can add a listener to the kAudioQueueProperty_IsRunning property of the Audio Queue. This will allow us to determine when playback has started and (more importantly) when playback has properly finished.

    // listen to the "isRunning" property
    err = AudioQueueAddPropertyListener(myData->audioQueue, kAudioQueueProperty_IsRunning, MyAudioQueueIsRunningCallback, myData);
    if (err) { PRINTERROR("AudioQueueAddPropertyListener"); myData->failed = true; break; }

    With this in place, we can implement the MyAudioQueueIsRunningCallback function and use it to wait until the audio has finished playing before we exit the program.

    The documentation doesn't point it out but the MyAudioQueueIsRunningCallback function will not be called when the audio stops unless the thread from which the stop was issued has a run loop (e.g. call CFRunLoopRunInMode in a loop while waiting for completion).
    Play the final audio buffer

    This is a simple problem. All that is needed is to call the MyEnqueueBuffer function once more, after the data has finished loading, to ensure that the buffer in progress is sent to the Audio Queue. It may help to flush the queue as well.

    MyEnqueueBuffer(myData);
    
    err = AudioQueueFlush(myData->audioQueue);
    if (err) { PRINTERROR("AudioQueueFlush"); return 1; }
    Handle CBR data too

    The "for CBR data, you'd need another code branch here" comment in the AudioFileStreamExample is a bit of a giveaway on this point. Basically, the code which follows that comment should be wrapped in an "if (inPacketDescriptions)" conditional, followed by an else that looks like this:

    else
    {
        // if the space remaining in the buffer is not enough for this packet, then enqueue the buffer.
        size_t bufSpaceRemaining = kAQBufSize - myData->bytesFilled;
        if (bufSpaceRemaining  inNumberBytes) {
            MyEnqueueBuffer(myData);
        }
        
        // copy data to the audio queue buffer
        AudioQueueBufferRef fillBuf = myData->audioQueueBuffer[myData->fillBufferIndex];
        memcpy((char*)fillBuf->mAudioData + myData->bytesFilled, (const char*)inInputData, inNumberBytes);
    
        // keep track of bytes filled and packets filled
        myData->bytesFilled += inNumberBytes;
        myData->packetsFilled = 0;
    }
    

    Straightforward stuff: you just copy all the data into the buffer, without needing to worry about packet sizes.

    Hinting about data types

    This is a bit more of an open ended problem. A few different approaches can work here:

    • Use file extensions to guess the file type
    • Use mime types provided in HTTP headers to determine the file type
    • Continuously invoke AudioFileStreamParseBytes on the first chunk of the file until it returns without an error
    • Hardcode the type, if you can presume it in all cases

    I only implemented the first of these options. If you know the URL of the source file, it goes a little something like this:

    AudioFileTypeID fileTypeHint = 0;
    NSString *fileExtension = [[url path] pathExtension];
    if ([fileExtension isEqual:@"mp3"])
    {
        fileTypeHint = kAudioFileMP3Type;
    }
    // ... and so on for a range of other file types

    Then you pass the fileTypeHint into the call to AudioFileStreamOpen.

    Final nasty bug

    After making all these changes, the Audio File Stream Services hit me with a nasty bug: AudioFileStreamParseBytes will crash when trying to parse a streaming MP3.

    Of course, if you let bugs in other people's code discourage you, you won't get too far as a programmer. Even if the bug is truly in someone else's code (99% of the time the real cause is in your own code), there's often a way around the problem.

    In this case, if we pass the kAudioFileStreamParseFlag_Discontinuity flag to AudioFileStreamParseBytes on every invocation between receiving kAudioFileStreamProperty_ReadyToProducePackets and the first successful call to MyPacketsProc, then AudioFileStreamParseBytes will be extra cautious in its approach and won't crash.

    So, set a boolean named discontinuous in the myData struct to true after:

    case kAudioFileStreamProperty_ReadyToProducePackets:

    and set it to false again at the start of MyPacketsProc, then replace the call to AudioFileStreamParseBytes with:

    if (myData->discontinuous)
    {
        err = AudioFileStreamParseBytes(myData->audioFileStream, bytesRecvd, buf, kAudioFileStreamParseFlag_Discontinuity);
        if (err) { PRINTERROR("AudioFileStreamParseBytes"); myData->failed = true; break;}
    }
    else
    {
        err = AudioFileStreamParseBytes(myData->audioFileStream, bytesRecvd, buf, 0);
        if (err) { PRINTERROR("AudioFileStreamParseBytes"); myData->failed = true; break; }
    }

    and all should be well.

    Making a proper Cocoa application out of it

    The final step was to take the reworked example and set it up as part of a proper Cocoa application. For this, I decided to further add the following:

    • Load the data over an NSURLConnection instead of a socket connection.
    • Handle the connection in a separate thread, so any potential blocking won't affect the user-interface.
    • Wrap the construction and invocation in an Objective-C class.
    • Make the isPlaying state an NSKeyValueObserving compliant variable so the user-interface can update to reflect the state.
    • Since the program always fills one buffer completely before audio starts, I halved the kAQBufSize to reduce waiting for audio to start.

    I invite you to look at the AudioStreamer code in the sample application to see how this was done. It is fairly straightforward. Where possible, AudioStreamer keeps the code, style and approach of the AudioFileStreamExample. I don't advocate using so many boolean flags or public instance variables in normal situations.

    Conclusion

    The application works. Given the learning curve of a new API and the MP3 parsing bug, I'm fairly pleased I succeeded.

    The program will handle other types of stream (not just MP3s) as well as non-streaming files downloaded over HTTP (although the player will block the download so that it only downloads at playback speed — this implementation doesn't cache ahead).

    I think the biggest limitation in the implementation's current form is that it doesn't read mime types or aggressively try different file types, so URLs without a file extension may not work.

    With regards to the bug in AudioFileStreamParseBytes, if this discussion thread is accurate, it appears that Apple have already fixed the MP3 parsing bug in the iPhone version of the function, so the fix should make it into an upcoming version of Mac OS X.

    by Matt Gallagher (noreply@blogger.com) at September 29, 2008 04:19 AM

    September 28, 2008

    Gus Mueller

    What I did on my summer vacation

    What I did on my summer vacation, pictures from climbing in Horseshoe Canyon Ranch and Sam's Throne, Arkansas.

    And various pics from our time in St. Louis.

    September 28, 2008 09:41 PM

    Uli's Web Site

    Across-the-Room GUI

    One important aspect of interaction design is determining typical usage patterns for your application. What many people overlook here, is that these patterns don't just happen inside your application, but may also be influenced by what happens outside, in the real world, in the user's home. As an example, let's take a feature that a friend of mine implemented in Toast 8: (...)

    September 28, 2008 05:03 PM

    waffle

    Doc Brown

    One of the things that scare me greatly about the current generation of development tools are how many of them are dedicated to generating completely useless, documentation-looking, tautological, disk space-wasting output that would never be of any significant help to anyone.

    The default output of Doxygen, Javadoc, Headerdoc and Sandcastle — the most popular open cross-platform alternative and the sponsored alternative of the three major next generation platforms — is horrible. Really horrible. What will you see? You’ll see a verbose listing of every single piece of metadata that the generation is able to reassemble, output in several files, with the documentation itself being easily lost in the flotsam. Some are clearly worse offenders than others; Javadoc’s signal-to-noise ratio is quite good. But I wouldn’t call this documentation.

    This isn’t what disturbs me most. The default setting needs to be good, but if it’s not, at least we can work around it, right? Look at the options afforded by most of these tools. You can change the font size and the base path, even the filename format. And you can apply a new coat of paint. But what you can’t do, effectively, is choose how you want to structure your documentation.

    You can’t choose which way you’d list the methods. You can’t group several related classes together under hierachial sections. It’s even hard in some cases to find an appropriate lookup table to be able to link to system API type definitions. And forget about including what Apple calls “guides” - prose content explaining the concepts and describing how to use a group of classes. Doxygen lets you create pages, but that’s just a small first step - there’s no sense of hierarchy, no index, no TOC. It’s just hard to do well.

    I might not be so peeved by this if it wasn’t that there’s no good niche tools to fill this gap that I’ve been able to find. What most documentation generators provide at the end of the day is nothing more than what you’ll be able to find in any competent IDE, and they don’t even generate that nicely. But hey, you can get it in #FF00FF Comic Sans, and we can render it to a PDF, and if you spend twenty minutes recompiling everything and passing a lot of bullshit to ./configure, we can also draw UML diagrams and retroactively legitimize your work as structured and well thought-out to nosy bosses.

    It’s a testament to the sad state of programming that this problem isn’t better solved. Concurrency, scalability, dynamic programming with IDE support — those problems are hard. But this one’s easy. It just takes effort, and for some reason we’ve stopped just clear of a good solution, or we’ve rolled it into some big in-house system that only runs on Ubuntu Feisty after a four hour configuration session and that’s too ugly to let out anyway.

    by Jesper at September 28, 2008 01:19 PM

    Kupuk

    Google Officially Takes a Stand Against Prop 8

    Signed by Sergey Brin, co-founder of Google:

    “It is the chilling and discriminatory effect of the proposition on many of our employees that brings Google to publicly oppose Proposition 8. While we respect the strongly-held beliefs that people have on both sides of this argument, we see this fundamentally as an issue of equality. We hope that California voters will vote no on Proposition 8 — we should not eliminate anyone’s fundamental rights, whatever their sexuality, to marry the person they love.”

    by Paul Robinson at September 28, 2008 02:40 AM

    September 27, 2008

    waffle

    Oh No Not Another Mega Man 9 Post Can’t He Start Talking About the iPhone SDK Licensing or Something Again

    Mega Man 9, it must be said, is not an 8-bit game.

    It is comprised of three components:

    • An awesome game using the graphics style and control style of the NES Mega Man games.
    • A current-generation style infrastructure with downloadable contentcheats whose acquisition require Wii/Microsoft/Whatever Sony Uses Point deduction; and achievements.
    • An unusually complex Mega Man menu and navigation shell, also in the style of the NES Mega Man shells.

    There are even elements in the game that are very similar in spirit to latter Mega Man games.

    None of this is criticism; it’s clarification. We already know that the game is far too big to fit on a NES cartridge. Mega Man 9 is about combining the style of the NES games and, with the exception of the graphics, unshackle them from the technical requirements of the NES. This has succeeded, and I believe the game is better for it.

    And in case you couldn’t tell, this is the most fun I’ve had with a game since Portal. Engaging and hard gameplay is just one thing you can achieve if you put the blood, guts and pretty graphics away.

    by Jesper at September 27, 2008 08:54 PM

    briksoftware Blog

    Xcode Refactorings

    I just created yet another class with some instance variables and so missed the functionality of creating accessor methods for these instvars automatically. As I never really looked into the Refactorings of Xcode 3 I didn’t notice that they provide an encapsulation refactoring. Using this on an instvar nicely generates accessor methods. You have to apply it to all your instvars separately, but still it’s a great gain.

    One thing they should improve though: why is the refactor command no submenu which shows all the available refactorings? This way the refactoring could be chosen much simpler.

    Karsten

    by Karsten at September 27, 2008 02:32 PM

    Kupuk

    Zones 1.2 Now In the App Store

    Zones 1.2 is now available in the App Store. This release sports a spiffy new UI and support for Internet Radio, Line-In, and Playlists.

    21196450-B714-4D4A-83D9-DAEFAC367969.jpg

    by Paul Robinson at September 27, 2008 01:14 PM

    No Buy, No Review in the App Store

    Looks like the App Store now requires users to have at least downloaded the app they are reviewing:

    require.png

    by Paul Robinson at September 27, 2008 12:45 PM

    Matt Legend Gemmell

    Apple is listening

    Just a small positive note amongst the gloom of NDAs, app rejections and approval delays: Apple have today changed how the customer reviews system works for App Store applications: you now must have downloaded or purchased the app before you’re allowed to post a review on it. Here’s what it looks like if you try to review an app you’ve not actually used.

    Since the App Store is the only way to get the apps in the first place, I think this is a strong positive step, and should help make the app reviews much more useful and representative to customers (and less depressing/frustrating for developers).

    The wheels may be turning slowly, but they are turning - and I do believe that Apple is listening to our complaints.

    (Thanks to my friend Neil for noticing the change this morning. His own app, Escape Pod, has received some frivolous reviews on the US store.)

    by Matt Legend Gemmell at September 27, 2008 12:04 PM

    September 26, 2008

    waffle

    Mega Man 9 “That’s What She Said”-Friendly Early Review

    What a first night. I missed the little bugger. So far it’s not much longer, but it is much harder than I thought it’d be, and I’d like to think I have some experience with the predecessors. I planned on taking a lot more time, but it was just too hard. I’m spent already, although it’s been a while. I’ll resume tomorrow and continue the fun all weekend… this thing definitely has staying power, and if you can just perform the right maneuvers, there’s a lot more to achieve.

    by Jesper at September 26, 2008 08:31 PM

    Safe from the Losing Fight

    Of graphics designers and men

    As I mentioned at C4[2], I’m working on my company’s first product, which is an iPhone application. I’ve gotten to the point where I need a graphics designer and one those sound creator type people (sorry, I don’t know their professional title).

    My app is a game, so in addition to an application icon, I also need avatars for players and some game backgrounds (like wallpaper), among other things. Basically, I’m looking for recommendations here. Anyone have someone they’ve worked with and really liked?

    I also need sound effects, which I’m pretty lost on. I mean, if I ever need a twoosh sound, I know who to go to, but for more complex sounds, I’m just don’t know. For those of you who have done games, who did your sound effects?

    After I get some real artwork into the game, I’ll see about posting screenshots and whatnot.

    by Andy at September 26, 2008 06:29 PM

    waffle

    MMIX

    I’ve been playing it for five minutes and so far, yes, it feels like the NES games did. I won’t similarly keep you posted, but I will note that in the modern age, the age of the intra-second Internet, distribution bureaucracy for a solely downloadable game still drags the span from “there” to “here” down to five days (released in the US this Monday; in Europe just now).

    by Jesper at September 26, 2008 05:25 PM

    Red Sweater Blog

    Building A Bigger Nerd Ranch

    When newcomers to programming on the Mac ask me for advice about getting started with Cocoa, I usually boil it down to three steps, depending on the amount of time and money they are prepared to put into the task:

    1. If you’re the slightest bit curious, buy Mark Dalrymple and Scott Knaster’s affordable book, Learn Objective-C on the Macintosh. It’s great that this book not only starts from the very beginning, but is available as an easy electronic download, for instant gratification.
    2. If you’re convinced you’re in for the long haul, but prefer to learn at your own pace and in your spare time, pick up Aaron Hillegass’s Cocoa Programming for Mac OS X