I’ve tried out iOS development using a few different approaches over the years. Having previous experience with Ruby and finding the prospect of learning Objective-C not particularly attractive, I tried RubyMotion back in 2013. RubyMotion was a pretty cool take on things, Laurent Sansonetti did a great job of making RubyMotion feel familiar to a Ruby developer. But the problem for me was not so much anything specifically to do with RubyMotion so much as the fact that I had no previous experience with native iOS development. These cross-platform/cross-language tools are a lot easier to use if you have a fair amount of experience with the original platform/language that they are trying to be a bridge to. But if you do have such experience, then it begs the question why would you need a cross-platform/cross-language tool? It’s a bit of a chicken and egg situation. How much familiarity with the original platform/language is enough?
Taking a step back, it seems self evident that one should have a reasonable familiarity with the underlying platform/language before trying to make use of one of these cross-platform/cross-language tools, but I don’t think I’m the only one who would feel that this point can get glossed over with the hype. You’re familiar with platform/language X? Well, now you don’t even really, truly, that much (OK maybe a little bit), need to be familiar with platform/language Y and Z! Just use this thing (points emphatically at new cross-platform tool set that’s just been released)! Learning this kind of cross-platform wrapper for a given native API that one is not particularly familiar with in the first place is certainly doable, I’ve done it in the past. But it’s not the easiest learning curve to embark on.
In 2014 Apple released Swift and I thought hey, maybe I can now use the native Apple tool chain for iOS development but I don’t have to use Objective-C!
Then a friend came to me with an iOS app - the development of which he’d outsourced - and he wondered if I’d like to take over maintenance of the app. So I said yes and not surprisingly, it turns out that the app was entirely written in Objective-C. I had tried to avoid it, but it turns out you can’t outrun that many square brackets forever.
So I’ve gathered some experience with iOS development using RubyMotion as well as Apple’s own tool chain with both Objective-C and Swift, in the process I’ve found out that Xcode is a fairly lack lustre IDE. And now, lured once more by the siren song of cross-platform development, collaborating with a friend who primarily uses Microsoft dev tools, a desire not to use Xcode except when absolutely necessary, and the fact that a lot of the other work I do these days involves Microsoft platforms and C#, I have been trying out Xamarin.
Xamarin 2.0 was released in 2013, with their own IDE for Mac named Xamarin Studio as well as integration with Microsoft’s own Visual Studio. I remember reading about Xamarin at the time but I was giving RubyMotion a go back then. Generally speaking though, if I’m going to use an IDE over a lighter weight text editor, that IDE will be Visual Studio. Visual Studio is not perfect, but it’s pretty good (for me, better than Xcode) so I thought it was great that Xamarin could integrate with it. I planned to keep an eye on Xamarin’s evolution.
Fast forward to today and Xamarin has been acquired by Microsoft, they’ve renamed Xamarin Studio to Visual Studio for Mac (which I find needlessly confusing, but whatever) and I was ready to give this Xamarin thing a go using my favourite IDE (i.e. the real Visual Studio… on Windows). So I fired up my Windows 10 VM on my Mac and went through the quite pain-free process of setting up Xamarin on both my Mac host (path of least resistance: install Visual Studio for Mac) and Windows VM (path of least resistance: install Visual Studio or modify your existing Visual Studio install and include the Xamarin bits) then connecting the two (path of least resistance: follow this guide1) so that the Mac host could be utilised by the Windows guest OS for various development tasks.
So far so good and super easy! Maybe this was the cross-platform tooling I’d been looking for? Well, then I tried actually doing something with Xamarin using Visual Studio on my Windows VM.
First problem is that much of the online Xamarin material that I kept bringing up in my googling for the things I wanted to know was pages that assumed use of Xamarin Studio (sorry, Visual Studio for Mac…). This was not super helpful for a person using Visual Studio on Windows. But I probably could have made do, except for the fact that important parts of Xamarin in Visual Studio on Windows are so buggy that they are effectively unusable.
There is a “Resources” folder created by default in a Xamarin.iOS project. If one is using an asset catalog to say, manage your app icons and one manually adds the
Images.xcassets folder to the project (i.e. so that the
Images.xcassets folder and contents is visible in the Solution Explorer, under the “Resources” folder), this appears to trigger some strange behaviour where the
.csproj file gets automatically updated making it so that the asset catalog no longer can be opened when you double click to view its contents in Visual Studio. I tried in vain to manually edit the XML inside the
.csproj file, but things just seem to get changed back the next time the project gets opened. Why would anyone want to manually add the
Images.xcassets folder to the project? Because
Images.xcassets wasn’t added to source control previously and this is one way to add it. It’s not the only way to add files to source control, but it is probably the most intuitive and common way.
The equivalent of Xcode’s Interface Builder in Xamarin is the “Xamarin iOS Designer”. With a few exceptions, much of the documentation for Xamarin.iOS expects that you would be using the Xamarin iOS Designer, which is not surprising considering most iOS developers tend to use Interface Builder wih Xcode. What the documentation doesn’t tell you however, is that in Visual Studio on Windows, the Xamarin iOS Designer is almost comically broken.
If you have more than one view connected together on the Xamarin iOS Designer’s “design surface” via a “segue”, then arrows between the views will be visible, representing connections between the views (similar to Interface Builder). But unlike Interface Builder, if you zoom in or out, the arrows jump to completely the wrong place on the design surface. Dragging one of the views around on the design surface seems to make the arrows jump back to their expected position (until you change the zoom level again).
Which brings me to another WTF moment: I only seemed to be able to drag the view related to my root controller around on the design surface, the other views appeared to be fixed in place. I then right-clicked and deleted one of the views from the design surface and noticed it didn’t immediately disappear. Well that’s annoying I thought, but maybe I just need to close and open the iOS Designer again? Upon opening the iOS Designer once more, I got a null reference exception that I’m guessing was caused by me right clicking on a view and choosing to delete it when it was still connected to another view and that other view still having some reference to the now deleted view? From this point on, the iOS Designer was completely inaccessible and would only show the null reference exception when I opened it. I considered opening the
.storyboard file directly and trying to figure out what bits in the XML I needed to change in order to fix things, but then I remembered I’m not that masochistic. This is what a developer really wants to be doing with their time, right? Not actually working on building anything, instead just spinning their wheels, wrestling with their tools, manually editing supporting XML that they should actually never even need to see.
Just doing simple and ostensibly innocuous things like adding a folder to the project or right-click deleting a view from the Xamarin iOS Designer caused me significant problems. The preceding couple of paragraphs are a condensed account of the better part of a couple of days worth of trial and error on my part, the primary learning coming out of this time being that I needed to end my abusive relationship with the Xamarin iOS Designer. I am running new and high spec hardware (late 2016 MacBook Pro), as well as what are currently the latest versions of Visual Studio (15.4.1) Xamarin.iOS/Xamarin.Mac SDKs for Visual Studio (18.104.22.168) and Xcode (9.0.1), so hardware grunt shouldn’t be a problem and there are currently no newer versions of things to upgrade to which might provide some relief.
For work reasons I happen to have an MSDN Subscription (or is it called a Visual Studio Subscription now?), which means that I can send Microsoft a support enquiry about this kind of thing and a Microsoft minion is obliged to reply to me. So before I completely gave up on the weird asset catalog issue and the iOS Designer I thought it worth contacting Microsoft to find out if what I was experiencing were known issues or just some problem with my particular situation.
As of the time of this writing, Microsoft have informed me that there may be a bug in relation to the asset catalog thing. My own workaround is to not add the
Images.xcassets folder to the Solution Explorer but rather add it to source control via the Source Control Explorer instead. This seems to accomplish the goal of having the
Images.xcassets folder in source control while still allowing the contents of this folder to be managed using the asset catalog over on the Solution Explorer in Visual Studio on Windows.
Microsoft confirmed that there are various known issues with iOS Designer and Visual Studio on Windows, recommending that if one wants to use the iOS Designer they should open the project in Visual Studio for Mac and use the iOS Designer there. Unfortunately, my previously mentioned friend who I am collaborating with on this piece of work does not use a Windows VM running on a Mac like I do, his development machine is a Surface Pro and he’s connecting to a loaned Mac across a network when it’s needed by Xamarin.iOS. In any case, why should my friend need to use Visual Studio for Mac in order to get the full, as advertised functionality of Xamarin? Reading the Xamarin documentation, one certainly gets the impression that the available functionality is equivalent regardless of whether one is using Visual Studio for Mac or Visual Studio on Windows. At the current time, this is just not the case. If Xamarin/Microsoft were clearer about the state of Xamarin as it relates to Visual Studio on Windows, then people could set their expectations appropriately, plan accordingly, and waste less time wrestling with things that just don’t currently work.
So anyway, the fall back workaround here for me is to move forward with managing UI views entirely in code with no storyboard files and no Xamarin iOS Designer. I know some people prefer the code-based approach to views (when I was using RubyMotion, this was the approach), but I wouldn’t have minded being able to take advantage of the iOS Designer if only so that visualising the view hierarchy could be a bit more intuitive and so that one could more easily take advantage of a large chunk of online Xamarin documentation, 3rd party blog posts and so on. Also, sorting out view constraints in code can be pretty time consuming in my experience so far.
I will be sticking it out with Xamarin for the foreseeable future and I do see promise in it. But as of the time of this writing, don’t expect a hassle free and polished product if you are using Xamarin with Visual Studio on Windows.
In the “Connecting to the Mac” section, step 3, I did not like the idea of allowing remote login for “All users”. I went with the other option of allowing remote login for one specific user. ↩