WebApp up iPad home screen bookmarks

While discussing mobile web frustrations with Rob, we hit on an idea to reclaim a few pixels for sites that we visit regularly enough to have added them to our device’s home screen.

Having been working a lot with HTML 5 for mobile app development recently (which Rocks, with a capital ‘R’) I suggested that we recycle Rob’s home screen icon injecting bookmarklet to add Apple’s web app meta tag to the document’s head, so that a site could be forced to run ‘full screen’ when added to your device’s home screen… Simple but effective!

Here’s the code, for anyone interested:


javascript: var s = document.createElement('meta');s.setAttribute('name', 'apple-mobile-web-app-capable');s.setAttribute('content', 'yes');document.getElementsByTagName('head')[0].appendChild(s);void(s);var z = document.createElement('meta');z.setAttribute('viewport', 'apple-mobile-web-app-capable');z.setAttribute('content', 'width=device-width');document.getElementsByTagName('head')[0].appendChild(z);void(z);

So, just save the above as a bookmark in Mobile Safari (or just bookmark this) and ‘go to it’ before adding a site to your home screen… and, hey presto, your newly book marked site will run full screen when you go to it!

Getting Big Brother to monitor custom processes

This is very easy to do - and the documentation is bang on the money… but as always, there are no examples!

So without further a do…

Create a bb-proctab file in the etc folder in your Big Brother’s home folder with the following syntax:


<host name>: <yellow alert processes> : <red alert processes>

Processes are space delimited (enclosed in quotes where necessary) and can be followed by a semicolon if you want to specify a minimum or maximum of times it should be running.

The example below will issue a yellow alert if myscript.pl is running more than 8 times (to check for over forking or excessive load) and then a red alert if cron, bbrun or myscript.pl stop running.


localhost: "myscript.pl;<8" : cron;>=1 bbrun;>=1 “myscript.pl”

Developing for iPhone (and UIScrollView Example)

So, what have I been doing lately? Well I’ve been wrestling with my first Mobile App in Objective C and the Cocoa Touch frame work for every bodies’ favourite mobile platform!

Between a day job, a social life and a couple of other projects, I haven’t really had the time I need to really get to grips with iPhone as a development platform yet… one of the biggest things that is holding me (and I’m sure a lot of other developers) back is the limited documentation that’s available.

What you get from Apple with the SDK (both actual documents and help given by XCode’s research assistant) is very good but it suffers from being single sourced. That is to say that there are no other contributors in the periphery giving comments, suggestions or even pointing out mistakes with the official docs. This is partly because of the infamous iPhone SDK NDA (which fortunately as now being lifted) but it’s also down to the fact it’s a relatively new and proprietary technology…

A good example of this is the problem I had getting the UIScrollView class to work. The documentation was accurate to a ‘T’ and Apple even provided some fairly complex implementations to demonstrate how to use it with paging and zooming… but there was no example or explanation of how the fundamentals worked. I was left with the impression by the sample code that I needed to set up a delegate to handle all the events that the class actually does straight out the box! An hour later I was still playing around with implementations of the UIScrollViewDelegate protocol, trying to get my scroll bars to work when, all the while, all I needed to do was tell my UIScrollView the full dimensions of its content!

All I’d have needed to see was the 4 line example I’ve drawn up below, in the absence of Head First iPhone Development, I’ve even made a simple colour diagram showing the relationship between the two areas you have to specify! I doubt something so simple will help many people in the future, but you never know… and I hope this will be just the first example I write up for my blog!





uiscrollview diagram


//all variables are of type CGFloat, unless named otherwise! 

UIScrollView *myScrollViewObj = [
    [UIScrollView alloc] initWithFrame:
          CGRectMake(frameX, frameY, frameWidth, frameHeight)
];

[myScrollViewObj setContentSize:
     CGSizeMake(contentWidth, contentHeight)
];

[myParentViewObj addSubview:myScrollViewObj];
[myScrollViewObj release];



PS. Hey Steve, please don’t sue me! The NDA’s being lifted anyway right? :)

Great Interview Question

So, how this for an interesting interview question:

You have two variables with integer values, without creating a third variable exchange their values.

At first it sounds fairly simple, but then it hits you that it’s actually not… there’s no simple ‘exchange value’ function. Here’s how I solved it:


list($a, $b) = array($b, $a);

My answer provoked a surprised (if not bemused) Yeah, that’d work… I’ve never heard that one before look. After a little conversation it turned out that the answer they were expecting but rarely got was:


$a = $a + $b;
$b = $a - $b;
$a = $a - $b;

My answer is of course better, because it works with any type of variable, but what they were actually testing for was a logical brain that would solve the problem with simple maths… The fact that most candidates don’t even try answering the question goes to show how dastardly it is!

Setting and Getting Cookies in Google’s WebApp

Here’s the disclaimer: I’m currently teaching myself Python for use with Google’s App Engine and (unlike my PHP or Perl) I’m not entirely sure if the below is best practice or even remotely sane, but that said, it does seem to work for me!

Setting a Cookie

Notes: Obviously the code is running in a controller (or rather a Request Handler) that extends webapp.RequestHandler and you’ll notice that I had to use a Regular Expression to remove the header name from Cookie.SimpleCookie’s output so I could tie it in to webapp’s header frame work which should stop any output buffering issues in the future.


import Cookie
import re
import base64

class YourHandler(webapp.RequestHandler):
   cookieName = 'MyCookie'
   domain = ''
   expires = 360
   value = 'Some value or something...'

   def get(self):
         simpleCookieObj = Cookie.SimpleCookie()

         simpleCookieObj[self.cookieName] = str(base64.b64encode(self.value))
         simpleCookieObj[self.cookieName]['expires'] = self.expires
         simpleCookieObj[self.cookieName]['path'] = '/'
         simpleCookieObj[self.cookieName]['domain'] = self.domain
         simpleCookieObj[self.cookieName]['secure'] = ''

         #Cookie.SimpleCookie's output doesn't seem to be compatible with WebApps's http header functions
         #and this is a dirty fix

         headerStr = simpleCookieObj.output()
         regExObj = re.compile('^Set-Cookie: ')
         self.response.headers.add_header('Set-Cookie', str(regExObj.sub('', headerStr, count=1)))

Getting a Cookie

Notes: This is much easier, we just have to make sure that it exists.


import Cookie
import base64

class YourOtherHandler(webapp.RequestHandler):
   cookieName = 'MyCookie'

   def get(self):
      try:
         cookieValue = str(base64.b64decode(self.request.cookies[self.cookieName]))
      except KeyError:
         #There wasn't a Cookie called that
         cookieValue = ''

Changing Default hostname in Google App Engine Launcher

Google App Engine\'s WebApp preferences

These past few weeks I’ve mostly been writing Python for Google’s App Engine and listening to Country Music. They say a change is as good as a holiday, so two changes must be equivalent to a cruise or something.

To cut to the chase, today I was testing some Cookie functionality and needed to run my WebApp on another domain other than localhost and of course, since I was using the App Engine Launcher GUI rather than the command line, I couldn’t find any documentation on how to do it.

To be fair, I didn’t look very hard, I just tried the following:

I added –address= followed by the hostname I wanted to run my WebApp under and low and behold I could access it across my LAN!