Plans, reflections and dreams.
This is a complete self reflection, so move along if you don’t want to read anything personal ;)
As you may know by know, a few days ago, we announced partiql, a software company. And this is my story behind it, why it’s such a damn joyride :)
About 9 months ago, I sat in the sun, somewhere between San Jose and Palo Alto and had a nice sandwich, probably Subways. I remember that day pretty clearly, I almost got arrested at Google and Apple at the same day ;)
It was in situations like these when I dreamed of having my own company, getting up late in the morning, creative people around and work on things I like and only a few who I trust tell me what to do in certain situations. Why? I don’t know. Daydreaming perhaps. I just thought about making a living around the corner of LinkedIn, Radar Networks or Digg. It all felt so vibrant, so bold, so pumping. Back home, it was hard at first, realizing that the bank account probably wouldn’t allow an own startup right now.. Days went by, I started working at Memonic, got quite a good feeling of what it’s like to work with a startup. They always call(ed) it Roller Coaster, and that’s probably the right term for it. One day you are down, no users, no one cares about you. The other day you are featured on lifehacker.com. Yet when you have to explain the product to someone you suddenly realize that you haven’t done so much yet but yet you worked like crazy.. WTF? (That’s valid for everything I’ve ever done..) However, you get something back, that not everyone gets. You see something grow, something “getting born..”
I once had a nice chat with Marc Liyanage about how long he will remain a Software Developer, because I was unsure if I wanted to do this all my life.. He said something like “writing software is one of the only things you can create something on your own out of nothing” – and this sentence has been in my head ever since.
So, this feeling of something getting alive… I tell you, it’s quite addictive. You not only get sick and tired of doing the same stuff over and over again, you also feel the need to create something from scratch every now and then. Having tabula rasa once in a while is a nice feeling. And this is why we and specifically I founded partiql.com.. Every day I come across technology I so desperately want to try out, be it at ETH (rarely) or by reading (often), that I would let everything else fall for the moment. “Es grausams ADHS Chind” (EN: “a terrible ADD child”) – as my girlfriend once noted :) Also, I have that inner desire to strive for perfection. And this doesn’t mainly mean the perfection you see, but the perfection I know. I think every developer knows what I’m talking about, that line of code that shouldn’t be there, that one element that wasn’t meant to be in that class.. (But of course also things that you might and will see..). Since Stefan is one of the best partners you can imagine to start up a company, it’s pretty easy for me to do a lot of refactoring and prototyping. Currently, we have a setup of 4-8 hosts, completely dynamic, running with some pretty fancy software like MongoDB and other software that even I wouldn’t recommend if we had 20 employees to feed (no offense, former employers). It’s those risks that make it so exciting. Will the API hold? Will the setup scale for real? Is the App really ready? Will we get a lot of one star rating because we didn’t live up to the expectations?
Can you feel it? I really cannot tell you to try it out, because it’s like publicly announcing that you should try cocaine or something.
Even the marketing. Both Stefan and I never did something like this before. Raising expectations before something’s finished? Not really our style. But, it’s like adding a bit of concrete into the water you are about to jump into from about 100m (300ft).
There are still many dreams to come. Like providing that space of creativity, sanctuary where other people can experience the same thing, but maybe with some help and a fallback option. Or going completely different ways with other style of applications, other devices.. Whatever will come, I’m excited as hell to be on this trip now.
Wanna know what it’s like? You hardly get any sleep, you are always nervous (“chribelig”) and yet you have that superhero feeling inside of you. A burning desire to tell everyone what you are doing yet you cannot tell anyone. Having good friends around you that help you, that wish you well but who’s expectations you have yet to meet. It feels like Stockholm Syndrome, it might torment you, but you still would never let go.
Thank you all for the great support so far and I really hope we can live up to the expectations we have set.
Look! UIAlertView is dating UITableView!
As you may have guessed, this is about UIAlertView containing a UITableView. Since I started playing around with GameKit, I had the issue that I couldn’t use the PeerPicker with Client/Server stuff..
I can’t really get into the stuff we are doing and where we are using it – but I can offer you some trick and code to have a UIAlertView displayed with a fully controllable UITableView.
I started off with making it a decorator.. After 20′ I had to give up, because it was just too complicated to decorate objects where you don’t really know what’s going on. So I had to subclass it – unfortunately, but anyway..
Let’s take a look at what you would probably like to have..
Client
UIAlertTableView *alert = [[UIAlertTableView alloc] initWithTitle:@"Select Option"
message:@"select option or create one"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Create", nil];
alert.tableDelegate = self;
alert.dataSource = self;
alert.tableHeight = 120;
And this should be the result:
Alright, so, we just add a UITableView to the UIAlertView as a Subview, right? Hold on, Tiger :)
First of all, if we set the message to nil, we want to have this:
And if we rotate, we want to have the nice effects! Like this:
If you only want to grab the code without BlahBlah: UIAlertTableView on Bitbucket.org (btw. I switched to bitbucket.org – but that’s another story)
So, let’s look at the code a bit:
UIAlertTableView.h
#import <UIKit/UIKit.h>
@class UIAlertView;
@interface UIAlertTableView : UIAlertView {
// The Alert View to decorate
UIAlertView *alertView;
// The Table View to display
UITableView *tableView;
// Height of the table
int tableHeight;
// Space the Table requires (incl. padding)
int tableExtHeight;
id dataSource;
id tableDelegate;
}
@property (nonatomic, assign) id dataSource;
@property (nonatomic, assign) id tableDelegate;
@property (nonatomic, readonly) UITableView *tableView;
@property (nonatomic, assign) int tableHeight;
- (void)prepare;
@end
You see: we subclass UIAlertView, we have a UITableView, we have a delegate which needs to implement the protocol as well as a dataSource. Straight forward, I’d say…
Now, as for the implementation, one would think: just overload the “show” method and insert the TableView as a subview etc. Well, that works – NOT. First of all: you have to resize your AlertView, then you have to move the buttons down and then you have to place the tableView somewhere (esoteric?).
OkOk, just overwrite the drawRect then? You are getting closer!
But, first, let’s have a look at the prepare method.
UIAlertTableView.m:prepare
- (void)prepare {
if (tableHeight == 0) {
tableHeight = 150.0f;
}
// Calculate the TableViewHeight with padding
tableExtHeight = tableHeight + 2 * kTablePadding;
tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
tableView.delegate = tableDelegate;
tableView.dataSource = dataSource;
// Insert it as the first subview
[self insertSubview:tableView atIndex:0];
}
This code creates the TableView but does not set a real frame yet. It sets the given DataSource and Delegate. To be totally correct, there should be a custom setTableDelegate / setDataSource method which changes them in the tableView – but this is left as an exercise to the reader :)
After the creation, we insert the tableView as the very first subview of the alertView – so we know where to find it again and that nothing is hidden because of the tableView.
Now comes the tricky part: drawing.
For that, we use a private API call to the AlertView, called layoutAnimated:(BOOL)animated.
We overload it in our custom subclass because the initial drawing and the drawing on setNeedsLayout goes through that method.
After that method is called, all the elements that belong to the AlertView (title, message, buttons …) are arranged, so we can use those values for our next computations.
So, this is how it goes:
UIAlertTableView.m:layoutAnimated
- (void)layoutAnimated:(BOOL)fp8 {
[super layoutAnimated:fp8];
[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y - tableExtHeight/2, self.frame.size.width, self.frame.size.height + tableExtHeight)];
// We get the lowest non-control view (i.e. Labels) so we can place the table view just below
UIView *lowestView = [self.subviews objectAtIndex:0];
int i = 0;
while (![[self.subviews objectAtIndex:i] isKindOfClass:[UIControl class]]) {
UIView *v = [self.subviews objectAtIndex:i];
if (lowestView.frame.origin.y + lowestView.frame.size.height < v.frame.origin.y + v.frame.size.height) {
lowestView = v;
}
i++;
}
// TODO: calculate this value
CGFloat tableWidth = 262.0f;
tableView.frame = CGRectMake(11.0f, lowestView.frame.origin.y + lowestView.frame.size.height + 2 * kTablePadding, tableWidth, tableHeight);
for (UIView *sv in self.subviews) {
// Move all Controls down
if ([sv isKindOfClass:[UIControl class]]) {
sv.frame = CGRectMake(sv.frame.origin.x, sv.frame.origin.y + tableExtHeight, sv.frame.size.width, sv.frame.size.height);
}
}
}
Step by step: first, we call the superclass - so everything gets arranged.
Then, we set a new frame for the AlertView, which is the same frame + tableHeight + padding. But we also need to rearrange the frame - which is half of that additional height.
After that, we compute the lowest "sitting" normal view - no control object - in the alert view. We loop through it, until we find the first control element - which are usually the buttons, because they are added at the end. You could loop through all views and get the lowest from any non-UIControl objects. But this works :)
This position is used to place the TableView at the correct position - whether you have a message, a title or whatever there.. but it needs to be above the buttons - UI standards.
To be above the buttons, we need to rearrange the buttons, and this is what happens: all UIControl object in the AlertView are moved down by the size we added to the AlertView frame - the complete TableHeight. And this is it.
We resize the AlertView, calculate the position where the TableView is supposed to be inserted at and then move the buttons. If we rotate, this gets calculated again and nicely rearranged.
Note: you can apply the very same method for any other UIView object you want to insert into an UIAlertView.. Be it TextField or ImageView or whatever. (For textField, you should use their private APIs though)
Again, code is here: Code on Bitbucket.org
Beer for Issue!
Hi there.. It’s been a while and I’m still pretty busy, but I feel like I have to write something this very sunny afternoon.
There are a lot of projects in the pipeline, a few will come out sooner or later :)
One project which is still making my head go up and down and left and right is Transport. I somehow managed to get on the shortlist of this years Best of Swiss Web. Besides that, I found a still secret partner for the work on Transport. There has been a lot of development, of which not all is on github yet – some parts are just not ready for open source deployment. (But they will be!)
Today, I want to talk about my beta testers – they are great. Most of them anyway :)
I’m facing two problems with them though. First, I don’t know all of them – which is unfortunate. There are some I just cannot meet because they live in the south of Uguhagdarbia (not quite..) but there are others which live in the very same city – Zurich – and I still haven’t managed to meet them.
Second, some of them just want to have an application before everyone else does – (no offense guys..) – and what I want in return is feedback – and not always get it. However, there are some very serious beta testers and I really want to thank you :)
This night, I had an insanly great idea to solve both problems at once and actually solve a third problem: get more testers :)
So what is it about? There have been rumors, that Transport will be ready at the end of march, and so I will need testers in the next few weeks.
This is why I proudly announce the “Beer for Issue” program :) What is that? My idea is: If you sign up until the 20th of march on beta[AT]codesofa.com with your UDID, name and e-mail (see Apply for Beta) and you are among the first 70 to sign up, then you get into the “program”. After that, you will receive a copy of “Transport.app” Beta for the iPhone somewhen after the 20th.
`HOLY CRAP WHERE IS THAT BEER!` – yes, we are coming to it. After that, you will receive instructions of how to report bugs/issues/whatsoever to me :) Since I really appreciate your time and haven’t figured out a way to show that to you, I offer Beer. Free Beer actually. :) The exact rules have to be determined after the signup is completed, but I plan to give out a beer for every fibonacci number of issues you report, starting at 3.. As long as they are not a duplicate. With “improvement” requests, I’m not so sure yet. That will be a mater of personal oppinion, if they are great, I’ll buy you 2 beers, if they are ridiculous, you’ll have to buy me 4 to make me implement it ;)
Let’s make an example: You report 3 issues – get 1 beer, 4 issues – still only 1, 5 issues (2+3) – get 2 beers, 6 & 7 issues – 2 beers, 8 issues – 3 beers etc. Maybe there will be more beer – I don’t know yet :)
`IS HE INSANE?!` – No, not at all. This will force me to write good code, so I don’t have to buy a lot of beers and besides that, I get to know all of you :) It’s like a release party.. But more fun because everyone worked on it..
In short:
- Write me an E-Mail with you iPhone/iPod UDID, your name and your e-mail address until march 20th, 2009 to beta[AT]codesofa.com
- Report issues on “Transport” iPhone app.
- Get paid in beer – and yes, for ladies there will be a special arrangement possible :)
Have fun.
btw.: There is some special ruling for the last testing-period testers, I will figure something out – but you’ll get more ;)
done.
So much for tonight. Thanks Stefan :)
Let’s celebrate the death of the iPhone NDA
If you haven’t got the wonderful news so far: the iPhone NDA has finally been lifted :)
This is of course a big step forward into an open world with open software for the iPhone – at least I hope so. But I’d like to take this chance and blog about something, that bothered me quite a while.. The locator on the iPhone.
The point is, the locator is not so easy to use as one might think. There is only one way to access it – and you always get every locations, be it WiFi, GSM or GPS. That means that the Locator calls the callback functions multiple times. It tries to find the most accuracte position, and it tries not to return any less accurate positions.
There is this nice example included with the SDK. Did you use it? Poor you. It seemply doesn’t work :)
** here should be more text, but the CMS killed it without notice – so you’ll have to wait a bit **
Alea iacta est.. almost.
Well.. Imagine.. You name your child “Bryan” and your wife/husband is from let’s say Iran.. To make your child getting the iranian passport, you’d have to name him/her “Ali” or something (this is actually true.).
Then you know how I feel now :)
Imagine as well: You are Opel.. They made some not so good cars back then – they had a few bugs. Then they brought out some better cars (I heard so..) but now, nobody – except the few who are really interested in those things – buy Opel anymore. Why? Because they had a bad experience or missed something.
Recently I heard something like this from a former PHP programmer:
I gave him some piece of code.. like this: “$a = new foo_class(); $b = $a;” He was pretty upset that I was going to post him a code which included object copying – and that’s exactly what he hates about PHP. Well this might be true for PHP4 but not for PHP5..
What am I going to tell you.. Well, the recent numbers of “GottaGo” made me think. We had an enormous loss of users after the 2.1 update and those are not coming back – probably never. So even if those hardcore fans who sticked to “GottaGo” over the time have updated so far (we only have about 5% v.0.0.1 users) those who missed something in the first version are not comming back – and they are not trying it again. Sad but true :)
As mentioned in an earlier blogpost, I’m not quite happy with the name “GottaGo” anymore. And even less with the logo. (Not the design itself, which is great, but with the message it sends..)
Besides that, “GottaGo” plays only a siderole in the new version, which kinda makes it not being “GottaGo” anymore. Rather a Schedule/Timetable app based on GottaGo. (To talk a bit of the coding side: almost 75% of the code was rewritten for this release – and of course every pixel was redesigned..)
What I think is that “GottaGo” deserves a new release – with a new name. Unfortunatly I can’t go with a cool name – although there were a few very good suggestions – but all geek names again :)
This means, we are most probably going with “Transport” and some other minor changes.. I hope you don’t mind if I rename this and me being an attention whore – but I think those who supported me in this new release deserve it.. And I think those who are not happy with “SBB Fahrplan” deserve it as well.
Let’s see, how this pays out.. It might be a horribly wrong decision, but since it’s a free-time project, I can only learn. :)

