|Jan 6, 2013, 07:48 PM||#1|
Windows Phone programming for iOS programmers (and iOS coding tips) Part I
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 present 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 (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.
Last edited by Menneisyys2; Jan 8, 2013 at 03:24 AM.
|Jan 6, 2013, 11:33 PM||#2|
If I may back you up a bit
I would presume that, if you are interested in making a multi-platform app, your best bet would be to write as much as possible in straight C, since otherwise you're not going to be able to bring that code into another platform. In other words, if you have a "standard" iOS app written mostly or entirely in Objective-C, you're not going to be able to reuse much of that in a WP8 (or Android) project. Is that correct?
On the other hand, I would presume that, since all this hardware is using ARM-ish hardware, that being able to use Obj-C code on the other platforms is not outside the realm of possibility, since the compiler is already there and open-sourced. But I'm not sure if reality has caught up with that possibility yet.
|Jan 7, 2013, 06:45 PM||#3|
I've played a bit with Windows Phone 7 code, and I loved it. C# is pretty close to Java so it's easy to develop like Android. But all the phones were the same screen resolution (475x800 iirc) so it was easy to test like IOS devices. The best of both worlds.
Also Adam Nathan's books are incredible, well written with tons of code to steal. Wish windows phone would reach critical mass and give the big two some competition.
|Jan 8, 2013, 03:24 AM||#5|
http://forums.macrumors.com/showpost...30&postcount=4 (will also fix the original article).
|Jan 9, 2013, 07:03 PM||#6|
WP7/8 programming for iOS developers my quick multi-device fix for VS2012
I've been porting my iOS-based Ubipix location & direction logger app for both Windows Phone 7(.5) and Windows Phone 8. During this, I've discovered a quick and, up to now, undocumented way of speeding up multiplatform development and to avoid having to remove / reinsert cables all the time when selecting which device to deploy the given app to.
This is just a quick note and not a full article because I think a lot of other are in the same boat as me, wanting to quickly develop for both major WP operating systems and all suffering from the same problem. This is why I've decided to post my hack – I can save a lot of time spent by removing / reinserting cables before. I also want to quickly warn (prospective) purchasers of the HTC 8S of it not having a digital compass, no matter what a lot of reviews and spec sheets state.
(Note that the full, Ubipix-related article will only be later published, along with the explanation of how WP8 enhanced video recording, thoroughly comparing it to how the same is done in iOS. I'll also present you with a full iOS video recorder, with all the sources, fixing all the problems I've listed with the official Ubipix recorder app.)
When developing for iOS (in Xcode), quick, software-only switching is certainly possible. An example showing both my iPhone 5 and an iPad 3 connected to the same Mac and ready to quickly switch between the two:
(click for a larger screenshot!)
The same (quickly switch between two phones to deploy the app to) isn't possible under VS2012 (at least the Express edition – I don't think the paid versions are better in this respect). I've made this screenshot with both a WP7 and a WP8 phone connected to the same PC:
As you can see, only one device is shown (basically, the one that was connected second) – unlike under Xcode. Unfortunately, (previously) working solutions like the one HERE don't work either – they 1, are only for the previous version (VS2010) and 2, are only for making it possible to run two instances of the emulator in parallel, not from quickly switching between hardware devices.
If you want to develop for WP7, always testing the same code on WP8, your will REALLY want to test your code on as many devices as possible to avoid bad surprises – sudden, unexplainable exceptions etc. For example, it was only after receiving it that I realized that the brand new WP8 phone, the HTC 8S, doesn't have a digital compass – before that, based on the reviews, I had thought it would. (The SlashGear, Geekaphone, TechCrunch articles / spec sheets all state it has a compass. It's only the official spec pages that lack the word “compass”) Whenever instantiating Microsoft.Devices.Sensors.Compass (or even accessing its “IsSupported” class variable), I got an exception with exactly the same code that ran just flawlessly on my LG E-900 (WP7.5, has compass). It was after this that I realized I shouldn't have trusted (p)reviews of the phone because it doesn't have a hardware compass, cotrary to what they state.
What about my hack?
Fortunately, it's really easy to very quickly switch between a WP 7.x and a 8 phone as the current target. Just fire up Task Manager, go to the “Services” tab and find the service “IPOverUsbSvc”. Right-click it and select “Stop” (highlighted below):
(click for a larger screenshot!)
After this, all deployments will happen on the 7.x WP, not on the WP8 one.
To quickly switch back to deploying to the WP8 phone, just right-click the same IPOverUsbSvc and select “Start”.
You can always keep Task Manager open, meaning switching between the two platforms is just two clicks away. No more time-consuming cable removals / reinserts!
This all will only work when switching between WP7.x and WP8 devices, not between two WP7.x or two WP8 ones. The hack is based on the fact that the two platforms use entirely different and fully independent ways of communication even when developing: WP7.x uses Zune, while WP8 uses the IPOverUsbSvc service of the automatically-downloaded “Windows Phone” app. If you disable any of these, the phone using the other (remaining) will be targeted by the next deployment. As killing / restarting Zune is far more time-consuming than doing the same to IPOverUsbSvc to quickly switch the target phone, I recommend the latter.
I really hope you'll find my quick hack useful and time-saving.
Last edited by balamw; Jan 10, 2013 at 07:48 AM. Reason: promotional link removed
|Thread Tools||Search this Thread|
All times are GMT -5. The time now is 02:40 PM.