{"id":14121,"date":"2015-06-04T13:20:34","date_gmt":"2015-06-04T11:20:34","guid":{"rendered":"https:\/\/blog.trifork.com\/?p=14121"},"modified":"2015-06-04T13:20:34","modified_gmt":"2015-06-04T11:20:34","slug":"ios-perspective-on-mobile-development-with-xamarin","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/","title":{"rendered":"iOS perspective on\u00a0mobile development with Xamarin"},"content":{"rendered":"<p style=\"text-align: justify\">One of the fundamental mantras of software development is DRY &#8211; \u201cDon\u2019t repeat yourself\u201d. It\u2019s an important rule, because it allows us to save both space and time. Instead of rewriting a non-trivial algorithm, we use a method call, instead of correcting bugs in multiple places, we do it only in one. Would you ever not follow DRY? Well\u2026 yes, when you need to develop a mobile app. If your plan is to get as many customers as possible, releasing an iOS and Android version is a must. This means maintaining two very similar codebases. Can we do better? The answer is yes and it\u2019s called Xamarin. It\u2019s the platform we\u2019re using for some of our newest projects here at Trifork, and we would like to share with you our experiences, likes and dislikes. Read on if you\u2019re not afraid to abandon Xcode and Objective C.<\/p>\n<p><!--more--><\/p>\n<h2>What is Xamarin and why would you use it?<\/h2>\n<p style=\"text-align: justify\">Xamarin is a San Francisco based software company leading the open source project called Mono. One of the goals of Mono is to provide cross-platform runtime for Microsoft .NET applications.<\/p>\n<p style=\"text-align: justify\">The Mono framework served as a basis for the mobile development tools offered by Xamarin: Xamarin.iOS and Xamarin.Android. As a developer opting in for the former, what you get is, amongst others, the following:<\/p>\n<ul style=\"text-align: justify\">\n<li>C# compiler<\/li>\n<li>Core .NET libraries<\/li>\n<li>Libraries that bind the native CocoaTouch APIs<\/li>\n<li>Xamarin Studio IDE<\/li>\n<\/ul>\n<p style=\"text-align: justify\">As the first item on the above list indicates, using Xamarin means saying goodbye to the good old Objective C. That is, in my opinion, a good thing. C# is a very modern language offering a lot of features that are also available in Swift. As for all the great frameworks we get to use, while developing iOS apps &#8211; they are all there! It\u2019s true that some naming conventions are a bit different but most of the time you\u2019ll feel very much at home.<\/p>\n<p style=\"text-align: justify\">Developing in C# is definitely a plus but the greatest benefit Xamarin has to offer is sharing code between multiple platforms. Unfortunately this does not mean, that we have found the Holy Grail of mobile development, which allows us to write code once and run anywhere. The promise that we get is, nonetheless, very attractive. Xamarin lets us to share the majority of our non-UI codebase. If you want more you can take a look at <a href=\"http:\/\/xamarin.com\/forms\">Xamarin.Forms<\/a>, which aims at providing common API for writing UI code! We decided not to use it in our projects due to quite complex and custom UI, as well as the fact that the API does not offer all the native features <sup><a id=\"fnref:1\" class=\"footnote\" title=\"see footnote\" href=\"1\">1<\/a><\/sup>.<\/p>\n<h2>Getting started<\/h2>\n<p style=\"text-align: justify\">It\u2019s important to mention that Xamarin is <a href=\"https:\/\/store.xamarin.com\">not free<\/a>. Depending on your needs, a single annual license will set you back between $300 and $1900. The price includes only one platform, so if you want to target both iOS and Android, you have to multiply it by two. This may seem like a lot, especially when you realise that you need the usual Apple and Google developer licenses on top of that. But if your project is big enough and contains a substantial amount of business logic, then you can probably get your money back by reducing the development time.<\/p>\n<h2>The IDE<\/h2>\n<p style=\"text-align: justify\">Xamarin supports two development environments: <em>Xamarin Studio<\/em> and <em>Visual Studio<\/em> (only Business and Enterprise license). While you cannot choose which one you want to use if you have a Mac, it is possible to run both on a Windows machine. We decided to use Xamarin Studio across the board, mainly to minimise any sorts of incompatibilities.<\/p>\n<p style=\"text-align: justify\">An added bonus for developers coming from the iOS\/Mac world is that Xamarin Studio looks a lot like Xcode.<\/p>\n<figure><a href=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio.png\"><img loading=\"lazy\" decoding=\"async\" class=\"  aligncenter wp-image-14133 size-large\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png\" alt=\"xamarin_studio\" width=\"1024\" height=\"619\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-300x181.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-768x464.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1536x928.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-2048x1238.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1920x1160.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Xamarin Studio<\/figcaption><\/figure>\n<p style=\"text-align: justify\">We have the familiar <em>Run<\/em> button in the upper left corner, the device selection dropdown as well as the notification bar in the middle. One difference between Xamarin Studio and Xcode, that I was really happy to see, is the <em>Solution Navigator<\/em>. In contrast to Xcode, it actually reflects the structure of directories on disk, not only the contents of an XML file. I\u2019ve spent way too much time trying to keep both of them in sync.<\/p>\n<p style=\"text-align: justify\">My overall experience, after using Xamarin Studio over the past few months, is positive. It is pretty well organised and fast at launching my apps on a device. That said, I encountered code highlighting issues and my device froze from time to time while connected to the debugger (usually after the screen has been locked for a short while).<\/p>\n<p style=\"text-align: justify\">As far as designing UI is concerned, Xamarin offers a tool called <a href=\"http:\/\/developer.xamarin.com\/guides\/ios\/user_interface\/designer\/\"><em>Xamarin Designer<\/em><\/a>, which allows you to edit storyboards in very much the same way as Interface Builder. I have not used it a lot, to be honest, because it is also possible to stick to our good, old friend IB. It\u2019s really cool that Xamarin automatically picks up the changes you make to a Xib file and new outlets are immediately available in your classes. The only annoyance I encountered was problems in communication between the two IDEs, which result in pesky pop-ups you have to dismiss from time to time.<\/p>\n<h2>The language<\/h2>\n<p style=\"text-align: justify\">I must admit that I like C# more and more. It\u2019s a powerful language that boasts a number of very useful constructs. Generics, lambda expressions, optionals and properties, just to name a few. Plus it\u2019s actually quite easy to get the hang of it, especially if you have some experience with Java.<\/p>\n<p style=\"text-align: justify\">One thing that may be unusual for people moving to C# from Objective C, is the use of <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms173160(v=vs.80).aspx\">exceptions<\/a>. In iOS apps this practice is almost non-existent, while in .NET it\u2019s a very important and integral part of the language. This means no more error codes and error objects. Instead it\u2019s time to get familiar with the <em>try<\/em>, <em>catch<\/em> and <em>finally<\/em> keywords.<\/p>\n<p style=\"text-align: justify\">Memory management in C# is very different than in Objective C, because of the presence of a garbage collector. Despite that, one thing to be aware of, is that it is still possible to create a retain cycle, for example when using lambda expressions. The reason for that is that the classes that derive from <code>NSObject<\/code> still work with reference counting under the hood.<\/p>\n<p style=\"text-align: justify\">Speaking of memory management, it is very important to understand and use the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/b1yfkh5e(v=vs.110).aspx\">Dispose pattern<\/a>. It allows you to release memory in a more deterministic way, instead of waiting for another garbage collector pass. <code>UIImage<\/code> serves as a good example. The object representing an instance of <code>UIImage<\/code> uses only 20 bytes of memory, but it contains a pointer to the raw image data, which can be megabytes in size. The garbage collector sees only the negligible 20 bytes, so it can take a long time before another GC pass will be triggered. By that time we may have run out of memory and ended up evicted by the system.<\/p>\n<h2>The frameworks<\/h2>\n<p style=\"text-align: justify\">The amazing thing about Xamarin is, that even though you\u2019re using a totally different environment and language, you still have all your familiar APIs available at your fingertips. This makes your transition from Xcode and Objective C smooth and fast. You have to be aware of certain naming differences and the C# conventions, though.<\/p>\n<p style=\"text-align: justify\">Let\u2019s take for example <em>Core Image<\/em>. The iOS framework defines string keys that allow you to set properties on filters that you want to apply to an image. They are all grouped into a long list in <code>CIFilter.h<\/code>. Xamarin goes a little bit further by defining a static class <code>CIFilterInputKey<\/code>, which contains static properties representing different keys. In my opinion, this makes it easier to find the one you\u2019re looking for.<\/p>\n<p style=\"text-align: justify\">If you decide to use <code>UITableView<\/code> in your project, you may be surprised that <code>UITableViewDelegate<\/code> and <code>UITableViewSource<\/code> are classes, not interfaces. This is because interfaces in C# are mandatory, whereas Objective C offers the <code>@optional<\/code> keyword. It is therefore much easier to create an abstract base class, so that subclasses can override the optional methods they need. This, in turn, results in the fact that it is not possible to make your controller the delegate or the data source. To do that ,you have to implement the <code>IUITableViewDelegate<\/code> and <code>IUITableViewDataSource<\/code> interfaces. They contain only the mandatory methods. The optional ones can be implemented as follows:<\/p>\n<pre><code>[Export(\u201cnumberOfSectionsInTableView:\u201d)]\npublic int NumberOfSections(MonoTouch.UIKit.UITableView tableView)\n{\n ...\n}\n<\/code><\/pre>\n<p style=\"text-align: justify\">The <em>Export<\/em> keyword is used to make sure that the Objective C runtime sees your <code>NumberOfSections<\/code> method as the <code>numberOfSectionsInTableView:<\/code> method declared in the <code>UITableViewDataSource<\/code> protocol.<\/p>\n<h2>What it\u2019s all about: sharing code<\/h2>\n<p style=\"text-align: justify\">The greatest advantage you get by choosing Xamarin for your next project is definitely code reuse. The following chart illustrates very well which parts of a codebase can be shared:<\/p>\n<figure><a href=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/ConceptualArchitecture.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14153 size-full\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/ConceptualArchitecture.png\" alt=\"ConceptualArchitecture\" width=\"776\" height=\"430\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/ConceptualArchitecture.png 776w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/ConceptualArchitecture-300x166.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/ConceptualArchitecture-768x426.png 768w\" sizes=\"auto, (max-width: 776px) 100vw, 776px\" \/><\/a><figcaption>Xamarin Project Structure<\/figcaption><\/figure>\n<p style=\"text-align: justify\">Xamarin offers two approaches to sharing your code between multiple platforms: <a href=\"http:\/\/developer.xamarin.com\/guides\/cross-platform\/application_fundamentals\/shared_projects\/\"><em>Shared Project<\/em><\/a> or <a href=\"http:\/\/developer.xamarin.com\/guides\/cross-platform\/application_fundamentals\/pcl\/\"><em>Portable Class Library<\/em><\/a>. The former works in a very simple way. After creating a Shared Project you can make it a dependency of an arbitrary number of other projects, for example iOS and Android. This ensures that all files added to the Shared Project will be included in all projects that depend on it. A consequence of this is, that you need to use compiler directives if you want to include platform specific code in your Shared Project. Here is a quick example:<\/p>\n<pre><code>#if __IOS__\nnsDispatcher.BeginInvokeOnMainThread(NotifyListeners);\n#elif __ANDROID__\nDispatcher.RunOnUiThread(() =&gt; NotifyListeners());\n#endif\n<\/code><\/pre>\n<p style=\"text-align: justify\">Since the above code is compiled separately for iOS and Android the compiler can figure out which line should be used.<\/p>\n<p style=\"text-align: justify\"><em>Portable Class Libraries<\/em> work in a fundamentally different way. They are compiled as a separate target and only then included in other projects. When creating a PCL project, you need to specify which platforms you want to be able to run it on. Moreover, you will not be able to reference platform specific libraries or use some of the classes available in Xamarin.iOS and Xamarin.Android.<\/p>\n<p style=\"text-align: justify\">With the two Xamarin project running parallel at the moment, our strategy has been to place as much code as possible in a PCL. We wanted to avoid using compiler directives too aften, as this can become difficult to maintain over time. Here is a summary of the projects in terms of lines of code.<\/p>\n<table style=\"width: 480px;margin: 20px auto 20px\" align=\"center\">\n<colgroup>\n<col style=\"text-align: left\" \/>\n<col style=\"text-align: left\" \/>\n<col style=\"text-align: left\" \/> <\/colgroup>\n<thead>\n<tr>\n<th style=\"text-align: left\"><\/th>\n<th style=\"text-align: left\">Project 1<\/th>\n<th style=\"text-align: left\">Project 2<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: justify\">iOS<\/td>\n<td style=\"text-align: left\">5212<\/td>\n<td style=\"text-align: left\">5077<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">Android<\/td>\n<td style=\"text-align: left\">5914<\/td>\n<td style=\"text-align: left\">3172<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">Shared<\/td>\n<td style=\"text-align: left\">2244<\/td>\n<td style=\"text-align: left\">2807<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left\">Shared %<\/td>\n<td style=\"text-align: left\">17%<\/td>\n<td style=\"text-align: left\">25%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p style=\"text-align: justify\">As we can see, we\u2019re able to share 17% of our codebase in <em>Project 1<\/em>. We\u2019re expecting this number to go up, as we\u2019ve been focusing a bit more on the UI, than on the code that we actually can reuse between platforms.<\/p>\n<p style=\"text-align: justify\">Lines of code do not paint the whole picture, though. Sharing code makes it is easier for us to discuss certain areas of our projects, especially those related to data persistence and networking.<\/p>\n<h2>Sharing assets<\/h2>\n<p style=\"text-align: justify\">After starting our first Xamarin projects at Trifork we immediately identified strings and colours as great candidates for sharing between platforms. Unfortunately we were unable to find good, coherent solutions to this problem. Two of my colleagues decided to build a tool that would let us store the above-mentioned assets in one place, so that they are always in sync on all platforms. They named it <em>Tirfork Xamarin Localization<\/em> and it will soon be available for download, as a <a href=\"http:\/\/en.wikipedia.org\/wiki\/NuGet\"><em>Nuget package<\/em><\/a>, via the Xamarin package manager.<\/p>\n<p style=\"text-align: justify\">The way the tool works is very simple. It gets executed as a part of the build process and it generates assets for both Android and iOS, based on an input CSV file. For example, if we take iOS, what we get is <em>Localized.strings<\/em> files and a class containing static properties representing colors. The input files can even ba placed in Google Drive, which should ease cooperation with the translators.<\/p>\n<h2>Profiling tools<\/h2>\n<p>Profiling Xamarin applications can be done using two different tools: <em>Mono HeapShot<\/em> and the already known to iOS developers <em>Instruments<\/em>. The below screenshot presents the former in its full glory.<\/p>\n<figure><a href=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-14138 size-large\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot-1024x747.png\" alt=\"heapshot\" width=\"1024\" height=\"747\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot-1024x747.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot-300x219.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot-768x560.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot-1536x1120.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2015\/05\/heapshot.png 1646w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>Heapshot<\/figcaption><\/figure>\n<p>As you can see the interface is quite rudimentary. The tool offers both memory and performance analysis. Unfortunately generating a snaphost of the application\u2019s memory takes quite a long time, which can quickly get on your nerves. On the positive side, it is possible to select one of the generated snaphosts and compare it to any other snapshot. What <em>HeapShot<\/em> does, is show you the diff i.e. all the objects created between the two selected snapshots.<\/p>\n<p>I was not able to get the performance analysis part of <em>HeapShot<\/em> to work, which just confirms that it\u2019s better to stick with <em>Instruments<\/em>. While you won\u2019t find a way to launch it through <em>Xamarin Studio<\/em>, there is nothing in the way of attaching <em>Instruments<\/em> to a running app built with <em>Xamarin<\/em>.<\/p>\n<h2>Continuous integration<\/h2>\n<p style=\"text-align: justify\">Continuous integration with Xamarin is a rather painless affair, especially if you choose to use Jenkins on a Mac build server. That is what we decided to do and we managed to get up and running in no time. You use a program called <em>mdtool<\/em> to build your Xamarin project from command line. The command itself looks like this:<\/p>\n<pre><code>\/Applications\/Xamarin\\ Studio.app\/Contents\/MacOS\/mdtool -v\nbuild \u201c--configuration:Release|iPhone\u201d app\/MyAwesomeApp.sln\n<\/code><\/pre>\n<p style=\"text-align: justify\">It seems to be pretty easy but you have to remember that Jenkins needs to be able to access the keychain and your signing certificate. Otherwise the build will fail. Unfortunately we were not able to configure the project in a way, that would allow us to build the app without code signing. This is not ideal, because it requires us to update certificates stored in the build server\u2019s keychain, instead of placing them in the repo, alongside other resources. As a result, we had to resort to the following command that unlocks the keychain:<\/p>\n<pre><code>security unlock-keychain -pPASSWORD ~\/Library\/Keychains\/login.keychain\n<\/code><\/pre>\n<p style=\"text-align: justify\">If you also feel like making a build without code signing could be useful, please upvote our feature suggestion on the Xamarin <a href=\"https:\/\/xamarin.uservoice.com\/forums\/144858-xamarin-product-suggestions\/suggestions\/8077842-build-ipa-without-codesigning\">website<\/a>.<\/p>\n<p style=\"text-align: justify\">One last thing worth mentioning, is the fact that you do not need a separate license to be able to build Xamarin projects on your CI machine. You have to sign a special addendum to the contract, though. This requirement is mentioned in the <a href=\"http:\/\/xamarin.com\/faq#q24\">FAQ<\/a> on Xamarin\u2019s website.<\/p>\n<h2>Third party libraries<\/h2>\n<p style=\"text-align: justify\">Xamarin offers a great way to manage third party libraries called <a href=\"http:\/\/blog.xamarin.com\/xamarin-studio-and-nuget\/\">NuGet<\/a>. It\u2019s a package management system for .NET, which is tightly integrated with Xamarin Studio. You can search a repository of more than 37,000 libraries right from the IDE. But coming from iOS, you may be wondering whether you can use all those awesome projects available through CocoaPods. Sadly, it\u2019s not possible to use them directly. You have to go through the process of creating a so called <a href=\"http:\/\/developer.xamarin.com\/guides\/ios\/advanced_topics\/binding_objective-c\/binding_objc_libs\/\"><em>binding project<\/em><\/a>. This requires you to take the project you want, for example <em>AFNetworking<\/em>, build it into a library (with the .a extension) and create a bunch of C# files which map the Objective C API into a corresponding C# API. I haven\u2019t tried it myself, but it doesn\u2019t seem to be a very straightforward process and can certainly take a lot of time. This issue is addressed by <a href=\"http:\/\/developer.xamarin.com\/guides\/ios\/advanced_topics\/binding_objective-c\/objective_sharpie\/\"><em>Objective Sharpie<\/em><\/a>, a tool that generates bindings automatically. The disadvantage is, that you have to have a pretty good knowledge of how the library you want to bind works, and how to build it.<\/p>\n<h2>Closing thoughts<\/h2>\n<p style=\"text-align: justify\">I have spent only two months with Xamarin, but my impression is already very positive. It offers you an environment that feels very familiar and is very easy to get used to. C# is pleasure to work with and it improves on many areas compared to Objective C. It\u2019s great that you can still use <em>Instruments<\/em> to profile your apps. But most of all you get to reuse quite a lot of code.<\/p>\n<p style=\"text-align: justify\">As far as cons go, I would like to see more Objective C libraries ported to Xamarin and fewer annoying bugs in Xamarin Studio.<\/p>\n<div class=\"footnotes\">\n<hr \/>\n<ol>\n<li id=\"fn:1\"><a href=\"http:\/\/www.polouchkine.com\/should-you-use-xamarin-forms-well-it-depends\/\">Val Polouchkine on Xamarin.Forms<\/a> <a class=\"reversefootnote\" title=\"return to article\" href=\"1\">\u21a9<\/a><\/li>\n<\/ol>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>One of the fundamental mantras of software development is DRY &#8211; \u201cDon\u2019t repeat yourself\u201d. It\u2019s an important rule, because it allows us to save both space and time. Instead of rewriting a non-trivial algorithm, we use a method call, instead of correcting bugs in multiple places, we do it only in one. Would you ever [&hellip;]<\/p>\n","protected":false},"author":74,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[346,62,54,55,10],"tags":[344,59,67,411],"class_list":["post-14121","post","type-post","status-publish","format-standard","hentry","category-c","category-ipad","category-iphone","category-mobile","category-development","tag-c","tag-ios","tag-mobile","tag-xamarin"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"One of the fundamental mantras of software development is DRY &#8211; \u201cDon\u2019t repeat yourself\u201d. It\u2019s an important rule, because it allows us to save both space and time. Instead of rewriting a non-trivial algorithm, we use a method call, instead of correcting bugs in multiple places, we do it only in one. Would you ever [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-06-04T11:20:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png\" \/>\n<meta name=\"author\" content=\"Marcin Kuptel\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marcin Kuptel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/\",\"url\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/\",\"name\":\"iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png\",\"datePublished\":\"2015-06-04T11:20:34+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/cb5e04cb3052e86627e5e017ceb3f89b\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png\",\"contentUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"iOS perspective on\u00a0mobile development with Xamarin\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/cb5e04cb3052e86627e5e017ceb3f89b\",\"name\":\"Marcin Kuptel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1a5913f727b01fc5b726bbb107bc76c2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/1a5913f727b01fc5b726bbb107bc76c2?s=96&d=mm&r=g\",\"caption\":\"Marcin Kuptel\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/marcink\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/","og_locale":"en_US","og_type":"article","og_title":"iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog","og_description":"One of the fundamental mantras of software development is DRY &#8211; \u201cDon\u2019t repeat yourself\u201d. It\u2019s an important rule, because it allows us to save both space and time. Instead of rewriting a non-trivial algorithm, we use a method call, instead of correcting bugs in multiple places, we do it only in one. Would you ever [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/","og_site_name":"Trifork Blog","article_published_time":"2015-06-04T11:20:34+00:00","og_image":[{"url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png","type":"","width":"","height":""}],"author":"Marcin Kuptel","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Marcin Kuptel","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/","url":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/","name":"iOS perspective on\u00a0mobile development with Xamarin - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png","datePublished":"2015-06-04T11:20:34+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/cb5e04cb3052e86627e5e017ceb3f89b"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#primaryimage","url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png","contentUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2015\/05\/xamarin_studio-1024x619.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/ios-perspective-on-mobile-development-with-xamarin\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"iOS perspective on\u00a0mobile development with Xamarin"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/cb5e04cb3052e86627e5e017ceb3f89b","name":"Marcin Kuptel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/1a5913f727b01fc5b726bbb107bc76c2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1a5913f727b01fc5b726bbb107bc76c2?s=96&d=mm&r=g","caption":"Marcin Kuptel"},"url":"https:\/\/trifork.nl\/blog\/author\/marcink\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/14121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/74"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=14121"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/14121\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=14121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=14121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=14121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}