Current location: Brighton, UK

Dropbox beta includes some sweet new features

Posted on Tuesday, August 31, 2010 @ 11:16 CET

I absolutely love Dropbox. Its such a fantastic service, that in case you're not familiar with it, runs in the background and seamlessly syncs your folders with their servers so you always have a backup. On top of that you can share folders (or others can share with you) which makes working with others really easy, without having to resort to things like source control. They also have clients for Mac, Windows, Linux, iPhone, iPad, Android and Blackberry (coming soon). Amazing.

However one of my main gripes with it is that it creates a Dropbox folder in your home directory and absolutely everything within that folder gets synced. Stupid simple, but I sometimes had files or folders I didn't really want to sync either because they're already in source control or its a folder with tons of heavy assets that put a real dent into my 50GB account limit.

The other was that I couldn't stop it when I was on a slow connection like a 3G data card - your only option was to kill the app.

Turns out I'm not alone! People asked and the friendly folks at Dropbox delivered. From version 0.8.91 onwards you can do both of these things. When you click on the icon in the menu bar you'll be presented with the option to pause, like so:

The great thing with this is that it continues to index the files on your machine so it knows what to sync once you resume syncing. Under the advanced tab you now also have the option to do a "Selective sync" where you can uncheck folders from being synced. Awesome! You'll also notice new icons in the Finder.

The latest beta version (at the time of this post) is 0.8.97 can be downloaded here, and includes all these goodies. If upgrading from an earlier version it might take a little while to upgrade the database at first but its worth it.

- paulo

Sorting numerical NSStrings by playing with C

Posted on Tuesday, August 03, 2010 @ 14:32 CET

The other day I was trying to sort a list of value objects by their ID. I know, not very exciting, but easy enough right? Except these are numbers that are typed as NSStrings. So basically the object looks something like this:

@interface MyObject : NSObject {
NSString *objectId;
// Other properties would be defined here
}

I tried various things, such as sorting the list using a NSSortDescriptor like so:

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"objectId" ascending:YES];
NSArray *orderedList = [list sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
[descriptor release];

However that ordered the 12 items as 1, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9. Not quite what I wanted. After some digging I found a lovely function that would do this, like so:

NSArray *orderedList = [list sortedArrayUsingFunction:compareObjectsUsingNumericalStringId context:@"objectId"];

The C function is quite straightforward:

static int compareObjectsUsingNumericalStringId(id p1, id p2, void *context) {
// Create a selector for the object's property
SEL methodSelector = NSSelectorFromString(context);
// Get the value
id obj1 = objc_msgSend(p1, methodSelector);
id obj2 = objc_msgSend(p2, methodSelector);
// We know objX is an NSString so get the int value for comparing
int v1 = [obj1 intValue];
int v2 = [obj2 intValue];
// Do the comparison
if (v1 < v2) {
return NSOrderedAscending;
}
else if (v1 > v2) {
return NSOrderedDescending;
}
else {
return NSOrderedSame;
}
}

And now the ordered items are 1, 2, 3, 4, etc as we would expect. One of those things that I'm sure I'll find useful in the future so better to leave it here where I can find it :) You can download an Xcode project here that shows this example in action.

- paulo

Flash Player opt-in vs opt-out

Posted on Friday, July 09, 2010 @ 11:29 CET

From an article on Inc from 2002:

The opt-out system, however, acts as a "tacit yes." ... It strikes us that companies that limit themselves to these choices aren't effectively serving the needs of customers or themselves.

The article was talking about opt-in versus opt-out email - a debate that ended years ago and its pretty well understood throughout the industry that opt-in is the way to go. The customer needs to make the decision, period.

So colour me surprised when I recently went to download the Flash Player and was presented with other stuff I could install along with it. Incredibly, these "add-ons" were selected by default! Has Adobe not been paying attention? This is "evil" behaviour after all.

If you're on a Mac you won't see these add-ons at all, but I was installing Flash on a VMWare instance running Windows XP. I took a few screenshots in Safari, using the Developer toolbar to fake the user-agent.

If you're running Internet Explorer you are presented with the option of downloading the Google Toolbar. It clearly states that it's optional, but then again its also selected by default.

Flash Player optional installs for IE

The Google Toolbar is arguably useful. But on Firefox, on Firefox you're presented with an option to download McAfee Security Scan Plus. What the?

Flash Player optional installs for Firefox

Now I've been told by people that have installed this by accident that it screwed up their existing anti-virus solution rendering it useless.

Lastly I visited the page pretending to be Opera and lo and behold you are presented with no extra options:

Flash Player optional installs for Opera

Awesome for Opera users, not so awesome for everyone else.

My question is why bother with the extras? Obviously Adobe is earning some money from these partnership deals, but they are also wasting their user's time and effort as well as annoying them. I assume this extra income is enough to ignore the fact that this practice tarnishes both Adobe's reputation and relationship with their users.

Of course I may be wrong and users don't really care.

However as someone who develops for the Flash Platform, I'm disappointed.

- paulo

Where is Influxis? Flash + Google Maps + Twitter mash

Posted on Tuesday, April 20, 2010 @ 11:53 CET

As our friends Jerry Chabolla and Grant Garrett from Influxis attempt to escape Germany and make their way back to LA Seb asked if there was any way to see all the tweet locations on one map. I thought it could be a fun, quick project so I fired up Flash, checked out their Twitter streams and whipped up this "mash-up" using Flash, Google Maps and Twitter.

Using the Twitter stream RSS feed

The guys had turned on the location tagging when they got to Paris so by pulling in the RSS feed of their Twitter streams you can see where the tweet was posted from by reading the <georss:point> tag. This tag contains the location and looks like this 40.47338548 -3.67284941.

Anyways, RSS is XML and with E4X its super easy to use in ActionScript 3. Namespaces are a little trickier only because I've used them like twice before, but eventually I got it working. There seemed to be some weird bugs in Flash CS4 where it would just crash when I was using them incorrectly though. CS5 was better, but still beach-balled for a while. In any case the new auto-complete feature in the Actions panel is great!

I've been using the AS3 Google Maps API a lot lately so I went with that since its easy to use, well documented and just works. So after pulling in and parsing the XML, only storing the tweets with location, I created markers for each of the tweets and plotted them on the map.

Lastly adding an onClick event to the markers to show the tweet itself and that was it. All done in the Actions panel too, with no major hair-loss! :)

The hardest part was parsing the date, which is sent as an RFC822 date. I'm not a fan of date parsing so after looking around I found a method that parses it to a native AS3 Date in AS3CoreLib's DateUtils but sadly this library seemed to have some Flex (mx:) dependencies so I just borrowed the bits I needed and was done.

You can check out the first version of the code here. Note: you need to bring in the Google Maps SWC into the project in order to test it out.

Proxies suck

After pushing it to the server I found that I couldn't load in the XML because the crossdomain.xml file on Twitter.com doesn't allow access from a non-Twitter server. Great... Anyways, I found an old proxy script I wrote 4 years ago which seemed to work, so loaded the streams through that and called it a night.

Earlier Seb let me know it wasn't working for him - I'm guessing using the proxy script craps out every now and then.

Using the Twitter API might fix this so I checked out some docs and eventually made it to the search page where they have some cool advanced options like specifying who a tweet came from. Their crossdomain.xml is also a lot friendlier and allows anybody to load in data from them.

Using search

So instead of loading in the Twitter stream I loaded a search that simply got all of Jerry's tweets:

http://search.twitter.com/search.atom?q=+from:jerrychabolla

Now that is an Atom feed, not RSS so I tried changing the extension from .atom to .rss and it worked!

http://search.twitter.com/search.rss?q=+from:jerrychabolla

Since the Twitter stream is RSS this would save me from changing my parsing method. Sadly there is no location data in the RSS search, so I had to use the Atom version which contains the location <georss:point> nested in a <twitter:geo> element.

Lastly Atom feeds use a W3C Date Time Format so I borrowed a method that parses that from the DateUtils in AS3CoreLib instead.

You can check out the second version of the code here. Note: you need to bring in the Google Maps SWC into the project in order to test it out.

The data is now coming directly from Twitter so it should be a lot more reliable! If you made it down this far, check it out

- paulo

Removing all subviews - a comparison of Objective-C vs ActionScript

Posted on , March 07, 2010 @ 20:48 CET

In Cocoa Touch a UIView object is similar to a DisplayObject in ActionScript. You can add a child to its "display list" by saying:

[myMainView addSubview:myOtherView];

To remove the view you say:

[myOtherView removeFromSuperview];

As far as I can tell there is no removeChild like we're used to in AS.

But what if you want to remove all of the children or subviews? Well, we're not as lucky as containers in Flex with that snazzy removeAllChildren() method, but we can loop through the list and tell each subview to remove itself like we do in plain-ol' ActionScript:

while(myMainView.children) {
myMainView.removeChildAt(0);
}

In Objective-C this would be:

while([[myMainView subviews] count]) {
[[[myMainView subviews] objectAtIndex:0] removeFromSuperview];
}

And this works fine. But today I learned a pretty cool trick. Basically [myMainView subviews] is an array just like myMainView.children. And NSArray has this cool method called makeObjectsPerformSelector which basically means make every object in the array call whatever method you want them to.

So instead of looping through you can simply say the following:

[[myMainView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

How cool is that! Not exactly a [myMainView removeAllSubviews] but still :)

- paulo

Playing with radial menus on the iPhone

Posted on Saturday, March 06, 2010 @ 18:06 CET

After watching the Microsoft Courier videos on Engadget yesterday I started thinking about radial menus again. There are a few examples out there for ActionScript but I wanted to figure it out in Cocoa Touch.

So this morning I spent a couple hours throwing some code together. Basically this was the idea:

  1. Listen for touches
  2. On touch-start, start a timer to show the menu
  3. On touch-end, kill the timer. The user will have lifted their finger so we don't want to show the menu
  4. If we're showing the menu, start a timer to remove it once its shown
  5. If a button is tapped or the timer is triggered remove the menu
  6. If a button is tapped, do something

At the end I tossed in some animation to make it a little nicer visually. A quick vid of it is below and you can grab the Xcode project here. Its obviously not perfect, but shows shows the idea :)

- paulo

Detecting what device you're on in CocoaTouch

Posted on Tuesday, February 16, 2010 @ 13:27 CET

Occasionally I have the need to know what device my app is running on (iPhone/iPod Touch) in order to expose or hide certain functionality. One app I wrote for a client recently was rejected at first because there was a "Call" button that obviously wouldn't work on an iPod Touch. Oops!

So I wrote this generic utility class to check the device you're running on with methods that not only return the platform ID, but also a quick check if you're running on an iPhone, iPod Touch or the iPhone Simulator.

The methods it contains are:

  • platformID
  • platformName
  • deviceIsiPhone
  • deviceIsiPodTouch
  • deviceIsSimulator

Dead simple, but very useful, at least for me. If it sounds like something you could use, you can grab the class here :)

Also included is a utility class I've used for a few things such as:

  • stringContainsSubstring - checks if a string contains a substring
  • showAlertWithTitle - pops up a standard UIAlert. Just one line instead of the standard 3
  • openURLInSafari - I never remember this so its a simple shortcut
  • colorForHex - very useful for converting hex color codes to UIColor

- paulo

Stealing the Tweetie 2 tabbar indicator

Posted on Monday, February 15, 2010 @ 17:37 CET

Sometimes you see something so obvious, yet totally original that just seems like the "proper" way of doing it. The latest case for me was in atebits' Tweetie 2 for iPhone. The tab bar has a tiny arrow that animates to indicate the currently selected tab item. In addition to a custom, yet standard indication by turning the icon blue-ish this small animation just makes it even more clear to the user where they are.

So in the tradition of stealing great ideas I tried to find out how to do this. Queue Picasso quote here. Anyways, turns out it was fairly simple - it came down to:

  1. creating a view to contain a TabBarController and be its delegate
  2. adding an indicator image to the TabBarController's tab bar
  3. animating the image to the selected tab bar index when the TabBarController's didSelectViewController method is fired

I created a small Xcode project (following the NIB-less way) that shows how I cloned it. You can see it in action below:

You can download the Xcode project here. Next up is the pull-down to reload mechanism :)

- paulo

NIB-less iPhone development

Posted on , February 14, 2010 @ 17:06 CET

After doing this whole iPhone development thing for a little over a year now I've realized that I hardly ever use Interface Builder. Sometimes I'll create a dummy NIB, drag in some control and use the panels to find what certain things are called which makes it easier to search through help. But otherwise I simply don't use it, kind of like in Dreamweaver or FlexBuilder where I never use the Design view - eventually you start to render this stuff in your head.

Which I suppose is a little scary.

Anyways, another thing I found was that I never really grokked the whole Interface Builder way of dragging outlets back and forth - I'd often drag something wrong and the whole project would just stop working. Finding out what had gone wrong wasn't always the easiest thing in the world.

So I decided to figure out exactly how I could go about avoiding using Interface Builder at all. You can create your own custom UIViewControllers etc, using nothing but code which is a nice start - and, maybe its subjective, but I do feel like they run faster. Maybe its just me.

But the problem was MainWindow.xib. The default NIB, how do I get rid of it? I wanted pure non-NIB based project which may sound silly but hey.

Eventually I found out there are three things you need to do:

  1. Delete MainWindow.xib from the project and send it to Trash. Easy enough
  2. In your project's Resources group, find the Info.plist file remove the entry for "Main nib file base name". Delete the line and save the file
  3. In the Other Sources group, find main.m and modify the following line:
int retVal = UIApplicationMain(argc, argv, nil, nil);

Change this to

int retVal = UIApplicationMain(argc, argv, nil, @"PROJECTAppDelegate");

So if your project is called Cheese, it would be @"CheeseAppDelegate".

Now the project is NIB-less, but because the window is no longer being created in MainWindow.xib we have to do this in code, but its simple enough. In the AppDelegate.m file applicationDidFinishLaunching might look like this:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

Just add the following line before hand to create it:

window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

For me at least I now feel like I have full-control over what's going on in the project and I sleep better at night. It kinda feels like during a pure AS3 project.

Maybe its completely silly but I'll find out in time :)

- paulo

Goodbye 2009. Hello 2010.

Posted on Wednesday, January 13, 2010 @ 17:31 CET

Nearly two weeks after the new year its about time for a roundup post I suppose... *sigh* If you're wondering why its been quiet...

Anyways. 2009 was a great year for I and I.

I started off the year getting forced onto a snowboard by some friends right before Christmas 2008. Well I say forced but it was more of a gentle prodding. And I became addicted. Completely and utterly. It was crack to my Whitney.

I suppose it still is.

So after 8 years in Oslo I finally managed to get around to play in the snow and actually enjoy winter. Whoda thunk it. So while that was going on during the evenings after work - you can ride until 10pm on weekdays up at Tryvann which kicks ass - during the day I spent my time learning a new language. I spoke a dialect from my uni days but it had been years since I'd written any C so I needed a refresher course. I needed a bible.

That language was Objective-C and I immediately fell in love with it and Xcode, which beats the pants off any other IDE I've ever used. Eclipse and anything built on top of it simply can't compete - I suppose the closest would be Visual Studio but its been a really long time since I used that. Actually the last code editor that I embraced to this extent would probably be FlashDevelop. Ahh, FlashDevelop. I miss you.

Come to Mac, please. I'll wait for you.

Anyways, I started to play with building iPhone apps and it was fun! Is fun! Reminded me of the early days of Flash when anything was possible and free and great, when unicorns roamed the cotton-candy fields along with ponies and other cute animals. Maybe I'm being nostalgic but for some reason lately its just not been the same, but I'm sure that will pass.

So iPhone apps! The first one I built was for the city bikes in Oslo and amazingly it reached the #2 spot on the Norwegian app store, and #1 in the Utilities category. It got great reviews in Aftenposten (Norway's largest paper), Macworld and Twitter until it died. But that's another story.

Summer came around and so did one of the most fun projects I've had the privilege to work on. While Chris and Paul were making the Flash on the Beach Connect website, Håvard G designed and I developed the iPhone app for FOTB'09. Its always a pleasure to add life to a beautiful design.

Otherwise there's been lots of small proof of concept apps and prototypes for work - building these is one of the things I love most about my job.

In other news, our local user group, Flash User Group Norway really grew last year and is doing really well with a core group thats grown from 10 to about 15. Our December meetup had over 30 people which was fantastic! I also held a few talks there last year:

I also held a talk at FlashBrighton in November which was great fun, though a bit nerve-wracking at first since the audience held the likes of Niqui, Seb and Aral - all of whom I'd seen talk several times at Flash on the Beach. Luckily I think it went over pretty well :)

Although at first I planned on staying in Oslo for summer I ended up going as far north as I've been in Norway - not very far north - for some white water rafting at Sjoa, a trip to Dubrovnik to celebrate a dual-30th birthday of some friends, a week in Ibiza and a few days in Malaga visiting some childhood friends. As well as a few trips to Brighton...

Ah Brighton. Lovely city by the sea where many a fantastic time has been had. The place where this year I spent my first Xmas without family. The city where my love resides.

Home...

Yes, home. After 9 years in Oslo I'm finally packing it up and moving over to Blighty to a fantastic flat in Hove with a cat and a lovely garden. In March. About 7 weeks.

2010 is going to be exciting!

- paulo