📜 ⬆️ ⬇️

Xamarin and Xamarin.Forms - cactus in chocolate. Part 1

We are in Contour. Elbe love mobile applications. We already had experience writing an application for iOS, as well as developing and further supporting an application for Android . This year we have released a new version for iOS , but this time based on Xamarin and Xamarin.Forms , and we are eager to share our experience. So far, we have managed to consider development only for iOS, but the impressions are already a sea, and a couple of words about Android are definitely going to say.

What is Xamarin


The framework for cross-platform development of mobile applications based on .NET (more precisely, on the implementation of Mono ), supports all major operating systems - Android, iOS and Windows Phone. More on Habré was written repeatedly , there is no need to repeat.

What is Xamarin.Forms


A framework that allows you to develop a single interface layout immediately under several of the above platforms. The idea is this: you make the layout once on the basis of the Xamarin components, and on the target platform, for each component, the code renderer is called, which draws already the native components. The layout itself can be prepared both in code and in XAML format. The UI utilities for layout and previews of the resulting interface, as a year ago , are still not there, so we chose the option to create a UI from code.

Why did we choose Xamarin + Xamarin.Forms?


There were several reasons.
')
  1. We use .NET and C # on the server, so it’s quite convenient to use one language and a platform for three applications (server, iOS, Android) - there is no need to switch from one language to another, the ability to use familiar patterns, it is easy to select common fragments into libraries, and .P.
  2. Of the available frameworks, Xamarin looked the most advanced.
  3. We did not consider the option of creating an HTML5 application: many forms were planned in the application, and the native components in this plan work noticeably more predictably and faster. Especially true for low-cost Android-smartphones.
  4. Xamarin.Forms was pleased with the potential opportunity to make a common interface for Android and iOS with minimal tillers, and also brought a number of advantages, for example, the block layout model on iOS, which is usual for us.

First blood


The beginning of communication from the paid version began with the activation system jamb: in the personal account on the Xamarin website it was already clear that payment ( $ 999 or $ 799 for MSDN subscribers ) was made, but Xamarin.Studio stubbornly refused to build the application, because “Paid version is not activated”. Only manual activation of payment by Xamarin technical support helped. They responded quickly, but in any case this is a great start, which set the tone for the subsequent project.

By the way, the free trial version does not allow building an application larger than 64 kilobytes for the compiled code. That is, we connect, say, the same json serializer (Newtonsoft) - and the application can no longer be assembled. Nicely.

IDE issues


Xamarin provides its own IDE Xamarin.Studio, based on MonoDevelop . Unfortunately, this IDE has several problems:

  1. Instability. For example, the chance of a deadlock is very high when trying to interrupt the application build.
  2. The backlight or autocomplete breaks down periodically.
  3. Autocompletion does not know how to look for classes that are not included in the current namespace, although it can prescribe the required using the fully written reference to the class.
  4. There are clearly not enough opportunities for refactoring, it is far from Resharper in this respect.
  5. Integration with the XIB editor (layout files for iOS) breaks down periodically. If you use the layout through XIB or Storyboard, then Xcode opens for editing, and upon closing it, auto-generated classes related to UI are updated. But not always. Sometimes the environment basically stops calling Xcode for some or all of the files. It is treated by clearing the studio cache (by deleting the contents of the ~ / Library / Caches / XamarinStudio-5.0 directory).

But there is good news too! At the business rate there is an integration with Visual Studio, which allows you to write code there. It works very well, with some of the problems, for example , we did not encounter such problems, apparently because we have not worked with Android and XAML yet. But then faced with others.

The fact is, to build an iOS application, you need a computer or a virtual machine with Mac OS X. And here you have two options:


Moreover, the plugin for integration worked for a long time unstable. We occasionally had this situation: three developers, all of them have the same version of the OS, studio, Xamarin, and so on. They are connected in turn to the same Maca. As a result, everything works fine for one, break points are ignored for the second one, and not for the third one.

Technical support advised to try the latest 4 versions for Mac and Windows, “maybe some combination will work”. Installation takes 20-30 minutes, because the installer downloads even those components (for example, the Android SDK library) that you already downloaded last time. Think about it ...

But even if the plugin works fine, the next time you open the project in Visual Studio, you will have the network turned off or, for example, the Mac is turned off - the plugin will with some probability be hung on searching for the buildhost. And the “cancellation” does not always work, once I had to go to the registry and delete the saved build-host parameters there.

Therefore, we have worked for a long time like this:

  1. The code lies in the network folder available on the Mac and in the Parallels virtual machine running on Windows running on it;
  2. The main part of the code is written in Visual Studio under Windows inside this virtual machine;
  3. Debugging or building the final version takes place in Xamarin.Studio on Mac OS X, but not through the plugin, but by manually opening the same code in the shared folder.

Well, and from minor troubles: every time you open a project with iOS, the plugin will offer to connect to the build.host, blocking further project download until the answer to the question.

This infection even standard Enter / Escape does not understand!


Fortunately, after many months of torment, the Xamarin team took pity on us. The last Xamarin.Studio update solved this problem - now in the connection window to the remote Mac there appeared a tick “not to show the connection window”.

Oh, and the remote build now does not through its own Xamarin utility, but through ordinary remote users on Mac OS X:



As a result, the connection became quite stable and debugging normally starts in 8 cases out of 10. But in any case, the simulator runs on another PC, i.e. Debug is on your machine, and the application is running somewhere there, the picture is not displayed on your PC. You can open a remote session or keep a second computer on the same table.

The solution still remains somewhat crutch, but it allows you to completely abandon the use of Xamarin Studio! Believe me, after several months of life we ​​can say for sure: it is worth it.

There are problems with profiling. Xamarin.Profiler (GUI wrapper over Mono log profiler ) for iOS applications did not show the names of the classes you wrote for a long time, there was only information that such native objects take up CPU time and memory, but how do you compare them with the classes you wrote - not a drop not obvious. Now things are better with this - the written classes have finally appeared on the list.

Also, under the profiler, the application is much slower, and, as a result, it can sometimes just not be in time for the launch time to show the first screen, and iOS will nail it. And if the application does launch, it can fly out in the process of working on the simulator under the profiler. As a weak excuse, it can be noted that the profiler has long been at the alpha version stage, and over the last year has not been able to reach even the “stable beta” stage - at least for iOS.



Problems with cross-platform code


We are offered to write a cross-platform code in one of two ways:

  1. Shared Project . The code in this project is not compiled into a separate assembly, but simply includes itself as part of several projects at once. A sort of symlink project.
  2. PCL Library . (Portable Class Library) Cross-Platform Library.

In theory, you are invited to choose one thing. In practice, we used both of these methods.

In the PCL project, we wrote all the business logic, work with the database, network, etc. The main advantage is that PCL will not allow the use of any system class that is not implemented on one of the platforms. So the code written and compiled within PCL is guaranteed to run on all selected platforms.

The downside is that the PCL library is written based on the intersection of the capabilities of all selected operating systems, not allowing to use what is missing in one of them. Ie, if we plan to use only iOS and Android, and there is no necessary feature in Windows Phone, we will not be able to use it. At the same time, there is a set of “profiles” for PCL, defining supported platforms, but at the time of this writing, it’s impossible to select the option “iOS and Android only, without Windows Phone and Windows”.

As a result, we put in the shared-assembly code, guaranteed to work on iOS and Android, but not able to assemble under PCL. For example, support for gzip-responses and other specifics of working with a network or database got there.

In PCL there may be no trivial things, like working with files, etc. - in this case, it is assumed that there will be interfaces in the PCL assembly, and the implementations will already be in the project for a specific OS. In our case, some of these implementations just fell into the shared-assembly.

By the way, if you choose a profile for PCL - we advise you to choose profile 259 . Best suited for the available opportunities. We started on another, not having in its composition, for example, mutexes or thread-safe dictionaries - you can write with your hands, but why? I also note that the choice of a profile is much more convenient and clearer done in Xamarin.Studio, and not in Visual Studio:



Well, for a snack - another PCL feature: you cannot add another PCL library with a different profile depending on one PCL library. More precisely, you can add it, but not any profile will get along with anyone. In general, the idea of ​​PCL is generally usable, but in particular it can be white-hot.

Binding issues to native platform capabilities


The basic idea behind Xamarin is that you can write code using the same classes, methods, and structures that you would use when writing native code, it’s just now written in C #. But there are nuances ...

In the case of iOS, there is a rather interesting bugfich with delegates. Here, for example, component UIScrollView . You can assign it a delegate to handle certain events, or you can subscribe to these events directly.

var scrollView = new UIScrollView(); // 1 class UIScrollViewDelegate1: UIScrollViewDelegate { public override void ScrollAnimationEnded(UIScrollView scrollView) { base.ScrollAnimationEnded(scrollView); Debug.WriteLine("Yes, animation ended"); } } scrollView.Delegate = new UIScrollViewDelegate1(); // 2 scrollView.ScrolledToTop += (_, __) => { Debug.WriteLine("Yes, scrolled to top"); }; scrollView.ScrollAnimationEnded += (_, __) => { Debug.WriteLine("Yes, animation ended"); }; 

Moreover, when subscribing to a ScrollAnimationEnded event, the delegate is automatically replaced with an internal Xamarin. And the subscription to the ScrolledToTop event will be lost. It would seem - what's the problem? Just don't mix event subscriptions and delegates in the same code! But sometimes there are problem situations:

  1. The component does not have the required event, although it is present in the delegate.
  2. In a component, Xamarin itself may already have its own delegate with some handlers.

Or, for example, in Xamarin.iOS, the single class UITableViewSource class is used, replacing the two iOS protocols UITableViewDataSource and UITableViewDelegate . This can be confusing.

Also, the signatures of methods and classes sometimes change, the same iOS constructor fileURLWithPath turned into Xamarin into CreateFileUrl .

A similar situation occurs in Android - for example, the original GONE constant is in the View class, and in the Xamarin version for the same purpose, we have the enum ViewStates with the Gone value. A similar problem exists with some other methods and constants, which causes some confusion when switching from a native platform.

Lack of abstractions over platform features


For complete happiness, the framework does not hide from you some of the features of a particular OS. For example - background work with the network:

  1. In Android, you can simply generate a new stream for working with a network or a background network service, if your application is minimized or the phone is locked, the work will not be interrupted.
  2. In iOS, when the application is minimized, it stops, and if you want to do something with the network, you need to use another option, for example, the Background-Safe Task, which stops a few minutes after the minimization.

You will say - it's just the features of a particular platform? Exactly. But no one from the developer hides these features under abstractions, so we repeat, we will have to study each of the platforms .

Lack of third-party components


At the moment, many components have already been written under Xamarin, but under iOS and Android, more are written. If necessary, it is theoretically possible to connect a binary library written in Object-C or Java , but you have to write a binding project for the connection between the native library and the Xamarin application. For iOS, the Objective Sharpie utility, which can independently generate such a project, will help, but it does not always work 100% exactly, sometimes you have to edit the result of such a generation with your hands, and sometimes even think about whether you need this library at all.

In addition, the authors often update such components with a delay, compared with the native version of the library. We were confronted with the situation when the TestFairy plugin was a couple of months behind the native version. The TestFairy tech support question was answered to us that everything is fine, you are not losing anything, except for a couple of small features. But with the release of the new version of Xamarin, a problem arose: applications with this library collected in this version of Xamarin began to fall in real-time.

findings


After studying the subtleties of the framework, the conclusions suggest themselves.


The article also planned a story about Xamarin.Forms , but that section was so stretched that we decided to allocate it in a separate article. In it, we’ll tell you about the various problems of the XAmarin.Forms UI framework and how we solved them. In the meantime - like and subscribe to the blog! Although no, what for stamp ...

Update. Link to the second part.

Source: https://habr.com/ru/post/273075/


All Articles