Ad

Our DNA is written in Swift
Jump

Making (Google) Waves

Being a geek at heart I instantly got excited when Google presented Wave to developers attending the I/O Conference. They call Wave a “personal communication and collaboration tool” when they unveiled it to the public for the first time. Since then a digital divide has opened up: those who have Google Wave accounts and those who want one.

For some reason that has many heads shaking in disgust they opted to not immediately release it to the general public like they would do with BETA versions but instead do it in waves of a couple hundred-thousand each. So besides from working for Google or being close to them in any other way, the only way to get a coveted Google Wave account was to wait to be nominated by one of the few members who have nomination rights. The first bunch of accounts went to people who are looking to write plugins aka “bots” to add more functionalities.

After a few minutes of experimenting you start to understand how to edit Waves. You can double-click into a body of text to get an option to edit. Once you do, all other people watching the wave will see your named cursor making the modifications almost live. You can also respond to specific blocks by clicking on their lower border. At the end of a thread you get “Continue this thread”, on a post in between you see “Insert Reply here”.

Due to my interaction with the iPhone developer community and me making no secret out of my wish to get on Wave, some friendly colleague blessed me with an invitation and two days later I was on. If you want to use Wave for something more than just a glorified rich text editor, you need to have contacts to “wave” at. So I started a wave where I am adding every iPhone developer who also happens to have a Wave account.

Wave

If you happen to have a Google Wave account yourself then please wave me at oliver.drobnik@googlewave.com. I am still “collecting” developers. As of this writing there are 16 developers on it. If you open the wave you see the other participants at the top and by clicking on their icons you can add them to your own contacts. The experiment is to see if some creativity could could be sparked if you just get enough like-minded people in the same place.

I am excited about Wave because in daily life I find myself in many situations where I get e-mails with just one line of text that would have been better put in a tweet or instant message. And if you respond to specific parts of the message all the original text is quoted and mangled differently between different e-mail clients. Wave could solve this problem by having one Wave being one topic that is being structured by all its participants. The original bits stay intact. Also you can play back a wave to step through all the changes that where made over time to find out who is responsible for a specific edit.

Wave in mobile Safari

Google Wave can be seen as a the bold attempt to make e-mail and instant messaging obsolete, but it can only achieve this if it reaches critical mass sooner rather than later. It was only 2 years ago, with the purchase of my first iPhone, that I got e-mails working and in sync between my mobile device, my Exchange mail server and my Mac. To make Wave a success over just being a glorified geekery about how cool it is to have multiple cursors editing the same document, there needs to be total integration into the platforms we already use. And I mean BINARY integration. Not just a browser window into a cloud but also offline capability and a mobile UI that will convince people to make Wave their primary means of communication.

Yesterday I also experimented around with the mobile version of Wave. If you access it with your iPhone’s safari you get a warning about it not being supported, but you can proceed at your own risk. Basic reading and responding to threads works well, though after a while you see why its not yet “officially supported”. Well, because of the ALPHA status its not even inofficially supported, but you find that some of the functions just don’t work. For example I found no way how I could enter editing mode for an existing Wave, some miniature buttons don’t do anything when tapped. But it is clear that Google is making an effort, because at first glance it looks quite usable even over 3G.

People, or the current lack thereof, are just one of several factors that need to be addressed to make Wave a success. The other main reason for people writing a blog and trying to interact with readers and friends alike is that you will be able to embed waves into blogs retaining the possibility of commenting and collaborative editing. Somebody could ask me a question and I could elaborate on the answer in a Wave. Once everything has been ironed out I can publish the wave to an article.

One question that’s been on my mind is if Google Wave will also be capable of replacing Wikis. There are many people who either keep all their “documentation” in their mail client or meticulously sort them into their personal Wikis. Or somewhere in between, say text files on harddisks. Wave offers folders and custom searches, but I don’t see yet how you can organize knowledge on a larger scale with it. But maybe down the road we will also edit Wikis from within Google Wave.

Finally the promise is also to be an open standard based on open source. Companies will be able to set up their own Wave servers and provide identity to users. Still, through a process called federation, the promise is to still be able to interact with Waves hosted on Google or other Wave servers. That is clearly the way ahead because even though Google claims to “not be evil” it is simply prudent to keep your confidential data on your own servers.

PS: One video on YouTube was also making waves. Some creative guy used quotes from Pulp Fiction to demonstrate a few of the things you can do in a wave.

Kernseife (SOAP for iPhone)

Applyzer.com has a SOAP-based API, which is also how AppViz is getting the ranking data. I’ve been putting it off for a while, but finally I tried to find a painless way to generate proxy classes for the webservice. I failed.

Well, not entirely, there IS a plethora of frameworks and toolkits that promise to automatically generate proxy classes for you. Only problem, these are either C++ based, or use libxml or use other xml parsers like are present in CoreFoundation on the Mac, but not on the iPhone. Also the code that gets generated by tools like wsdl2objc gives me the creeps.

A proxy class is a class that looks like a normal class that you can instantiate and use it’s methods. But behind the scenes it packages all calls in SOAP or HTTP GET/POST, calls the server, retrieves the answer and unpackages the returning SOAP envelope. Basically you program against the web service as if the functionality offered is part of your local code.

Read more

Getting the User's Language

Geppy Parziale wrote about this topic on his “Invasive Code” blog. The method he proposes is to be found in Apple’s documentation and looks like this:

NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString* preferredLang = [languages objectAtIndex:0];

This is a good method to retrieve the set language, BUT it has two major drawbacks when used in regular apps:

  • Changes are not visible to the app by simply changing the language in settings. It seems you also have to change the region for it to be effective.
  • This really returns the user’s set language but for most cases you instead want to know which localization is used.

What good does it get you if you know that the user has set Klingon as his iPhone language? Not much because most of the time you then still want to know which localization is the currently active one.

You know if the iPhone is set to any language that is not amongst your localizations then the auto-localization feature falls back to the app’s default language, usually English. If you add German localization and the user chooses German then this is automatically used.

I learned this the hard way when we added multiple languages to LuckyWheel. Now here’s the method that I found to be way more useful:

NSString *selectedLocale = [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0];

If you read Apple’s page to the end you get to a box where it says:

“Although you can get the user’s preferred settings from the defaults database, it is recommended you use the CFBundleRef functions or NSBundle class instead. The associated functions and methods of those objects return the preferred language or locale that is also supported by your application.”

That’s exactly what I am saying …

UIImage from UIView

This is a neat trick that I developed when I needed a PNG Image with the same content that I was already drawing in a UIView. I had finished the broad strokes of a small app I am developing and then I figured it would be a neat trick to also be able to e-mail a graphic I was drawing as an attached image.

Turns out to be not that hard to do – after a couple of hours of trial and error. Though attaching said PNG file to an e-mail is only something that’s available with SDK 3.0 and above. But that’s another story, let’s stick to the image generation technique I developed. And one more thing: I am NOT taking about the contents of subviews to be put into an image, strictly what’s the result of the UIView’s drawRect method.

Read more

Manipulating UIColors

For the charting class I am working on I wanted to modify a given UIColor by darkening it and also by making it more translucent. This is both straightforward for some aspects but also tricky for others as I have learned.

Looking at the documentation for UIColor you find that there are only several methods provided of creating a UIColor, but none to actually modify it. Neither you will find any colorByModifying… methods, nor is there a UIMutableColor class true to the general rule of keeping mutable and immutable variants for all the important classes.

If you do a bit of Quartz drawing then you also know about CGColor, CG being short for CoreGraphics. Here we have more luck. Actually UIColor is basically a wrapper for a CGColor as I have learned subsequently. By using CoreGraphics functions to modify this internal CG color I was able to come up with two category methods extending UIColor with the missing functionality.

Read more

LuckyWheel 1.1.2

In the reviews (which we are now getting with MyAppSales *g*) we saw some complaints which this update aims to address:

  • Customers complained of some really “bad English”. Native English speaker Michael Kayne of SendMeToSpace.co.uk volunteered to proof-read and massively correct all of this.
  • Due to a partially intentional “bug” some people who bought the full version saw advertisements on the end-of-round screen. Since they gave rather passionate feedback against that we decided to end this experiment. First via disabling ads on the AdMob dashboard, and now by removing the ad code altogether from the full 1.1.2 version.

As usual we dropped to price to $1 until Apple gives it the nod. We sent them the binary yesterday.

MyAppSales 1.0.9

This new version, on which I’ve literally been working every free minute in the past week, completes the featureset to make reviews useful for people of all languages because it introduces automatic background translations to a language of your choice. And finally you now find full support for automatic downloading Monthly Free and Monthly Financial reports.

Reviews_TranslationChanges:

  • ADDED: Background processing of review texts with optional language translation.
  • ADDED: New setting to choose target language or no translation.
  • ADDED: If you change target language you get the option of deleting previous translations and redo them for the new language.
  • ADDED: Downloading of Monthly Free reports which complement the financial reports showing downloads of free apps.
  • Language changedADDED: Downloading of Monthly Financial reports
  • FIXED: Flag would not show if there was no sale in last 7 days.
  • FIXED: Many other small bugs related to reviews, translations or financial reports.
  • CHANGED: Apple uses 50 pixel country flags now, changed code to get flags of new stores from new URL
  • CHANGED: Revamped duplicate checking code to be more robust.

There is a known issue with the new downloading pipeline which is actually Apple’s problem. It seems that under some circumstances (too much load?) their ITC website does not properly pass on credential cookies to ITTS which is where the daily and weekly reports are hosted. So every once in a while you might get a red message stating that an unrecognized response was received. This is due to the fact that ITTS is sending an HTML page stating that the session has expired when it actually just has started. The present workaround is to simply hit the refresh button on the reports page, the second time it generally works.

As usual you can get these updates via SVN, it’s tagged as well as the current contents of trunk. And of course I am still happy to receive your donations if you think I am doing a good job maintaining and improving MyAppSales.

Deep-Copying Dictionaries

Cocoa Touch has this concept of basic functionality being immutable and then there is a bigger brother of most classes that adds mutability. One effect of this pradadigm is that often you reuse a single NSString throughout your code because you pass around a pointer to it, retaining it wherever you are interested in it’s continued existence in memory.

Only very rarely you would see the use of the [receiver copy] approach which is like an init but creates a copy of the object. As I said this rarely makes sense because if the original is non-mutable in the first place why do I need to clone it? If it is used in another place and then there it is released and some other static value retained it does not have any adverse effect on other places where it is used, provided that proper retaining occurs.

But this feature is there because there might really BE some esotheric cases. There is even the “copy” attribute for properties which sets up your setters to copy the incoming objects, as opposed to the “retain” attribute which simply retains it.

Read more

Where does this annoying tone come from?

At drobnik.com we are not only publishing our own apps or doing contracting/consulting. Sometimes we get approached by people with an interesting idea or concept for an app who are looking to partner with us. The simplest form of partnership is a publishing deal like we struck with Laurens from ipodandiphoneguide.com. Laurens developed the app “Frequency Annoyer” and sought a partner to publish it for him.

AnnoyerReasons to do so may vary to enter into such an agreement, most developers try to “go it alone”. But Laurens recognized that our experience and help would allow him to reap way higher benefits as he would have been able to by himself. Faster to market, easier navigating around the cliffs that Apple’s review team presents, copy protection, intuitive reporting and lots of other reasons why drobnik.com is the publishing partner of choice. In short: drobnik.com knows how to get you published pronto.

Annoyer IconFrequency Annoyer allows the user to emit high frequency sounds up to the maximum the iphone is able to. There are many uses for this, besides testing your hearing or repelling insects. The reason why most people bug this app is to annoy other people who have a sensitive enough hearing. Did you ever find your self asking “Where does this annoying high pitched tone come from?” This is the app that puts the capability for such pranks right into your pocket.

Getting it ready for to pass Apple’s review was no easy task, let me tell you. Theoretically the iPhone speakers should be able to go up to 20.000 Hertz, but in reality there are hardware differences between iPhone, iPhone 3G and iPhone 3GS which made Laurens’ work really hard. To put it in simple terms: iPhone speakers: Crap. iPhone 3G speakers: fine. iPhone 3G speakers: very fine, twice as loud as 3G.

Rigorous testing was necessary to make sure that only frequencies where enabled that could be sounded without problems. In some cases the physics of sound made it necessary to reduce the volume of the sound to prevent overloading of the speaker and nastly crackling noises. Anything else might would have gotten the “might lead to customer confusion” response from Apple.

Several weeks of acceptance testing on 4 different devices finally paid off when Apple approved the app on the first go. Since then it became an overnight success outperforming all our other apps on the store, even reaching sales rank #5 in the Entertainment category for Netherlands.

Annoyer Rank

– Ranking Data by Applyzer.com

The Dutch are for some reason one of the countries that buys most on the app store, at least when it comes to satisfying their hunger for interesting new entries in the Entertainment category. Twice as many Dutch purchased “Frequency Annoyer” (in absolute numbers) on the second day than people from the USA. Could it be that the US market has reached its Apex and now the sales volume in other markets finally has a chance to play catch-up?

You can now get your mobile “Frequency Annoyer” on the app store. Please comment at the end of this article of interesting uses you found or give us your prank reports.

MyAppSales 1.0.8

ReviewsIf you’re scratching your head, thinking to yourself “didn’t I just see a new version just 5 days ago?” then you are absolutely right. There really was a new version that recently. But that did not prevent me from going into overdrive and burn much midnight oil to get the next release out.

Buckle up, this is “The Review Release”!

Enable Reviews

Changes:

  • ADDED: Tapping on a row on the apps tab now shows the reviews sorted chronologically, new reviews have a red headline
  • FIXED: A bug would cause a chart to hang if the user had sales in excess of a couple of thousand dollars per day or week. Yes, there are really such iPhone Developers who make boatloads of money and they use MyAppSales.
  • CHANGED: Added compiler directive to prevent trying to build the project below SDK 3.0. I figure you are all developers out there and no serious developer would still have his iPhone on an OS below 3.0.
  • CHANGED: The iTunes Connect downloading pipeline is now an NSOperation using synchronous calls. Added a ton of additional error catching code.
  • UpDownADDED: Buttons on the review screen to directly page to the previous or next report of the same type.
  • ADDED: A multi-threaded review scraping engine which is also based on NSOperation. This is amazingly fast compared to competing engines, and all running completely on a background thread. So this can run while you are checking the new daily report.
  • ADDED: Settings to allow enabling of review downloading and setting of the interval.
  • BadgeADDED: Badges on the app icons show the existence of new reviews.
  • CHANGED: your database will be upgraded to schema version 3 with new tables for the review stuff.
  • FIXED: The sync button on the review page is now properly disabled when the sync manager is active.
  • ADDED: Monthly Free reports now get downloaded as well.

Known issues:

  • Financial reports are still experimental and thus don’t get downloaded automatically. Sometimes they are labelled incorrectly and there are lots of other unsolved problems. Check the bug tracker to find out which.
  • Sums are generated every time after there are new exchange rates or new reports. This might cause short periods of lagging.

As usual, before you upgrade, please make a backup of your apps.db. The upgrade should be straightforward, but it never hurts to have a backup. 😉

The release is tagged in /tags/release-1.0.8 and you may checkout this exact version either from the terminal or via XCode. Or you can simply “Update Entire Project” in XCode’s SCM Menu provided that you have linked your working copy with the repo.

If you have not donated yet to keep me improving MyAppSales, then please do so now to get access to this fabulous update. If you already did, you are welcome to show your continued appreciation by another small donation.