NineOneOne: First App Submitted to iTunes AppStore!

After weeks/months of work I have submitted my first app to the iTunes AppStore!

So, now we wait for the approval/rejection to occur (hopefully not the latter)…

In truth, the amount of work can actually be measured in hours or perhaps days, with the actual building of the app being the least time consuming part since this is a very basic application.

I had no idea going into this the amount of time that would be spent on the preparation of the application for submission. At this point it is probably the most daunting aspect of the process — the development of the product was the simple[r] part. I expect that it will get easier the more apps I create, and having gone through the process once already, at least now I know what’s involved and what some of the potential gotchas are.

It’s tough to go it alone, but for now that’s what I have to stick with, having a day job and no capital to back up my projects or to hire other staff, much as I would like to be able to focus on this alone. It seems to me like you really need a team of three (+/-) people to make a really decent app in a timely fashion. Ideally, I think  I could get by on a relatively lean three-person team and would consist of:

  • Me. (duh)
    • product design and specification
    • UX/interaction design
    • iPhone development/programming
    • Web site programming (if required)
  • graphic designer (my graphic design skills are limited, and I’m really slow at what I do…)
    • iPhone interface eye candy
    • Icon design
    • Web site design
  • Deployment/distribution (and marketing) engineer
    • Manages distribution for testing, arranging and managing alpha and beta tests.
    • Handles all iTunes AppStore preparations (SKUs, marketing materials)

That last one is kind of squidgy, but it was the stuff that really made me insane on this first go-round, and having someone – even just part time – to collect the resources and manage the iTunes part of the equation would be really helpful. This persone would be someone who has done it a number of times and knows all the little gotchas. There are many.

Thankfully, I chose to create an app that was very small and not real complicated to construct. Otherwise, this app would never have gotten submitted! However, since it was an app that I personally needed (but didn’t realize until after I needed it), I felt pretty strongly about just getting it DONE!

I will announce when the app is approved, if it is approved. In the meantime I will be planning out the next update for NineOneOne, in addition to the next app in line…

Easily refresh an UpdatePanel, using JavaScript [Encosia]

Seems that I occasionally need to trigger the postback on an UpdatePanel, and invariably I forget between usages.

Since this particular post from Encosia has saved my bacon on more than one occasion, I shall share it here (and for my own future benefit):

Easily refresh an UpdatePanel, using JavaScript | Encosia:

I’ve noticed a lot of discussion lately regarding methods to refresh an UpdatePanel via client script. This is very easy on the server side, of course. You can just call UpdatePanel.Update(). However, on the client side, the most common solutions I’ve been seeing just don’t feel right. Many will advise you to use a hidden button control inside the UpdatePanel, manipulated via button.click(), to trigger a partial postback of the UpdatePanel. While it does work, I never have been able to get past the kludgey nature of that solution.

In a nutshell, we can use the __doPostBack() method:

Luckily, there’s an easy method for triggering a postback targeted at the UpdatePanel: __doPostBack().

As long as the event target of a __doPostBack() call is an async trigger of an UpdatePanel, the ASP.NET AJAX framework will intercept the postback and fire a partial postback instead. For purposes of demonstration, I’m going to add that to the OnClick event of the container div:

<div id="Container" onclick="__doPostBack('UpdatePanel1', '');">

Now, clicking anywhere in the UpdatePanel will trigger a partial postback, targeting the UpdatePanel. Since partial postbacks follow the full page lifecycle, this will fire UpdatePanel1_Load and update the Label’s text.

Simple CSS Cross-Browser Drop Shadow

After seeing what Google did with Google Images, I thought, “OK… time to find a cross-browser way of doing drop shadows.” I was expecting to find something that combined CSS, HTML, and possibly some JQuery (which has some plugins for doing drop shadows, but none that really struck me as adequate for my project’s needs).

So then I found a reference to this blog post by Robert Nyman:

Drop shadow with CSS for all web browsers – Robert’s talk

…which includes a very simple CSS rule that seems to work in the following browsers:

  • Firefox 3.5+
  • Safari 3+
  • Google Chrome
  • Opera 10.50
  • Internet Explorer 5.5+

…and here’s a quick look at the final product (with some extra commentary from yours truly…):

.shadow {
	/* firefox, mozilla, et al. */
	-moz-box-shadow: 3px 3px 4px #000;

	/* webkit: safari, chrome */
	-webkit-box-shadow: 3px 3px 4px #000;

	/* css3 */
	box-shadow: 3px 3px 4px #000;

	/* For IE 8 (concatenate on one line) */
	-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(
		Strength=4, Direction=135, Color='#000000')";

	/* For IE 5.5 - 7 (concatenate on one line) */
	filter: progid:DXImageTransform.Microsoft.Shadow(
		Strength=4, Direction=135, Color='#000000');
}

I’m thinking that with some tweaking of the colors I can get what I’m really after, and this should integrate nicely with some relatively simple JQuery scripting as well.

We shall see… if it doesn’t work out I’ll post a follow-up.

Setting Session Variables in ASP.NET from JavaScript

Someone on the ASP.NET forums asked how to set session variables in JavaScript. The answers given ranged from “totally wrong” to “rather misleading” or “marginally helpful”.

So in a nutshell, yes, you can totally do it. Not only will you be able to do it, you will love doing it after you get used to the process of getting it set up.

Here’s the recipe for success:

  • Add an ASP.NET AJAX ScriptManager to your page.
  • Create a simple ASMX Web service using Visual Studio.
  • Uncomment the Attribute directly above the class definition that reads [System.Web.Script.Services.ScriptService] to enable ASP.NET AJAX to see your web methods.
  • Create a method to get or update data in your session, and make sure the Attribute above the web method reads [WebMethod(EnableSession = true)] so you can have access to the session via your web service method.
  • Add a <Services> section to your ScriptManager.
  • In the <Services> section add a <ServiceReference> element with the Path attribute set to the path of your .asmx page.

OK, so that enables the ability to access your session from the client side.

But here’s the really awesome part:  if you include a reference to the web service in your .js file like so:

///<reference path=”~/MyServices/MyService.asmx” />

…you will get IntelliSense in the JavaScript for your web service methods! it’s very cool.

So then you just call your web service methods like you would any other JavaScript function. It’s totally easy and almost magical. It’s one of my favorite features of ASP.NET AJAX.

Solved a problem with an Visual Studio 2008 “Source control provider could not be found” error…

I had run into this problem before.

Setup

  1. I have my Visual Studio 2008 options set to reload the previously loaded solution on startup.
  2. I use Subversion.
  3. I use AnkhSVN as my SVN provider in Visual Studio 2008.

Problem
If I launched Visual Studio 2008 with a particular solution loaded when I last closed VS, I would receive a “Source control provider could not be found” error.

However… if I just launched it via double-clicking on the .SLN file in my file system, no error!!!

Weird.

OK – so I did a quick diff on a solution that I knew worked fine. Both had the expected source control provider information embedded:

SccProjectName = "Svn"
SccAuxPath = "Svn"
SccLocalPath = "Svn"
SccProvider = "SubversionScc"

However there was a difference.

The solution that did not generate the error message also contained the following block in the “Global” section:

GlobalSection(SubversionScc) = preSolution
    Svn-Managed = True
    Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection

Which somehow got generated in one solution, but not the one causing problems. Once I copied the block from one solution to the other, the error message ceased to be shown on launch of VS2008.

What happens when you press F5, Ctrl-F5 or click the Refresh Button on your browser

Found this chart by accident, but it is quite useful to know how to refresh your browser and what happens when you perform various combinations of clicking the refresh button vs. F5 vs. Ctrl-F5 etc.

This originally came from a tweet from Webmonkey regarding a post on Stackoverflow:

The table below is updated with information on what will happen when the browsers refresh-button is clicked (after a request by Joel Coehoorn), and the “max-age=0″ Cache-control-header.

Browser Refresh Chart

Smashing Magazine – Getting Started with Web Development For The iPhone And iPad

Web Development For The iPhone And iPad: Getting Started – Smashing Magazine:

According to AdMob, the iPhone operating system makes up 50% of the worldwide smartphone market, with the next-highest OS being Android at 24%. Sales projections for the Apple iPad run anywhere from one to four million units in the first year. Like it or not, the iPhone OS, and Safari in particular, have become a force to be reckoned with for Web developers. If you haven’t already, it’s time to dive in and familiarize yourself with the tools required to optimize websites and Web applications for this OS.

Preparing Your Web Content for iPad (Apple Technical Note TN2262)

Apple ~Technical Note TN2262: Preparing Your Web Content for iPad:

Safari on iPad is capable of delivering a “desktop” web experience. iPad has a large, 9.7″ screen and fast network connectivity, and Safari on iPad uses the same WebKit layout engine as Safari on Mac OS X and Windows. You can ensure that your website looks and works great on iPad, and even create new touch-enabled web experiences for your customers, by considering a few specific differences between iPad and other platforms.

If you have access to an iPad, test your website using the iPad. If not, you can test your website in Safari on iPad using the iPhone Simulator (Hardware -> Device -> iPad). iPad is available in the iPhone Simulator in iPhone OS 3.2 SDK beta 2 and later, which is available to iPhone Developer Program members. In cases where it is possible to simulate iPad-like behavior in Safari on a desktop computer, instructions are given below.

Methods of iPad Detection in Web Applications

With all this Dashcode and iPhone web development exploration that I’ve been doing lately, the question of course came up in my mind… what about the iPad? I’m already using some rudimentary sniffing to make sure iPhone users go to the appropriate spot, but obviously this case would have to be dealt with too, since maybe I would not want to send iPad users to the same spot as the iPhone users.

So I was very glad to find this article: iPad web development tips by Nicholas C. Zakas at his site, NCZOnline.

As it turns out, my method would have failed in that case since I have only been checking for “iPhone” (NOTE: strings are split on multiple lines to fit on this page… they actually don’t have line breaks.):

User-agent string

The previously-linked post describes the iPad Safari user-agent to be in the following format:

Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us)
AppleWebKit/531.21.10 (KHTML, like Gecko)
Version/4.0.4 Mobile/7B334b Safari/531.21.10

This was the user-agent string during the beta testing phase. The format is slightly different for the final release: Although this appears to be the official user-agent string, I have received reports of a user-agent like this:

Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us)
AppleWebKit/531.21.10 (KHTML, like Gecko)
Version/4.0.4 Mobile/7B314 Safari/531.21.10

You’ll note the addition of “iPhone” in the operating system segment of the user-agent string. This brings the user-agent string for Safari on the iPad more into line with Safari on the iPhone and iPod Touch, which have the following user-agent strings, respectively:

Mozilla/5.0 (iPod; U; CPU iPhone OS 3_0 like Mac OS X; en-us)
AppleWebKit/528.18 (KHTML, like Gecko)
Version/4.0 Mobile/7A341 Safari/528.16

Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)
AppleWebKit/528.18 (KHTML, like Gecko)
Version/4.0 Mobile/7A341 Safari/528.16

This means a single user-agent string sniff for “iPhone” returns true in all three cases. The problem, of course, is that you might want to serve different experiences to the iPhone/iPod Touch than you would for the iPad. Make sure you double-check any user-agent sniffing designed to target these devices.

Then we move on to the interesting tidbit for the client-side. If detection is necessary, evidently we can use the navigator.platform property:

JavaScript iPad detection

If you’re trying to detect the iPad using JavaScript, there’s a very simple way to do so: check navigator.platform. The value of navigator.platform is always “iPad” when Safari for iPad is the user-agent. This follows the tradition of “iPhone” for the iPhone and “iPod” for the iPod Touch. This is the most accurate way to detect the iPad from JavaScript, assuming you don’t want to do a full user-agent string sniff.

function isIPad() {
    return navigator.platform == "iPad";
}

Also, keep in mind that navigator.platform doesn’t change even when the user-agent string for a browser is changed.

Good information for both sides of the computing fence, so I’m glad to have it!

When JavaScript Conventions Aren’t Conventions

In experimenting with Dashcode last night using the introductory tutorial provided by Apple, I noticed that in their example, they build a URL dynamically:

var dsource = dashcode.getDataSource("list");
var name = dsource.selection().valueForKey("name");
document.location =
    ("http://www.google.com/search?client=googlet&q="
    + name);

But your first thought when looking at this may be (as was mine), “what if there are spaces or other characters in the “name” value that are not legal in an URL?

So then I set out to use one of the standard functions for escaping URIs: encodeURIComponent.

Unfortunately, when I entered the function I spelled it encodeUriComponent using camel case, which is what I thought was appropriate in this situation. Evidently not. I even was referencing good ol’ w3schools on the subject too.

But once again it kind of gets back to the whole “was it getElementByID or getElementById?” dilemma. And, unfortunately, unlike Visual Studio, there wasn’t IntelliSense in this case.

So then I set out looking to see why it was bombing, thinking that it was maybe a problem in Mobile Safari, like it didn’t support the function. I switched to escape and that worked just fine.

Then I looked more closely at the w3schools page and noticed the difference.

DUH.

Felt real stupid too.

But when using the function with the correct spelling/capitalization it worked just fine. Whew!!!

I guess I should have just copy-n-pasted.

;)