By Werner Ruotsalainen on Sun, 01/06/2013
With the release of Windows Phone 8 and backed by (at least when it comes to Nokia) truly excellent and unique hardware manufacturers, Microsoft's mobile platform has become really interesting. Therefore, I, a seasoned iOS programmer (and iOS programming lecturer) decided to provide you, preferably an iOS programmer (or at least a geek interested in coding) a long tutorial series specifically tailored for fellow iOS programmers to greatly help getting up to speed with Windows Phone (WP for short) programming.
Note that this series will have tons of iOS-specific tips and tricks. Therefore, if you are in no way interested in WP, you can still find a great deal of valuable information on iOS programming. For example, I've dedicated a great deal of text to explain the differences between Xcode 3.x and 4.x and between the ARC-less and ARC-enabled programming.
While, from time to time, I do elaborate on the differences between it and its predecessor, I assume you use Xcode 4.x and Visual Studio 2012 (VS2012). The former is, unfortunately for long-time iOS programmers, wildly different from its pretty much outdated predecessor. On the other hand, VS2012 isn't that much different from its predecessor, VS 2010 and, fortunately, you can also develop WP7 applications in it. This means there's no need for discussing VS 2010 either (unless you in no way want to upgrade to Windows 8 on your desktop. As the upgrade price is really low, I don't see why you shouldn't.)
I know there are some WP articles / material already out there specifically meant for iOS programmers but they're pretty much outdated, particularly now with WP8 on the scene. (Needless to say, I'll talk a lot about WP8.) In some cases, I don't spend as much time on a subject as I should; nevertheless, I always try to provide you with the relevant links for more information.
1. Developing with hardware deployment
1.1 Other apps you must install for testing on real devices
On the Mac, you won't need to install anything else than Xcode for full iOS development. Not so with developing for WP.
First, you absolutely must use hardware deployment if your CPU isn't sufficiently current and, consequently, doesn't support running hardware Hyper-V support (see THIS, THIS or THIS (Parallels-specific for people having the necessary hardware but running VS2012 under a virtualization software like Parallels Desktop)). When developing for iOS, you only need to do the same with hard- or impossible-to-simulate input data like GPS, compass, gyroscope, camera inputs. With WP development, the situation is much more dire.
If you plan to test your apps on a WP7 device, you will need to install the Zune client. (Download from HERE)
1.2 Registering your device for hardware deployment
During the years, Apple's approach to registering new devices (or just enabling them again for development after a system restore) has become much-much easier. You in no way need to visit the Developer Portal any more. All you need to do (assuming you're a team admin if it's a company license; individual license holders will not have any registration restrictions) is clicking the well-known “Use for development” button in Window > Organizer (that is, inside Xcode itself) and, when prompted, enter the developer credentials. Everything else is done automatically and promptly meaning you can start deploying your apps on your iDevice in 10-15 seconds (unless you are using a company developer account and are just a team member, not an admin)
Not so with WP development. The VS installer installs a separate (as opposed to the built-in Organizer in Xcode) app, “Windows Phone Developer Registration”, where you need (as with Apple's Organizer) to enter your (upon paying the $99 annual fee) registered e-mail address and password. Of course, you also need to connect your WP phone – and you, as usual, need to unlock it and make sure the needed device handler app does run in the background. Fortunately, the need for using a separate app is the only problem: as soon as the registration is done, you can start deploying your app on the device right away, just like on iOS.
1.3 Removing apps before redeploying
While developing, you'll sometimes find VS2012 doesn't seem to deploy the latest version of the app on your hardware device. Then, a simple desktop-side clean (Build > Clean Solution) may not help – you'll need to actively remove the app (by tap-and-holding it on the phone and, then, selecting “Uninstall” from the pop-up menu) and, then, redeploy it. In Xcode, the “worst: thing I had to do was cleaning when running into cases where a simple recompilation didn't suffice. (Of course, if you do want to delete the contents of Documents without using other apps like iTunes (if you do enable iTunes File Sharing in the .plist file) or iExplorer, the easiest is always completely removing the app.)
2. Projects in the file system
Xcode 4 has made the projects definitely easier to quickly organize and overview in the file system. Now, you no longer need to search the .xcodeproj file from inside the, possibly, ocean of .pch, .plist, main.m etc. files – it's the only file in the root of the project (where the, by default, only subdirectory was Classes with the true, non-main.m class files), all the other files being moved to a subdirectory named after the project name. (Interestingly, there is no Classes subdirectory inside that. That is, by default, your sources aren't separated from the other files any more. It's only the language-specific resources (by default, en.lproj only) that have their own subdirectory. Of course, as with the 3.x series of Xcode, you can organize your source files into physical layers in the file system too, not only (virtually but not physically) in Xcode itself.)
You can also quickly show the entire project (and the compiled app after a compilation in a completely different, randomly named folder) or any individual file in it by right-clicking it and selecting “Show in Finder”. (Doing the same with the compiled .app file is extremely useful when you create files from your app running in the Xcode simulator and you want to quickly find them.)
Doing the same is equally easy in VS. Just right-click the tab name and select “Open Containing Folder”:
(As usual, click the image for an enlargened, much better-quality version.)
3. Quick event handler and outlet setup
Xcode 4 made it much-much easier to quickly declare both event callbacks and IBOutlets in header files by integrating Interface Builder into Xcode: you only need to, after selecting the XIB file to wire in to the code and switching to the double-pane mode (the center icon in the “Editor” icon trio in the upper right corner) right-click and drag from the widget to the header file and select whether it's an outlet or an action you want to declare (see the uppermost “Connection” drop-down list, the default being an outlet) and name it. This is definitely much faster than manually entering all those long IBOutlet declarations in the header file (along with their @synthesize in the .m implementation) and, after making sure the header is saved (so that the non-integrated IB sees it), one by one, dragging them to the main window of IB, listing IBOutlet-tagged properties listed in the header file of the View Controller the particular XIB is connected to. (With actions, you can define the type of action here, too. The most sensible and used ones will be the default ones here - for example, for buttons, Touch Up Inside. Note that these are exactly the same defaults – for example, for UITextField, “Editing did end” and not “Did End On Exit”, which you must keep in mind if you want to hide the on-screen keyboard with a call to [UITextField resignFirstResponder] from an IBAction callback method.
In VS, when dropping a component (say, a button) on your interface, you can quickly add an “x.name” attribute to its XML tag, providing the name you'll reference it from your code. (BTW, upon creating a new project, the two widgets already available in the UI, two TextBlocks, will also have this attribute, with the values ApplicationTitle and PageTitle for the upper and lower one, respectively. This means you can any time, say, set their text via “PageTitle.text = “something”;”. New components you add to the interface won't have this attribute automatically added.) This is the only place you should declare a name for your widgets – no wiring is needed, unlike in Xcode.
Wiring IBAction-like event handlers is also very easy: they're, as opposed to outlets, automatically created. You only need to double-click the event-generating widget to quickly move to the action method definition. (Note that, as with Java, there are no header files for C# files. Not so with WP8-only C++-based projects, of course.)
4. Object library
To quickly find and pick UI components, you use the Object library in the lower right corner of Xcode, in the Utilities pane shown by default (you can hide it via View > Utilities > Hide Utilities). (Note that the pane also contains the File Template, the Code Snippet and the Media library at icon index 1, 2 and 4, respectively.)
In VS2012, this is found in the upper left corner (only) available upon selecting a XAML file in the main editor view:
If you select a C# or, with WP8, C++ file, the “Toolbox” tab won't contain anything, they not being UI descriptors. This is shown in the next screenshot:
This is exactly just like .m (and, of course, .h) files not being able to describe a GUI in iOS programming, unlike XIB files containing the serialized version of them. Under the “Toolbox” tab, there are two UI widget-related tabs, Common and All Windows Phone Controls. You, as with Xcode, can quickly search in the widget library, even with both tabs closed, by entering the search expression in the textfield above them:
Dropping widgets on your UI is done in exactly done the same way in the two systems. Unlike with some less-capable UI editors like those of Samsung's Bada SDK (at least back in 2010; dunno if the latest versions have fixed this – I've always created my widgets in my Bada apps striclty from code and not from the visual editor), you can drag-and-drop widgets – no need to click them in the object library first and, then, strictly without dragging, clicking in the target position of the UI you're designing.
5. Profiling, memory leaks etc.
Unlike in Automatic Reference Counting (ARC)-less iOS, Symbian or Bada, in a C# program, you don't need to bother with keeping track of references, whether they'll be used in the future etc. This means there's no point in tracking memory leaks (that's what the excellent “Leaks” tool of Xcode does) – there won't be any.
Performance profiling (in Xcode, via Product > Profile > Time Profiler), on the other hand, can be very handy (just like on the ARC-enabled iOS too). Two example screenshots of the non-ARC-based app (see next section) instantiating NSDate in a loop; first, the loop running 100,000 times and, then, a 10,000,000 times. In the first case, the loop was in charge of 7.9% of the total execution time (see the “Running time” column); in the second case, 34.5%.
For WP, the situation isn't this good: it's not possible to exactly measure how much time, say, a constructor like that of “string” spends creating new string instances in, say, a for loop in WP7. In WP8, the situation is far better with its brand new (also listed HERE, in the “What's new” list, in the “Testing tools and features” section) Monitoring mode.
If you do have WP8, you'll want to start with THIS, Monitoring-specific guide. If you only have a WP7 device, you'll want to read THIS one instead (an additional stackoverflow thread is HERE) for more info. As these both links article are WP7-only, they completely lack the WP8-specific, new Monitoring mode.
(the Monitoring mode is displayed at the top upon starting Windows Phone Application Analysis)
5.1 A quick, iOS-only remark on ARC
A quick remark on ARC (also as an additional tip to the ones described HERE). With ARC enabled, you can't cause memory leaks if you forget to use the synthesized setter method for strong properties (like a @property (retain, nonatomic) NSDate* myDate;) but use direct assignment instead. An example of this: for (int i=0; i<100000; i++) myDate = [NSDate date];. Using this code, neither leaking nor automatic freeing of the last-saved instances will take place (meaning the reference will be valid upon accessing it later): only the previous values will be released, just like in the automatically generated setter method not only retaining the new, passed reference, but also (after checking it isn't equal to the new, to-be-retained one) releasing the one the property has and was set in the previous setter call. That is, the above call has completely the same effect as [self setMyDate:[NSDate date]]; or its shorthand, self.myDate = [NSDate date];.
Before ARC, the above assignment has resulted in a runtime exception when, later, you tried to access the then-already-automatically-freed variable from, say, a UI callback. (Like a button event handler setting a label to the stored date via label.text = [NSString stringWithFormat:@"%@", myDate];) BTW, this is why I've always forced my students to rename (=hide) their properties upon synthesizing them (like in @synthesize myDate=hiddenMyDateProp;) to be forced to use the auto-generated, release-the-previous-value-and-retain-the-new-one setter to 1, avoid having to manually retain the reference and, before assigning it to the property, releasing the previously retained one, making sure it isn't the same as the newly-retained one, all resulting in a lot of additional code; 2, avoiding sometimes very-hard-to-track-down runtime errors by forgetting to explicitly retaining it. If you do write non-ARC apps (I don't see why you should do as even 4.x-based iDevices support ARC – see THIS for more info.), make sure you do rename your properties upon synthesizing so that you don't make this very-very common mistake.
Finally, you can test all these on THIS and THIS, non-ARC-based and ARC-based projects, respectively. In both of them, I've put a button to display the value of the “myDate” property in the label. (It's during this that the non-ARC app will crash if you don't explicitly call retain (if you just use a simple reference assignment and not set the reference via the synthesized setter).) I instantiate NSDate and pass the reference of the new instance to the property in viewDidLoad. Play with the above-mentioned myDate = [NSDate date] (and its retain-enabled version) and self.myDate = [NSDate date] (the latter, again, being just a shorthand for [self setMyDate:[NSDate date]]) using both Instruments' Leaks and by testing whether the reference is alive when you do click the button.