Pages - Menu

Sunday, March 26, 2017

UIDatePicker Countdown mode bug and solution in Xamarin.Forms

Problem

Show hh:mm:ss picker on iOS using Xamarin.Forms.

Goal

Extend Picker view in order to achieve the next result:

Solution

First I tried to keep it simple: to give up on seconds and use UIDatePicker in UIDatePickeCountDownMode. So the end result will look like this:
I achieved it by extending the DatePicker and it's DatePickerRenderer and changing the mode as described above. However, I discovered that 'datePickerValueChanged' is being called only on a second iteration with the values. The issue was successfully reproduced in Swift, so it's not a Xamarin bug. The Swift version can be found here.

After spending some time understanding the issue described above, I found an example on StackOverflow, thanks to Mathieu who shared his solution. His example was based on XLabs, so I removed the dependency and shared it with the community.
The code can be found on GitHub.


Tuesday, March 21, 2017

JSON.net Mastering enums

Problem

Legacy backend API endpoint returns JSON with units in an uncommon manner.
Instead of returning the measurement system "imperial" or "metric" it returns "kgs" or "lbs".

Goal

Using JSON.net deserialize & serialize "kgs" to "metric" and "lbs" to "imperial" in our front-end app.

Solution

The solution is pretty simple. We have to define an enum, with "EnumMember" attributes on each element and use "StringEnumConverter" as preferred JsonConvertor. Here is the full and working example:

using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace JSONnetEnums
{
    class Program
    {
        static void Main(string[] args)
        {
            var deserializedObj = 

                JsonConvert.DeserializeObject<Foo>("{\"Unit\":\"kgs\"}");
            Console.WriteLine(deserializedObj.Unit);
            // Output: Metric

            var serializedObj = 

                JsonConvert.SerializeObject(new Foo { Unit = Unit.Imperial });
            Console.WriteLine(serializedObj);
            // Output: {"Unit":"lbs"}
        }
    }

    class Foo
    {
        public Unit Unit { getset; }
    }

    [JsonConverter(typeof(StringEnumConverter))]
    enum Unit
    {
        [EnumMember(Value = "kgs")]
        Metric,
        [EnumMember(Value = "lbs")]
        Imperial
    }
}

Wednesday, March 15, 2017

Xamarin Forms SQLite-net PCL nuget package failing to install

Following Local Databases Xamarin guide in order to add SQLite database to a Xamarin Forms project I spent quite some time on adding the "SQLite.Net PCL" nuget package. It failed with the next message:

Could not install package 'System.Runtime.InteropServices.RuntimeInformation 4.0.0'. You are trying to install this package into a project that targets '.NETPortable,Version=v4.5,Profile=Profile111', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

The solution is pretty easy, you just have to install "System.Runtime.InteropServices.RuntimeInformation" before installing "SQLite.Net PCL"  nuget package.

More details can be found here.

Tuesday, March 14, 2017

JSON.net snake case notation naming strategy

Communicating with backend in JSON can be challenging.
In case of C# model which by convention should be in CamelCase notation and backend which is using snake_notation we can easily solve the problem with Json.NET.

For example, we have the next model:

public class Model
{
  public string FooBar { get; set; }
}

and we want it to be serialised to: { "foo_bar": "" }
We could use an attribute:

[JsonProperty(PropertyName = "foo_bar")]
public string FooBar { get; set; }

That will work, however, if we want to generalise this strategy we should create a JsonSerializerSettings with DefaultContactResolver which is using SnakeCaseNamingStrategy and to use it while serialisation/deserialization:

public class JsonCoverter : IJsonConverter
{
 private static JsonSerializerSettings defaultJsonSerializerSettings = 
new JsonSerializerSettings
 {
  ContractResolver = new DefaultContractResolver
  {
   NamingStrategy = new SnakeCaseNamingStrategy()
  }
 };
    
 public T Deserialize<T>(string json) =>
  JsonConvert.DeserializeObject<T>(json, defaultJsonSerializerSettings);
      
 public string Serialize(object obj) =>
  JsonConvert.SerializeObject(obj, defaultJsonSerializerSettings);
   
}

Using the JsonConverter globally will solve the different notation problem.

Saturday, March 4, 2017

How to debug an iOS app build in Xamarin on a real device for free?

"With Apple's release of Xcode 7 came an important change for all iOS and Mac developers–free provisioning."

So all you need is an apple id and to configure your IDE.
There are a lot of guides available out there, so this post is not going to be another one:
Xamarin Developer Guide
- http://stackoverflow.com/a/32249026/1970317

One thing that can be confusing is that first, you need to create a Xcode project with the same "Bundle Identifier" and then download the free provisioning profile. Just pay attention to the uniqueness of your bundle identifier otherwise, it won't work.