Xamarin.Forms: First look


Installation

In MacOS, install Xamarin Studio and you will be able to developing for iOS and Android.
In Windows, you will require to install Visual Studio and/or Xamarin Studio and you will be able to develop Android and Windows. If you have access to a MacOS then you will also be able to develop for iOS.

Go to, https://www.xamarin.com/download

Download Xamarin Studio and Install. The installation wizard will download a pretty big amount of data, like 3.5 GB. Bear with it.

After Installation, enter your credential in Xamarin Studio (Menu) -> Accounts.

Xamarin Player

Download Xamarin Player from, https://developer.xamarin.com/releases/android/android-player/

Screenshot at Nov 22 04-29-02.png

First Project

  1. Start Xamarin Studio/ Visual Studio
  2. File -> New Solution.
  3. Multiplatform -> App.
  4. Forms App (C#) -> Next.

Screenshot at Sep 17 11-13-37.png

  1. Give an app name. Here, XamarinFormsFirstLook
  2. Select Use Portable Class Library
  3. Select Use XAML for user interface files
  4. Next

Screenshot at Nov 22 04-12-13.png

Optionally you can enable Git and Automated UI test.

Screenshot at Nov 22 04-13-41.png

You should see there are three projects under a solution.

  1. Common code/ project (PCL)
  2. Droid project
  3. iOS project.

Screenshot at Nov 22 04-31-59.png

Before beginning, let’s build the project. Build (menu) -> Build All (Cmd + B)

Troubleshooting

Error MT0091: This version of Xamarin.iOS requires the iOS 10.0 SDK (shipped with Xcode 8.0) when the managed linker is disabled. Either upgrade Xcode, or enable the managed linker. (MT0091) (XAMLFirstLookDemo.iOS)

If you get the above error, it means you need to upgrade your Xcode.

If that is not an option for now, you can try to downgrade your Xamarin.iOS. You can get the previous Xamarin.iOS SDK here.

If that is not an option for now, you can enable the managed linker (although this may not work if your project uses API that was introduced in the required SDK).

(Disclaimer: This is official Xamarin suggestion, but didn’t work for me.)

Double-click on the iOS project and browse to iOS Build > Linker Options, as illustrated below:

Screenshot at Sep 17 11-31-59.png

And select, Linker behavior: Link All.

Rebuild the project again.

Project Structure

There are 3 projects inside the solution XamarinFormsFirstLook

Screenshot at Nov 22 04-36-47.png

We will be working with XamarinFormsFirstLookPage.xaml file.

Let’s create a simple change in the XamarinFormsFirstLookPage.xaml file

First Program

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Run the application and see the output in iOS simulator.

The equivalent C# code would look like this,

namespace XamarinFormsFirstLookPage
{
	public partial class XAMLFirstLookDemoPage : ContentPage
	{
		public XAMLFirstLookDemoPage()
		{
			Content = CreateUI();
			InitializeComponent();
		}

		public View CreateUI()
		{
			var parentStackLayout = new StackLayout()
			{
				Padding = 16,
				Children = {
					new Label() {
						Text = "Welcome to Xamarin Forms!",
						VerticalOptions = LayoutOptions.Start,
						HorizontalOptions = LayoutOptions.Center
					},
					new StackLayout() {
						Orientation = StackOrientation.Horizontal,
						Padding = 16,
						Children = {
							new Label() {
								Text = "Name",
								VerticalOptions = LayoutOptions.Center
							},
							new Entry() {
								Placeholder = "Enter your name"
							}
						}
					}
				}
			};

			return parentStackLayout;
		}
	}
}

Add an Action

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
				<Button Text="Submit" Clicked="Submit_Clicked"/>
			</StackLayout>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class XamarinFormsFirstLookPage : ContentPage
	{
		public XamarinFormsFirstLookPage()
		{
			InitializeComponent();
		}

	    private void Submit_Clicked(object sender, EventArgs e)
	    {
	        DisplayAlert("Greetings!", "Hello from Xamarin.Forms!", "OK");
	    }
	}
}

Navigation

To navigate from one page to another you need Navigation.
Using Navigation you can move to next page, come back to previous page, skip any intermediate page, remove a page, insert a new page in between etc.

In this example, we will add a button in our first page and tapping on the button will take us to the second page.

Let’s add NavigationPage.

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new XamarinFormsFirstLookPage());
		}

		protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}

Now let’s create a new page

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.NextPage">
	<ContentPage.Content>
		<Button 				Text="Hello I am Next Page" 				VerticalOptions="Start" 				HorizontalOptions="Center" 				Clicked="GoBack_Clicked"/>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class NextPage : ContentPage
	{
		public NextPage()
		{
			InitializeComponent();
		}

		private void GoBack_Clicked(object sender, EventArgs e)
		{
			Navigation.PopAsync();
		}
	}
}

Add a button and title in our first page

<?xml version="1.0" encoding="utf-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.XamarinFormsFirstLookPage" 		Title="Xamarin.Forms First Look">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Welcome to Xamarin Forms!" 				VerticalOptions="Start" 				HorizontalOptions="Center" />
			<StackLayout 				Orientation="Horizontal" 				Spacing="8">
				<Label 					Text="Name" 					VerticalOptions="Center" />
				<Entry 					Placeholder="Enter your name" />
				<Button Text="Submit" Clicked="Submit_Clicked"/>
			</StackLayout>
			<Button Text="Next Page" Clicked="NextPage_Clicked"/>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class XamarinFormsFirstLookPage : ContentPage
	{
		public XamarinFormsFirstLookPage()
		{
			InitializeComponent();
		}

		private void Submit_Clicked(object sender, EventArgs e)
		{
			DisplayAlert("Greetings!", "Hello from Xamarin.Forms!", "OK");
		}

		private void NextPage_Clicked(object sender, EventArgs e)
		{
			Navigation.PushAsync(new NextPage());
		}
	}
}

Let’s run the app again.

Data binding

Create a model class User, with some simple properties.

namespace XamarinFormsFirstLook.Models
{
    public class User
    {
        public User()
        {
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
	public string Password { get; set; }
    }
}

XAML layout file to display the properties

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DataBindingPage1">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="{Binding FirstName}" 				Font="16" />
			<Label 				Text="{Binding LastName}" 				Font="14" />
			<Label 				Text="{Binding Age}" 				Font="12" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Now we will create a simple User object and set it as BindingContext

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public partial class DataBindingPage1 : ContentPage
	{
		public DataBindingPage1()
		{
			BindingContext = GetUser();
			InitializeComponent();
		}

		private User GetUser()
		{
			return new User
			{
				FirstName = "John",
				LastName = "Doe",
				Age = 25
			};
		}
	}
}

Data binding#2

using System;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public class DataBindingPage2ViewModel
	{
		public DataBindingPage2ViewModel(User user)
		{
			FullName = user.FirstName + " " + user.LastName;
			Age = GetAge(user.Age);
			Password = user.Password.Length == 0 ? "<Set password>" : "******";
		}

		string GetAge(int Age)
		{
			if (Age < 18) return Age + "(Child)";
			if (Age < 30) return Age + "(Young)";
			if (Age < 50) return Age + "(Adult)";
			else return Age + "(Old)";
		}

		public string FullName { get; set; }
		public string Age { get; set; }
		public string Password { get; set; }

		public static User GetUser()
		{
			return new User()
			{
				FirstName = "John",
				LastName = "Doe",
				Age = 25,
				Password = "Jonny"

			};
		}

		public static User GetUser2()
		{
			return new User()
			{
				FirstName = "Sarah",
				LastName = "Doe",
				Age = 65,
				Password = ""
			};
		}

	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DataBindingPage2">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="{Binding FullName}" 				Font="16" />
			<Label 				Text="{Binding Age}" 				Font="14" />
			<Label 				Text="{Binding Password}" 				Font="12" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Models;

namespace XamarinFormsFirstLook
{
	public partial class DataBindingPage2 : ContentPage
	{
		DataBindingPage2ViewModel dbp2VM;

		public DataBindingPage2()
		{
			User user1 = DataBindingPage2ViewModel.GetUser();
			User user2 = DataBindingPage2ViewModel.GetUser2();

			dbp2VM = new DataBindingPage2ViewModel(user2);
			BindingContext = dbp2VM;

			InitializeComponent();
		}
	}
}

List View

using System;
using System.Collections.Generic;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public class ListPage1ViewModel
	{
		public string FirstName { get; set; }
		public string LastName { get; set; }
		public string Age { get; set; }

		public ListPage1ViewModel()
		{
		}

		public List<User> Users()
		{
			return new List<User>()
			{
				new User() {FirstName = "John", LastName = "Doe", Age = 25},
				new User() {FirstName = "Sarah", LastName = "Doe", Age = 58},
				new User() {FirstName = "Andrew", LastName = "Phillips", Age = 35}
			};

		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.ListPage1">
	<ContentPage.Content>
		<ListView 			x:Name="UserListView" 			ItemSelected="ListView_OnItemSelected" 			RowHeight="120">
			<ListView.ItemTemplate>
				<DataTemplate>
					<ViewCell>
						<StackLayout 							Padding="16" 							Spacing="8" 							Orientation="Vertical">
							<Label 								Text="{Binding FirstName}" 								FontSize="20">
							</Label>
							<Label 								Text="{Binding LastName}" 								FontSize="18">
							</Label>
							<Label 								Text="{Binding Age}" 								FontSize="16">
							</Label>
						</StackLayout>
					</ViewCell>
				</DataTemplate>
			</ListView.ItemTemplate>
		</ListView>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage1 : ContentPage
	{
		private ListPage1ViewModel vm;

		public ListPage1()
		{

			InitializeComponent();
			vm = new ListPage1ViewModel();
			UserListView.ItemsSource = vm.Users();
		}

		private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
		{
			User user = e.SelectedItem as User;
			DisplayAlert("User selected", user.FirstName, "OK");
		}
	}
}

Tabbed Pages

Create a generic XAML file

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage1" 	Title="Tab 1">
	<ContentPage.Content>
		<Label 			Text="I am Tab 1" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>

Remember, the Title property is very important.

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage1 : ContentPage
	{
		public TabPage1()
		{
			InitializeComponent();
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage2" 	Title="Tab 2">
	<ContentPage.Content>
		<Label 			Text="I am Tab 2" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage2 : ContentPage
	{
		public TabPage2()
		{
			InitializeComponent();
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabPage3" 	Title="Tab 3">
	<ContentPage.Content>
		<Label 			Text="I am Tab 3" 			FontSize="20" 			VerticalOptions="Center" 			HorizontalOptions="Center" />
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabPage3 : ContentPage
	{
		public TabPage3()
		{
			InitializeComponent();
		}
	}
}

Now we need a tab container, TabbedPage

<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.TabContainer" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">

	<TabbedPage.Children>
		<local:TabPage1/>
		<local:TabPage2/>
		<local:TabPage3/>
	</TabbedPage.Children>

</TabbedPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class TabContainer : TabbedPage
	{
		public TabContainer()
		{
			InitializeComponent();
		}
	}
}

Static Style

Let’s create a StylePage and will put colors on our regular controls.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.StylePage">
	<ContentPage.Resources>
		<ResourceDictionary>
<Style 				x:Key="buttonStyle" 				TargetType="Button">
				<Setter 					Property="HorizontalOptions" 					Value="Center">
				</Setter>
				<Setter 					Property="TextColor" 					Value="Lime">
				</Setter>
				<Setter 					Property="FontSize" 					Value="20">
				</Setter>
			</Style>
<Style 				TargetType="Label">
				<Setter 					Property="HorizontalOptions" 					Value="Center">
				</Setter>
				<Setter 					Property="TextColor" 					Value="Blue">
				</Setter>
				<Setter 					Property="FontSize" 					Value="26">
				</Setter>
			</Style>
<Style 				x:Key="baseStyle" 				TargetType="View">
				<Setter 					Property="HorizontalOptions" 					Value="Start">
				</Setter>
			</Style>
<Style 				x:Key="entryStyle" 				TargetType="Entry" 				BasedOn="{StaticResource baseStyle}">
				<Setter 					Property="TextColor" 					Value="Red">
				</Setter>
			</Style>

		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<StackLayout 			Orientation="Vertical">
			<Button 				Text="Button 01" 				Style="{StaticResource buttonStyle}">
			</Button>
			<Button 				Text="Button 02">
			</Button>
			<Button 				Text="Button 03" 				BorderWidth="2">
			</Button>
			<Label 				Text="Label 01">
			</Label>
			<Entry 				Placeholder="Entry 01">
			</Entry>
			<Entry 				Placeholder="Entry 02" 				Style="{StaticResource entryStyle}">
			</Entry>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class StylePage : ContentPage
	{
		public StylePage()
		{
			InitializeComponent();
		}
	}
}

Dynamic Style

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.DynamicStylePage">
	<ContentPage.Resources>
		<ResourceDictionary>
			<x:String 				x:Key="currentTime">Show current time</x:String>
		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<Label 			HorizontalOptions="Center" 			VerticalOptions="Center" 			FontSize="24" 			Text="{DynamicResource currentTime}">
		</Label>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class DynamicStylePage : ContentPage
	{
	    private bool shouldDisplayTime;

		public DynamicStylePage()
		{
			InitializeComponent();
		}

	    protected override void OnAppearing()
	    {
	        shouldDisplayTime = true;
	        Device.StartTimer( TimeSpan.FromSeconds(1), () =>
	        {
	            Resources["currentTime"] = DateTime.Now.ToString();
	            return shouldDisplayTime;
	        });
	        base.OnAppearing();

	    }

	    protected override void OnDisappearing()
	    {
	        shouldDisplayTime = false;
	        base.OnDisappearing();
	    }
	}
}

Triggers

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook" 	x:Class="XamarinFormsFirstLook.TriggerPage" 	Title="Trigger">
	<ContentPage.Resources>
		<ResourceDictionary>
<Style 				TargetType="Entry">
				<Style.Triggers>
					<Trigger 						Property="Entry.IsFocused" 						Value="true" 						TargetType="Entry">
						<Setter 							Property="Entry.TextColor" 							Value="Blue" />
					</Trigger>
				</Style.Triggers>
			</Style>

		</ResourceDictionary>
	</ContentPage.Resources>
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Entry 				Placeholder="Enter your first name" />
			<Entry 				Placeholder="Enter your last name" />
			<Entry 				TextColor="Black" 				Placeholder="Enter your age">
				<Entry.Triggers>
					<EventTrigger 						Event="TextChanged">
						<local:EntryValidation />
					</EventTrigger>
				</Entry.Triggers>
			</Entry>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
    public class EntryValidation : TriggerAction<Entry>
    {
        public EntryValidation()
        {
        }

        protected override void Invoke(Entry sender)
        {
            int parsedAge;

            bool isValid = int.TryParse(sender.Text, out parsedAge);

            if (!isValid)
            {
                sender.TextColor = Color.Red;
            }
            else {
                sender.TextColor = Color.Blue;
            }
        }
    }
}

Publisher Subscriber (Pub Sub)

We can send messages from one page to another.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PubSubPage" 	Title="Pub Sub Page">
	<ContentPage.Content>
		<Button 			x:Name="ButtonPubSub" 			HorizontalOptions="Center" 			VerticalOptions="Center" 			Text="Next page" 			Clicked="Button_OnClicked">
		</Button>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class PubSubPage : ContentPage
	{
		public PubSubPage()
		{
			InitializeComponent();
		    Subscribe();
		}

	    private void Subscribe()
	    {
	        MessagingCenter.Subscribe<PubSubPage>(this, "fireEvent", (sender) =>
	        {
	            ButtonPubSub.Text = "Don't click!!";
	        });
	    }

	    private void Button_OnClicked(object sender, EventArgs e)
	    {
	        Navigation.PushAsync(new PubPage());
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PubPage" 	Title="Pub Page">
	<ContentPage.Content>
		<Button 			HorizontalOptions="Center" 			VerticalOptions="Center" 			Text="Pub Page" 			Clicked="Button_OnClicked">
		</Button>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class PubPage : ContentPage
	{
		public PubPage()
		{
			InitializeComponent();
		}

	    private void Button_OnClicked(object sender, EventArgs e)
	    {
            MessagingCenter.Send<PubSubPage>(new PubSubPage(), "fireEvent");
	        Navigation.PopAsync();
	    }
	}
}
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Content>
		<StackLayout Padding="16" BackgroundColor="Blue" />
	</ContentPage.Content>
</ContentPage>

On #4 we have  BackgroundColor="Blue" and it takes up whole space of iOS but leaves the status bar of Android.

To resolve this, we need to add padding in iOS

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
	</ContentPage.Padding>
	<ContentPage.Content>
		<StackLayout Padding="16" BackgroundColor="Blue" />
	</ContentPage.Content>
</ContentPage>

Adding a StackLayout with an Entry and Button click handler.

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Todo_Xamarin_Forms" x:Class="Todo_Xamarin_Forms.Todo_Xamarin_FormsPage">
	<ContentPage.Padding>
		<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
	</ContentPage.Padding>
	<ContentPage.Content>
		<!--  		Padding = Layout padding 		Spacing = Space between elements  		-->
		<StackLayout Padding="16" Spacing="8" VerticalOptions="Center" HorizontalOptions="Center">
			<Label x:Name="LblName" Text="Enter user name" />
			<Entry x:Name="TxtUserName" Placeholder="Enter user name" />
			<Button x:Name="BtnSubmit" Text="Submit" IsEnabled="true" Clicked="Submit_Clicked" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class Todo_Xamarin_FormsPage : ContentPage
	{

		public Todo_Xamarin_FormsPage()
		{
			InitializeComponent();
		}

		void Submit_Clicked(object sender, System.EventArgs e)
		{
			LblName.Text = "Hello, " + TxtUserName.Text + "!";
		}
	}
}

Adding Preference

Add Xam.Plugins.Settings package in all 3 projects (Forms, Android, iOS)

After adding the package change in Helpers -> Settings.cs of Forms module

// Helpers/Settings.cs

using Plugin.Settings;
using Plugin.Settings.Abstractions;

namespace Todo_Xamarin_Forms.Helpers
{
	///
<summary>
	/// This is the Settings static class that can be used in your Core solution or in any
	/// of your client applications. All settings are laid out the same exact way with getters
	/// and setters.
	/// </summary>

	public static class Settings
	{
		private static ISettings AppSettings
		{
			get { return CrossSettings.Current; }
		}

		#region Setting Constants

		private const string SettingsKey = "settings_key";
		private static readonly string SettingsDefault = string.Empty;

		private const string UserNameKey = "uname_key";
		private static readonly string UserNameDefault = string.Empty;

		#endregion

		public static string GeneralSettings
		{
			get { return AppSettings.GetValueOrDefault<string>(SettingsKey, SettingsDefault); }
			set { AppSettings.AddOrUpdateValue<string>(SettingsKey, value); }
		}

		public static string UserName
		{
			get { return AppSettings.GetValueOrDefault<string>(UserNameKey, UserNameDefault); }
			set { AppSettings.AddOrUpdateValue<string>(UserNameKey, value); }
		}
	}
}
public partial class Todo_Xamarin_FormsPage : ContentPage
	{

		public Todo_Xamarin_FormsPage()
		{
			InitializeComponent();

			TxtUserName.Text = Settings.UserName;
		}

		void Submit_Clicked(object sender, System.EventArgs e)
		{
			var name = TxtUserName.Text;

			if (!string.IsNullOrWhiteSpace(name))
			{
				Settings.UserName = name;
			}
			else
			{
				DisplayAlert("Error", "Pleaes enter your user name", "OK");
			}

			LblName.Text = "Hello, " + name + "!";
		}
	}

Add a ListView

Create a new ListPage

<?xml version="1.0" encoding="UTF-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"              x:Class="Todo_Xamarin_Forms.LIstPage" Title="Saved Items">
    <ContentPage.Content>
        <ListView x:Name="ListView" ItemSelected="ListView_OnItemSelected" RowHeight="80">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <AbsoluteLayout IsClippedToBounds="True" LayoutBounds="1,1,1,1" LayoutFlags="All">
                            <Image Source="bg_img.png" Aspect="Fill" />
                            <StackLayout Padding="10, 10, 0, 0" HorizontalOptions="StartAndExpand"                                          Orientation="Vertical">
                                <Label Text="{Binding title}" HorizontalOptions="Start" FontSize="Medium"                                        TextColor="Blue" />
                                <Label Text="{Binding description}" FontSize="Small" TextColor="Green" />
                            </StackLayout>
                        </AbsoluteLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class LIstPage : ContentPage
	{
		public LIstPage()
		{
			InitializeComponent();
		}

	    private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
	    {

	    }
	}
}

Add NagivationPage

		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new Todo_Xamarin_FormsPage())
			{
				BarTextColor = Color.White,
				BarBackgroundColor = Color.Blue
			};
		}

Add SQLite Database

Add library sqlite-net-pcl

Get platform specific DB connection

using SQLite;

namespace Todo_Xamarin_Forms
{
    public interface ISQLite
    {
        SQLiteConnection GetConnection();
    }
}

Android Implementation

using System;
using System.IO;
using SQLite;
using Todo_Xamarin_Forms.Droid;
using Xamarin.Forms;

[assembly: Dependency(typeof(SQLite_Android))]
namespace Todo_Xamarin_Forms.Droid
{
	public class SQLite_Android : ISQLite
	{
		public SQLite_Android()
		{

		}

		#region ISQLite implementation 

		public SQLiteConnection GetConnection()
		{
			var dbFile = "database.db3";
			var privatePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			var path = Path.Combine(privatePath, dbFile);
			var connection = new SQLite.SQLiteConnection(path, true);
			return connection;
		}

		#endregion
	}
}

iOS Implementation

using System;
using System.IO;
using SQLite;
using Xamarin.Forms;
using Todo_Xamarin_Forms.iOS;

[assembly: Dependency(typeof(SQLite_iOS))]
namespace Todo_Xamarin_Forms.iOS
{
	public class SQLite_iOS : ISQLite
	{
		public SQLite_iOS()
		{
		}

		#region ISQLite implementation 

		public SQLiteConnection GetConnection()
		{
			var dbFile = "database.db3";
			var privatePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			var libPath = Path.Combine(privatePath, "..", "Library");
			var path = Path.Combine(libPath, dbFile);
			var connection = new SQLite.SQLiteConnection(path, true);
			return connection;
		}

		#endregion
	}
}

Model class

using System;
using SQLite;

namespace Todo_Xamarin_Forms
{
	public class ListItemModel
	{
		[PrimaryKey, AutoIncrement]
		public int ID { get; set; }

		public string title { get; set; }
		public string description { get; set; }
	}
}

Database

using System;
using SQLite;
using Xamarin.Forms;
using System.Collections.Generic;
using System.Linq;

namespace Todo_Xamarin_Forms
{
	public class Database
	{

		private SQLiteConnection _connection;

		public Database()
		{
			_connection = DependencyService.Get<ISQLite>().GetConnection();
			_connection.CreateTable<ListItemModel>();
		}

		public List<ListItemModel> GetListItems()
		{
			return (from item in _connection.Table<ListItemModel>() select item).ToList();
		}

		public void AddItem(ListItemModel item)
		{
			_connection.Insert(item);
		}

		public void AddItems(List<ListItemModel> items)
		{
			foreach (var item in items)
				AddItem(item);
		}

		public void EditItem(ListItemModel item)
		{
			_connection.Update(item);
		}
	}
}

Load Items from Database

using System;
using System.Collections;
using System.Collections.Generic;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class ListPage : ContentPage
	{
		public ListPage()
		{
			InitializeComponent();
		    CheckDatabasePopulated();
		    ListView.ItemsSource = GetItems();
		}

	    List<ListItemModel> GetItems()
	    {
	        var items = new Database().GetListItems();
	        return items;
	    }

	    private void CheckDatabasePopulated()
	    {
	        if (new Database().GetListItems().Count < 1)
	        {
	            var items = new List<ListItemModel>();

	            for (int i = 0; i < 10; i++)
	            {
	                items.Add(new ListItemModel()
	                {
                        title = "Item title" + (i + 1).ToString(),
	                    description = "Description - " + (i + 1).ToString()
	                });
	            }

	            new Database().AddItems(items);
	        }
	    }

	    private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
	    {

	    }
	}
}

Item Edit Page

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Todo_Xamarin_Forms.ItemEditPage" xmlns:locale="clr-namespace:Todo_Xamarin_Forms:assembly=Todo_Xamarin_Forms" Title="Edit page">
	<ContentPage.Content>
		<StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand" Orientation="Horizontal">
			<Entry Text="{Binding title, Mode=TwoWay}" HorizontalOptions="CenterAndExpand" />
			<Entry Text="{Binding description, Mode=TwoWay}" HorizontalOptions="CenterAndExpand" />
			<Button Text="Save" Clicked="Save_Clicked" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;
using System.ComponentModel;

using Xamarin.Forms;

namespace Todo_Xamarin_Forms
{
	public partial class ItemEditPage : ContentPage
	{
		public ListItemModel Model
		{
			get { return (ListItemModel)BindingContext; }
			set
			{
				BindingContext = value;
				OnPropertyChanged();
			}
		}

		public ItemEditPage(ListItemModel item)
		{
			Model = item;

			InitializeComponent();
		}

		void Save_Clicked(object sender, System.EventArgs e)
		{
			if (string.IsNullOrEmpty(Model.title)) return;

			new Database().EditItem(Model);
			Navigation.PopAsync();
		}
	}
}

Updates ListPage

public partial class ListPage : ContentPage
	{
		public ListPage()
		{
			InitializeComponent();
			CheckDatabasePopulated();
		}

		protected override void OnAppearing()
		{
			base.OnAppearing();
			ListView.ItemsSource = GetItems();
		}

		List<ListItemModel> GetItems()
		{
			var items = new Database().GetListItems();
			return items;
		}

		private void CheckDatabasePopulated()
		{
			if (new Database().GetListItems().Count < 1)
			{
				var items = new List<ListItemModel>();

				for (int i = 0; i < 10; i++)
				{
					items.Add(new ListItemModel()
					{
						title = "Item title" + (i + 1).ToString(),
						description = "Description - " + (i + 1).ToString()
					});
				}

				new Database().AddItems(items);
			}
		}

		private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
		{
			if (e.SelectedItem == null) return;

			((ListView)sender).SelectedItem = null;

			Navigation.PushAsync(new ItemEditPage((ListItemModel)e.SelectedItem));
		}
	}

Custom Button

using System;
using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public class GLabButton : Button
	{
		public GLabButton()
		{
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomButton" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout Padding="16">
               <Entry Placeholder="Enter your name"/>
            <local:GLabButton Text="Click me!" TextColor="Navy" FontSize="16" Clicked="OnClickHandler"/>
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class CustomButton : ContentPage
	{
		public CustomButton()
		{
			InitializeComponent();
		}

	    private void OnClickHandler(object sender, EventArgs e)
	    {
	        DisplayAlert("Hello", "Nice Button", "OK");
	    }
	}
}

Inside the iOS project create the renderer file

using System.Reflection;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.iOS;

[assembly:ExportRendererAttribute(typeof(GLabButton), typeof(GLabButtonRenderer))]

namespace XamarinFormsFirstLook.iOS
{
    public class GLabButtonRenderer : ButtonRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                Control.BackgroundColor = UIColor.Red;
            }
        }
    }
}

Run the project in iOS and see the custom effect (Background color red)
Run the same project in Android and see a regular button instead of this effect.

Custom BoxView

using System;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public class GLabBoxView : BoxView
	{
		public static readonly BindableProperty BorderColorProperty = BindableProperty.Create<GLabBoxView, Color>(
		    p => p.BorderColor, default(Color)
		);

	    public Color BorderColor
	    {
	        get { return (Color) GetValue(BorderColorProperty); }
	        set { SetValue(BorderColorProperty, value);}
	    }

	    public static readonly BindableProperty BorderThicknessProperty = BindableProperty.Create<GLabBoxView, double>(
	        p => p.BorderThickness, default(double)
	    );

	    public double BorderThickness
	    {
	        get { return (double) GetValue(BorderThicknessProperty); }
	        set { SetValue(BorderThicknessProperty, value);}
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomBoxView" 	xmlns:local="clr-namespace:XamarinFormsFirstLook;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<local:GLabBoxView 				WidthRequest="160" 				HeightRequest="160" 				Color="Accent" 				BorderColor="Green" 				BindingContext="{x:Reference Name=SliderThickNess}" 				BorderThickness="{Binding Path=Value}" />
			<Label 				BindingContext="{x:Reference Name=SliderThickNess}" 				Text="{Binding Path=Value}" />
			<Slider 				x:Name="SliderThickNess" 				Minimum="0" 				Maximum="30" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Custom renderer in iOS

using Xamarin.Forms.Platform.iOS;
using UIKit;
using System.ComponentModel;
using CoreGraphics;
using Xamarin.Forms;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.iOS;

[assembly:ExportRendererAttribute(typeof(GLabBoxView), typeof(GLabBoxViewRenderer))]

namespace XamarinFormsFirstLook.iOS
{
    public class GLabBoxViewRenderer : BoxRenderer
    {
        public override void Draw(CGRect rect)
        {
            GLabBoxView boxView = (GLabBoxView) Element;
            using (var context = UIGraphics.GetCurrentContext())
            {
                context.SetFillColor(boxView.Color.ToCGColor());
                context.SetStrokeColor(boxView.BorderColor.ToCGColor());
                context.SetLineWidth((float) boxView.BorderThickness);

                var rectangle = Bounds.Inset((int) boxView.BorderThickness, (int) boxView.BorderThickness);

                var path = CGPath.FromRect(rectangle);
                context.AddPath(path);
                context.DrawPath((CGPathDrawingMode.FillStroke));
            }
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == GLabBoxView.BorderThicknessProperty.PropertyName)
            {
                SetNeedsDisplay();
            }
        }
    }
}

Custom renderer in Android

using System.ComponentModel;
using Android.Graphics;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinFormsFirstLook;
using XamarinFormsFirstLook.Droid;

[assembly:ExportRendererAttribute(typeof(GLabBoxView), typeof(GLabBoxViewRenderer))]

namespace XamarinFormsFirstLook.Droid
{
    public class GLabBoxViewRenderer : BoxRenderer
    {
        public GLabBoxViewRenderer()
        {
            SetWillNotDraw(false);
        }

        public override void Draw(Android.Graphics.Canvas canvas)
        {
            base.Draw(canvas);

            GLabBoxView boxView = (GLabBoxView) Element;

            Rect rect = new Rect();
            GetDrawingRect(rect);

            Rect inside = rect;
            inside.Inset(
                (int) boxView.BorderThickness,
                (int) boxView.BorderThickness
            );

            Paint p = new Paint();
            p.Color = boxView.Color.ToAndroid();

            canvas.DrawRect(inside, p);

            p.Color = boxView.BorderColor.ToAndroid();
            p.StrokeWidth = (float) boxView.BorderThickness;
            p.SetStyle(Paint.Style.FillAndStroke);

            canvas.DrawRect(rect, p);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            Invalidate();
        }
    }
}

Custom markup extension

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace XamarinFormsFirstLook.Extension
{
    public class RGBExtension : IMarkupExtension
    {
        public int Red { get; set; }
        public int Green { get; set; }
        public int Blue { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            return Color.FromRgb(Red, Green, Blue);
        }
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.CustomMarkup" 	xmlns:local="clr-namespace:XamarinFormsFirstLook.Extension;assembly=XamarinFormsFirstLook">
	<ContentPage.Content>
		<StackLayout 			Padding="16">
			<Label 				Text="Hello World" 				FontSize="30" 				TextColor="{local:RGBExtension Red=105, Green=205, Blue=180}" />
			<Label 				Text="Hello Xamarin" 				FontSize="36" 				TextColor="{local:RGBExtension Red=150, Green=250, Blue=0}" 				BackgroundColor="{local:RGBExtension Red=50, Green=60, Blue=70}" />
		</StackLayout>
	</ContentPage.Content>
</ContentPage>

Platform Service

using System;

namespace XamarinFormsFirstLook.Extension
{
    public interface ITwitter
    {
        void SendTweet(String msg);
    }
}

Write the service in iOS

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 	xmlns="http://xamarin.com/schemas/2014/forms" 	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 	x:Class="XamarinFormsFirstLook.PlatformService">
	<ContentPage.Content>
        <Button Text="Twitter" Clicked="onClickTwitter"></Button>
	</ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Extension;

namespace XamarinFormsFirstLook
{
	public partial class PlatformService : ContentPage
	{
		public PlatformService()
		{
			InitializeComponent();
		}

	    private void onClickTwitter(object sender, EventArgs e)
	    {
                DependencyService.Get<ITwitter>().SendTweet("Hello world!!");
	    }
	}
}

List View (Once again)

using System;

namespace XamarinFormsFirstLook.Model
{
    public class Contact
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Email { get; set; }

        public Boolean IsFavorite { get; set; }
    }
}
using System;
using System.Collections.Generic;

using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class DataGenerator
    {
        private static List<string> FirstNames = new List<string> {
            "Aiden", "Liam", "Lucas", "Noah", "Mason", "Ethan", "Caden", "Jacob", "Logan", "Jayden", "Elijah", "Jack", "Luke", "Michael", "Benjamin",
            "Alexander", "James", "Jayce", "Caleb", "Connor", "William", "Carter", "Ryan", "Oliver", "Matthew", "Daniel", "Gabriel", "Henry", "Owen",
            "Grayson", "Lincoln", "Jordan", "Tristan", "Jason", "Josiah", "Xavier", "Camden", "Chase", "Declan", "Carson", "Colin", "Brody", "Asher",
            "Jeremiah", "Micah", "Easton", "Xander", "Ryder", "Nathaniel", "Elliot", "Sean"
        };

        private static List<string> LastNames = new List<string> {
            "SMITH", "JOHNSON", "WILLIAMS", "BROWN", "JONES", "MILLER", "DAVIS", "GARCIA", "RODRIGUEZ", "WILSON", "MARTINEZ", "ANDERSON", "TAYLOR", "THOMAS HERNANDEZ",
            "RICHARDSON", "WOOD", "WATSON", "BROOKS", "BENNETT GRAY", "JAMES", "REYES", "CRUZ", "HUGHES", "PRICE", "MYERS", "LONG", "FOSTER SANDERS", "ROSS",
            "MORALES", "POWELL", "SULLIVAN", "RUSSELL ORTIZ", "JENKINS", "GUTIERREZ", "PERRY", "BUTLER", "BARNES FISHER", "HENDERSON", "COLEMAN", "SIMMONS", "PATTERSON",
            "JORDAN", "REYNOLDS"
        };

        public static List<Contact> GetContacts() {

            var random = new Random();
            List<Contact> contacts = new List<Contact>();

            for (int i = 0; i < 20; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="XamarinFormsFirstLook.ListPage2">
    <ContentPage.Content>
        <StackLayout Padding="40">
            <Label Text="Contacts" FontSize="20" />
            <ListView x:Name="ContactList" ItemsSource="{Binding Contacts}" ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout Padding="10">
                                    <StackLayout Orientation="Horizontal">
                                        <Label Text="{Binding FirstName}" FontSize="14" FontAttributes="Bold"
                                               TextColor="Blue" />
                                        <Label Text="{Binding LastName}" FontSize="14" FontAttributes="Bold"
                                               TextColor="Blue" />
                                    </StackLayout>
                                    <StackLayout Orientation="Horizontal">
                                        <Label Text="{Binding Email}" FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage2 : ContentPage
	{
	    public List<Contact> Contacts { get; set; }
	    
	    public ListPage2()
	    {
	        Init();
		}

	    private void Init()
	    {
            Contacts = DataGenerator.GetContacts();
            BindingContext = this;
            InitializeComponent();
	    }

	    private void OnItemTapped(object sender, ItemTappedEventArgs e)
	    {
            var contact = e.Item as Contact;
			DisplayAlert("Great!", contact.FirstName + " " + contact.LastName, "OK");
	    }
	}
}

List View (Grouping)

using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace XamarinFormsFirstLook.Model
{
    public class Grouping<K, T> : ObservableCollection<T> {
        public K Key { get; private set; }

        public Grouping(K key, IEnumerable<T> items) {
            Key = key;
            foreach (var item in items)
                Items.Add(item);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class DataGenerator
    {
        private static List<string> FirstNames = new List<string> {
            "Aiden", "Liam", "Lucas", "Noah", "Mason", "Ethan", "Caden", "Jacob", "Logan", "Jayden", "Elijah", "Jack", "Luke", "Michael", "Benjamin",
            "Alexander", "James", "Jayce", "Caleb", "Connor", "William", "Carter", "Ryan", "Oliver", "Matthew", "Daniel", "Gabriel", "Henry", "Owen",
            "Grayson", "Lincoln", "Jordan", "Tristan", "Jason", "Josiah", "Xavier", "Camden", "Chase", "Declan", "Carson", "Colin", "Brody", "Asher",
            "Jeremiah", "Micah", "Easton", "Xander", "Ryder", "Nathaniel", "Elliot", "Sean"
        };

        private static List<string> LastNames = new List<string> {
            "SMITH", "JOHNSON", "WILLIAMS", "BROWN", "JONES", "MILLER", "DAVIS", "GARCIA", "RODRIGUEZ", "WILSON", "MARTINEZ", "ANDERSON", "TAYLOR", "THOMAS HERNANDEZ",
            "RICHARDSON", "WOOD", "WATSON", "BROOKS", "BENNETT GRAY", "JAMES", "REYES", "CRUZ", "HUGHES", "PRICE", "MYERS", "LONG", "FOSTER SANDERS", "ROSS",
            "MORALES", "POWELL", "SULLIVAN", "RUSSELL ORTIZ", "JENKINS", "GUTIERREZ", "PERRY", "BUTLER", "BARNES FISHER", "HENDERSON", "COLEMAN", "SIMMONS", "PATTERSON",
            "JORDAN", "REYNOLDS"
        };

        public static List<Contact> GetContacts() {

            var random = new Random();
            List<Contact> contacts = new List<Contact>();

            for (int i = 0; i < 25; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }

        public static ObservableCollection<Contact> GetObservableContacts() {

            var random = new Random();
            var contacts = new ObservableCollection<Contact>();

            for (int i = 0; i < 25; i++) {
                Contact contact = new Contact();
                contact.FirstName = FirstNames [i];
                contact.LastName = LastNames [i];
                contact.Email = FirstNames [i] + "@gmail.com";
                contact.IsFavorite = random.Next(FirstNames.Count) % 2 == 0;
                contacts.Add(contact);
            }
            return  contacts;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ListPage3">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <ListView
                x:Name="ContactList"
                ItemsSource="{Binding .}"
                ItemTapped="OnItemTapped"
                IsGroupingEnabled="true"
                GroupShortNameBinding="{Binding Key}"
                HasUnevenRows="true">
                <ListView.GroupHeaderTemplate>
                    <DataTemplate>
                        <ViewCell
                            Height="30">
                            <StackLayout
                                VerticalOptions="FillAndExpand"
                                Padding="10"
                                BackgroundColor="Blue">
                                <Label
                                    Text="{Binding Key}"
                                    TextColor="White"
                                    VerticalOptions="Center" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.GroupHeaderTemplate>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            TextColor="Red" />
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            TextColor="Red" />
                                    </StackLayout>
                                    <Label
                                        Text="{Binding Email}"
                                        FontSize="10" />
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ListPage3 : ContentPage
	{
	    public ObservableCollection<Grouping<string,Contact>> ContactGroup;

	    public ListPage3() {
	        Init();
	        BindingContext = ContactGroup;
	        InitializeComponent();
	    }

	    private void Init()
	    {
	        var listOfContacts = DataGenerator.GetObservableContacts();

	        var sorted =
	            from c in listOfContacts
	            orderby c.FirstName
	            group c by c.FirstName[0].ToString()
	            into theGroup
	            select new Grouping<string, Contact>(theGroup.Key, theGroup);

	        ContactGroup = new ObservableCollection<Grouping<string,Contact>>(sorted);
	    }

	    private void OnItemTapped(object sender, ItemTappedEventArgs e)
	    {
	        var contact = e.Item as Contact;
	        DisplayAlert("Great!", contact.FirstName + " " + contact.LastName, "OK");
	    }
	}
}

List View (Item Trigger)

<?xml version="1.0" encoding="UTF-8"?>

<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="XamarinFormsFirstLook.ListPage4">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Label
                Text="Contacts"
                FontSize="20" />
            <ListView
                x:Name="ContactList"
                ItemsSource="{Binding Contacts}"
                ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding IsFavorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding IsFavorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                    </StackLayout>
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding Email}"
                                            FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>
using System.Collections.Generic;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class ListPage4ViewModel
    {
        public List<Contact> Contacts { get; set; }

        public ListPage4ViewModel()
        {
            Contacts = new List<Contact>();
            var listOfContacts = DataGenerator.GetContacts();
            Contacts = listOfContacts;

        }
    }
}
using System.Collections.Generic;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class ListPage4ViewModel
    {
        public List<Contact> Contacts { get; set; }

        public ListPage4ViewModel()
        {
            Contacts = new List<Contact>();
            var listOfContacts = DataGenerator.GetContacts();
            Contacts = listOfContacts;

        }
    }
}

Rest service

Package: Microsoft.Net.Http
Newtonsoft.Json

using System;

namespace XamarinFormsFirstLook.Model
{
    public class WeatherObservation
    {
        public string weatherCondition { get; set; }

        public string ICAO { get; set; }

        public long elevation { get; set; }

        public string countryCode { get; set; }

        public string cloudCode { get; set; }

        public long lng { get; set; }

        public long temperature { get; set; }

        public long dewPoint { get; set; }

        public long windSpeed { get; set; }

        public long humidity { get; set; }

        public string stationName { get; set; }

        public DateTime dateTime { get; set; }

        public long lat { get; set; }

        public long hectoPascAltimeter { get; set; }
    }
}
namespace XamarinFormsFirstLook.Model
{
    public class WeatherResult
    {
        public WeatherObservation weatherObservation { get; set; }
    }
}
using System;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Newtonsoft.Json;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
    public class RESTViewModel : INotifyPropertyChanged
    {
        private string station;

        public string StationName {
            get { return station; }
            set {
                station = value;
                NotifyPropertyChanged();
            }
        }

        private long el;

        public long Elevation {
            get { return el; }
            set {
                el = value;
                NotifyPropertyChanged();
            }
        }

        private long temp;

        public long Temperature {
            get { return temp; }
            set {
                temp = value;
                NotifyPropertyChanged();
            }
        }

        private long humid;

        public long Humidity {
            get { return humid; }
            set {
                humid = value;
                NotifyPropertyChanged();
            }
        }

        public async Task GetWeatherAsync(string url) {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(url);
            var response = await client.GetAsync(client.BaseAddress);
            response.EnsureSuccessStatusCode();
            var JsonResult = response.Content.ReadAsStringAsync().Result;
            var weather =
                JsonConvert.DeserializeObject<WeatherResult>(JsonResult);
            SetValues(weather);
        }

        private void SetValues(WeatherResult weather) {
            var stationName = weather.weatherObservation.stationName;
            var elevation = weather.weatherObservation.elevation;
            var temperature = weather.weatherObservation.temperature;
            var humidity = weather.weatherObservation.humidity;

            StationName = stationName;
            Elevation = elevation;
            Temperature = temperature;
            Humidity = humidity;
        }



        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") {
            if (PropertyChanged != null) {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.RESTPage">
    <ContentPage.Content>
        <StackLayout
            Padding="30">
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Latitude"
                    WidthRequest="130" />
                <Entry
                    x:Name="Lat"
                    WidthRequest="150" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Longitude"
                    WidthRequest="130" />
                <Entry
                    x:Name="Lon"
                    WidthRequest="150" />
            </StackLayout>
            <Button
                x:Name="Search"
                Clicked="OnClicked"
                WidthRequest="75"
                Text="Search"
                TextColor="White"
                BackgroundColor="Blue" />
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Location: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding StationName}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Elevation: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Elevation}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Temperature: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Temperature}" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Humidity: "
                    TextColor="Green"
                    WidthRequest="130" />
                <Label
                    Text="{Binding Humidity}" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace XamarinFormsFirstLook
{
	public partial class RESTPage : ContentPage
	{
	    RESTViewModel vm;

	    public RESTPage() {
	        vm = new RESTViewModel();
	        BindingContext = vm;
	        InitializeComponent();
		}

	    private async void OnClicked(object sender, EventArgs e)
	    {
	        var longitude = double.Parse(Lon.Text);
	        var latitude = double.Parse(Lat.Text);

	        var url = string.Format("http://api.geonames.org/findNearByWeatherJSON?lat={0}&lng={1}&username=tausiq", latitude, longitude);
	        await vm.GetWeatherAsync(url);
	    }
	}
}

SQLite database

Make sure you have package: sqlite-net-pcl in all projects

using System.Collections.Generic;
using System.Linq;
using SQLite;
using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook.Data
{
    public class ContactDatabase
    {
        SQLiteConnection database;
        static object locker = new object();

        public ContactDatabase() {


            database = DependencyService.Get<ISQLite>().GetConnection();

            database.CreateTable<Contact>();

        }

        public int SaveContact(Contact contact) {
            lock (locker) {
                if (contact.ID != 0) {
                    database.Update(contact);
                    return contact.ID;
                } else {
                    return database.Insert(contact);
                }
            }
        }

        public IEnumerable<Contact> GetContacts() {
            lock (locker) {
                return (from c in database.Table<Contact>()
                    select c).ToList();
            }
        }

        public Contact GetContect(int id) {
            lock (locker) {
                return database.Table<Contact>().Where(c => c.ID == id).FirstOrDefault();
            }
        }

        public int DeleteContact(int id) {
            lock (locker) {
                return database.Delete<Contact>(id);
            }
        }
    }
}
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;

namespace XamarinFormsFirstLook
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();

			MainPage = new NavigationPage(new XamarinFormsFirstLookPage());
		}

	    static ContactDatabase database;

	    public static ContactDatabase Database {
	        get {
	            if (database == null) {
	                database = new ContactDatabase();
	            }
	            return database;
	        }
	    }

	    protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ContactEntryPage">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Entry
                x:Name="FirstName"
                Placeholder="First Name" />
            <Entry
                x:Name="LastName"
                Placeholder="Last Name" />
            <Entry
                x:Name="Email"
                Placeholder="Email" />
            <StackLayout
                Orientation="Horizontal">
                <Label
                    Text="Favorite?" />
                <Switch
                    x:Name="IsFavorite" />
            </StackLayout>
            <StackLayout
                Orientation="Horizontal">
                <Button
                    x:Name="Save"
                    Text="Save"
                    Clicked="OnSave" />
                <Button
                    x:Name="Cancel"
                    Text="Cancel"
                    Clicked="OnCancel" />
                <Button
                    x:Name="Review"
                    Text="Review"
                    Clicked="OnReview" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ContactEntryPage : ContentPage
	{
	    private int updateID = 0;

	    public ContactEntryPage() {
			InitializeComponent();
		}

	    public ContactEntryPage(int id)
	    {
	        InitializeComponent();
	        var contact = App.Database.GetContect(id);
	        FirstName.Text = contact.FirstName;
	        LastName.Text = contact.LastName;
	        Email.Text = contact.Email;
	        IsFavorite.IsToggled = contact.IsFavorite;
	        updateID = id;
	    }

	    public void OnSave(object o, EventArgs e) {
	        Contact contact = new Contact();
	        contact.FirstName = FirstName.Text;
	        contact.LastName = LastName.Text;
	        contact.Email = Email.Text;
	        contact.IsFavorite = IsFavorite.IsToggled;
	        contact.ID = updateID;
	        Clear();
	        App.Database.SaveContact(contact);
	        Navigation.PopAsync(true);
	    }

	    private void OnCancel(object o, EventArgs e) {
	        Clear();
	    }

	    private void OnReview(object o, EventArgs e) {
	        Navigation.PopAsync(true);
	    }

	    private void Clear() {
	        FirstName.Text = LastName.Text = Email.Text = string.Empty;
	        IsFavorite.IsToggled = false;
	    }
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
	xmlns="http://xamarin.com/schemas/2014/forms"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	x:Class="XamarinFormsFirstLook.ContactListPage">
    <ContentPage.Content>
        <StackLayout
            Padding="40">
            <Label
                Text="Contacts"
                FontSize="20" />
            <Button Text="New Entry" Clicked="OnNewEntry" />
            <ListView
                x:Name="ContactList"
                ItemTapped="OnItemTapped">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <ViewCell.View>
                                <StackLayout
                                    Padding="10">
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding FirstName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding Favorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                        <Label
                                            Text="{Binding LastName}"
                                            FontSize="14"
                                            FontAttributes="Bold"
                                            TextColor="Blue">
                                            <Label.Triggers>
                                                <DataTrigger
                                                    TargetType="Label"
                                                    Binding="{Binding Favorite}"
                                                    Value="True">
                                                    <Setter
                                                        Property="TextColor"
                                                        Value="Red" />
                                                </DataTrigger>
                                            </Label.Triggers>
                                        </Label>
                                    </StackLayout>
                                    <StackLayout
                                        Orientation="Horizontal">
                                        <Label
                                            Text="{Binding Email}"
                                            FontSize="10" />
                                    </StackLayout>
                                </StackLayout>
                            </ViewCell.View>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

using System;
using System.Collections.Generic;

using Xamarin.Forms;
using XamarinFormsFirstLook.Model;

namespace XamarinFormsFirstLook
{
	public partial class ContactListPage : ContentPage
	{
		public ContactListPage() {
			InitializeComponent();
		}

	    public void OnItemTapped(object o, ItemTappedEventArgs e) {
	        var contact = e.Item as Contact;
	        Navigation.PushAsync(new ContactEntryPage(contact.ID));
	    }

	    protected override void OnAppearing() {
	        base.OnAppearing();
	        ContactList.ItemsSource = App.Database.GetContacts();
	    }

	    protected void OnNewEntry(object o, EventArgs e) {
	        Navigation.PushAsync(new ContactEntryPage());
	    }
	}
}

In iOS project,

using System;
using System.IO;
using SQLite;
using Xamarin.Forms;
using XamarinFormsFirstLook.Data;
using XamarinFormsFirstLook.iOS;

[assembly: Dependency(typeof(SQLite_IOS))]
namespace XamarinFormsFirstLook.iOS
{
    public class SQLite_IOS: ISQLite
    {
        public SQLite_IOS()
        {
        }

        public SQLite.SQLiteConnection GetConnection()
        {
            var sqliteFilename = "Contacts.db";
            //			string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
            //			string libraryPath = Path.Combine (documentsPath, "..", "Library"); // Library folder
            //			var path = Path.Combine(libraryPath, sqliteFilename);

            var path = "/users/shahab/Contacts.db";

            // This is where we copy in the prepopulated database
            if (!File.Exists(path))
            {
                File.Copy(sqliteFilename, path);
            }

            var conn = new SQLite.SQLiteConnection(path);

            // Return the database connection
            return conn;
        }
    }
}

Full Project

Full project can be downloaded from here

A Quick Review of C# 6.0


nameof

When we rename an identifier and the identifier name is referenced in a string then the effect of renaming won’t affect the string.

static void setUser(User user)
{
    if (user == null)
    {
        throw new ArgumentNullException("user", "User is null");
    }
}

Renaming user (#3) will not affect the string "user" (#5)

To resolve this issue, we can use nameof

static void setUser(User user)
{
    if (user == null)
    {
        throw new ArgumentNullException(nameof(user), "User is null");
    }
}

Type safety will be imposed if we use nameof

String interpolation

Old way

const string city = "Dhaka";
const string area = "Dhanmondi";
const string country = "Bangladesh";

var displayAddress = string.Format("Address: {0}, {1}, {2}", area, city, country);

New way

const string city = "Dhaka";
const string area = "Dhanmondi";
const string country = "Bangladesh";

var displayAddress = $"Address: {area}, {city}, {country}";

Another example

var formattedString = $"Today: {DateTime.Now.ToLongDateString()}\n" +
                      $"Dollar: {5:C}";

Console.WriteLine(formattedString);

/*
Today: Sunday, October 16, 2016
Dollar: $5.00
*/

Null conditional operator

Old way

int? age = (user == null) ? (int?) null : user.Age;

// This will crash if user == null
Console.WriteLine($"Name: {user.Fullname}");

New way

int? age2 = user?.Age;

// prints blank if user == null
Console.WriteLine($"Name: {user?.Fullname}");

// default value
int? age3 = user?.Age ?? 0;

// You can chain null checking
Console.WriteLine($"Length: {user?.Fullname?.Length}");

Index initializer

Old way

var dict = new Dictionary<string, string>()
{
    { "Name", "John Doe" },
    { "Profession", "Soft Engg."}
};

New way

var newDict = new Dictionary<string, string>()
{
    ["Name"] = "New John Doe",
    ["Profession"] = "New Soft Engg."
};

Method extension

Suppose we have a class called UserDB

using System.Collections;
using System.Collections.Generic;

namespace AQuickReviewCSharp6
{
    public class UserDB : IEnumerable<User>
    {
        List<User> users = new List<User>();

        public IEnumerator<User> GetEnumerator()
        {
            return users.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public User Insert(User anUser)
        {
            users.Add(anUser);
            return anUser;
        }
    }
}

Notice that, there is no Add method. Now, if we would like to make an UserDB object and use index initializer then we will get error.

var userCollection = new UserDB()
{
    new User { Fullname = "User 01", Age = 25 },
    new User() { Fullname = "User 02", Age = 30 }
};

Cannot resolve symbol 'Add'

To resolve this we can use extension and add a new method named Add

static class UserDBExtension
{
    public static User Add(this UserDB db, User anUser)
    {
        db.Insert(anUser);
        return anUser;
    }
}

await in catch and finally block

private static async void AMethod()
{
    try
    {
        throw new Exception("Error");
    }
    catch (Exception ex)
    {
        await log("Catch: ", ex);
    }
    finally
    {
        await log("Finally: ", null);
    }
}

private static async Task log(String log, Exception ex)
{
    using (var file = File.AppendText("app.log"))
    {
        await file.WriteLineAsync($"{log} {ex?.ToString()}");
    }
}

Exception filter

You can add exception filter, pretty much like if-else if-else

try
{
    throw new Exception("Error");
}
catch (Exception ex) when (ex.Message.Contains("Warning"))
{
    // Just an warning
}
catch (Exception ex)
{
    // Handle exception
}
finally
{
    Console.WriteLine("Finally");
}

Remember: You need to return a boolean (true) if you handled the case, so that further catch clauses will not be executed.

Auto property initializer

We can initialize a property without using constructor.

public class User
{
    public string Fullname { get; set; } = "Great user";
    public int Age { get; set; } = 20;
}

This is also applicable for getter only properties

public class User
{
    public string Fullname { get; set; } = "Great user";
    public int Age { get; set; } = 20;
    public string Country { get; } = "Australia";
}

Few short hand techniques

Old way

static private string name = "John Doe";

static public string Name
{
    get { return name; }
}

New way

static public string Name = "John Doe";

Old way

static public string GetFullName(string firstName, string lastName)
{
    return String.Format("{0} {1}", firstName, lastName);
}

New way

static public string GetFullName(string firstName, string lastName) => $"{firstName} {lastName}";

Old way

static public User GetUser(string firstName, string lastName)
{
    return new User(firstName, lastName);
}

New way

static public User GetUser(string firstName, string lastName) => new User(firstName, lastName);

static using

using System;
using static System.Console;

public static void Main(string[] args)
{
    WriteLine("Hello World");
}

Android: Gradle First Look


Introduction

Gradle favors convention over configuration. It means, Gradle provides default values for settings and properties. This makes Gradle very easy to get started with. However, if you would like to change/override Gradle default settings and properties, you can do that easily.

Gradle uses Groovy DSL (Domain Specific Language) as it’s configuration lanugage. Groovy is a dynamic language for the Java Virtual Machine (JVM).

Gradle supports three different kinds of repositories.

  1. Maven
  2. Ivy
  3. Static files (mostly *.jar or .aar)

Dependencies are fetched from repositories during the execution phase. Gradle keeps a local cache, so a particular dependency will be downloaded for once only.

Gradle also allows you to build other than Java projects. If you want to manage your JS/C++ projects you can do that using Gradle.

We only need to say what we need, not how to achieve it and Gradle will make it happen. For example, we can add a single line to our build file and Gradle will download the dependency from a remote repository and also sub dependencies and it will make sure all the classes are available to our project.

Installation

Download Gradle from, https://gradle.org/gradle-download/
Make sure to add the Gradle/bin path to your Environment variable.

In MacOS, if you have homebrew installed, then you can run the following command,

~$ brew update
~$ brew install gradle

First task

Let’s create our first task in gradle.

task firstTask {
	println "Hello Gradle"
}

Now we will run our first task.

~$ gradle firstTask
Starting a Gradle Daemon (subsequent builds will be faster)
Hello Gradle
:firstTask UP-TO-DATE

BUILD SUCCESSFUL

Total time: 3.838 secs

All available tasks

~$ gradle tasks
Hello Gradle
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Temp'.
components - Displays the components produced by root project 'Temp'. [incubating]
dependencies - Displays all dependencies declared in root project 'Temp'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Temp'.
help - Displays a help message.
model - Displays the configuration model of root project 'Temp'. [incubating]
projects - Displays the sub-projects of root project 'Temp'.
properties - Displays the properties of root project 'Temp'.
tasks - Displays the tasks runnable from root project 'Temp'.

Other tasks
-----------
firstTask

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 1.008 secs

Build a simple Java project

  1. Create this project structure, /SimpleJava/src/main/java/com/genericslab/simplejava
  2. Create a Java file inside simplejava folder
  3. Create a build.gradle file inside SimpleJava fodler, parallel with src folder.
package com.genericslab.simplejava;

public class Main {
	public static void main (String... args) {
		System.out.println("Hello Java!!!");
	}
}
apply plugin: 'java' 

After this, run the ~ $ gradle tasks command again and see the avialable tasks.

~$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the main classes.
testClasses - Assembles test classes.

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'SimpleJava'.
components - Displays the components produced by root project 'SimpleJava'. [incubating]
dependencies - Displays all dependencies declared in root project 'SimpleJava'.
dependencyInsight - Displays the insight into a specific dependency in root project 'SimpleJava'.
help - Displays a help message.
model - Displays the configuration model of root project 'SimpleJava'. [incubating]
projects - Displays the sub-projects of root project 'SimpleJava'.
properties - Displays the properties of root project 'SimpleJava'.
tasks - Displays the tasks runnable from root project 'SimpleJava'.

Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.

Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 1.657 secs

As you can see, we have got a number of additional Build Tasks because we had added java plugins.
Let’s run ~ $ gradle build

~$ gradle build
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

Total time: 1.448 secs

A build directory has been generated. You can find a Main.class file in the following directory,
~SimpleJava/build/classes/main/com/genericslab/simplejava

Let’s run it.

~$ java -cp build/classes/main/ com.genericslab.simplejava.Main
Hello Java!!!

Run build with a specific version of Gradle (Gradle Wrapper)

You need to have Gradle already installed.

apply plugin: 'java'

task wrapper(type: Wrapper) {
	gradleVersion = '2.6'
}
~$ gradle wrapper

After running the wrapper task, you will see a folder named gradle and a script file named gradlew and a .bat file named gradlew.bat

From now on, you need to use gradlew instead of gradle to use the particular gradle version 2.6. Any further command started with gradlew will first install the Gradle version 2.6 (if not installed already).

If you have built an application that need to use a particular Gradle version, or you might want to run the application without any hassel in other machine then it is a preferable way to use a wrapper.

Tasks

Task is the unit that Gradle executes. Each task has a lifecycle and may contain properties. Task can also contain dependencies of other tasks.

Let’s create a task

// project level task 
project.task "TaskA"


// in theory, it is a local level task 
// however, practically it is same as before 
// because we are now in project context 
task "TaskB"

// We can add description of a task 
TaskB.description = "This is a description for TaskB"

// Action of a task 
TaskA {
	doLast {
		println "Action#1 for TaskA"
	}
}

// We can define the task and define action together
task "TaskC" {
	doLast {
		println "Action#1 for TaskC"
	}
}

// If we define multiple actions inside a task, 
// actions will be appended
TaskA {
	doLast {
		println "Action#2 for TaskA"
	}
}

// define, description and actions all in one 
task "TaskD" {
	description "This is a description for TaskD"
	doLast {
		println "Action#1 for TaskD"
	}
}

Run ~$ gradle tasks in command line.

~$ gradle tasks
:tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Temp'.
components - Displays the components produced by root project 'Temp'. [incubating]
dependencies - Displays all dependencies declared in root project 'Temp'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Temp'.
help - Displays a help message.
model - Displays the configuration model of root project 'Temp'. [incubating]
projects - Displays the sub-projects of root project 'Temp'.
properties - Displays the properties of root project 'Temp'.
tasks - Displays the tasks runnable from root project 'Temp'.

Other tasks
-----------
TaskA
TaskB - This is a description for TaskB
TaskC
TaskD - This is a description for TaskD

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

BUILD SUCCESSFUL

Total time: 0.852 secs

Task Dependencies

// define, description and actions all in one 
task "TaskD" {
	description "This is a description for TaskD"
	doLast {
		println "Action#1 for TaskD"
	}
}

// TaskA is dependent on TaskC
// means, TaskC will auto executed when we run TaskA 
TaskA.dependsOn TaskC 

// one task must execute after another task 
TaskB .mustRunAfter TaskA 

// one task should execute after another task 
// avoids circular dependencies 
TaskB.shouldRunAfter TaskA, TaskB 

/*
Remember, mustRunAfter and shouldRunAfer will not kick in 
automatically. If we run both tasks together, or, the tasks
have dependencies on one another, only then those two 
keywords will be meaningful. 

What if we would like to run a task after another task, 
even we don't call it separately, or don't have dependencies.
Similar to final block, we can use finalizedBy 
*/

// might be very usefule for db migration 
// after the migration you might want to run a task for cleanup 
TaskB.finalizedBy TaskC 

Run ~$ gradle TaskA

~$ gradle TaskA
:TaskC
Action#1 for TaskC
:TaskA
Action#1 for TaskA
Action#2 for TaskA

BUILD SUCCESSFUL

Total time: 0.908 secs

Define properties

 
def buildName = "Awesome-20160902a"
println "Build name: $buildName"

// global scope
project.ext.versionName = "Awesome=20160902b"
println "Version name: $project.ext.versionName"


<h3>Use built-in task: Copy</h3>


task copyFiles (type: Copy) {
	exclude 'file1.txt', 'file2.txt' // do not copy these files
	from 'src'  // define the source folder 
	from 'dest' // define the destiantion folder 
}

// this can be re-written to 

def spec = copySpec {
	exclude 'file1.txt', 'file2.txt' // do not copy these files
	from 'src'
}

task copyFilesAgain (type: Copy) {
	with spec 
	into 'dest' 
}

// another spec variable 
def spec = copySpec {
	exclude {
		// iterator: it 
		// exclude all pngs 
		it.file.name.endsWith("png")
	}
	from 'src'
}

Sourceset

Gradle Android projects follows this folder structure:

src/main/java
src/main/res
src/main/jniLibs
src/androidTest/java
src/test/java

if you do not like to change your current folder structure then you can tell Gradle where to look for specific files

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        androidTest.setRoot('tests')
    }
}

Gradle daemon

Everytime we run ~$ gradle build, Gradle launches JVM and starts from the beginning. Instead if Gradle could run as a service and could reuse already runned JVM then it would have been great!

Voila! Gradle can do that and it's called daemon.

Run ~$ gradle --daemon build and you might be prompted to give a permission and gradle daemon will be started.

If you would like to run --daemon all the time, instead of per command basis then write the following code,

or.gradle.daemon=true

in your project's gradle.properties file. That will ensure daemon will run on your project.

If you would like run daemon irrespective of projects, that means for all projects, then add the line in your ~/.gradle/gradle.properties file.

Android: Instrumentation Testing using Espresso


Introduction

Android provides a number of extra components beyond Java, for example, Activity, Service etc. Testing these extra components you will be required Instrumentation testing and it needs to be run on device/emulators. Espresso is an official instrumentation testing framework by Google.

Installation

Add this line in app level build.gradle in dependencies

androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'

add this line inside defaultConfig

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

For more information,

  1. Android dev
  2. Google github

Project Structure

An androidTest folder should automatically be generated when you created the Android application. For example,

In Android view,

Screenshot at Sep 15 11-44-37.png

Or, in Project view,

Screenshot at Sep 15 11-46-31.png

If not,

  1. Create a folder named androidTest inside src
  2. Create a folder named java inside androidTest

Now we will create our first test class.

  1. Go to the MainActivity.java class and click on MainActivity class name
  2. Select Navigate (from menu)
  3. Select Test (Shift + Cmd + T)
  4. Select, Create New Test…

Select JUnit4 and the dialog should look like this,

Screenshot at Sep 15 11-56-52.png

Click OK.

Check the correct directory is selected. We need to select androidTest directory,

Screenshot at Sep 15 11-57-34.png

Click OK.

Now Sync Gradle.

If you get the following error,

Error:Conflict with dependency 'com.android.support:support-annotations'. Resolved versions for app (24.2.1) and test app (23.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.

The add the following line in dependencies

androidTestCompile 'com.android.support:support-annotations:24.2.1'

Note that the above line version number need to match with the expected version number indicated with the error.

Now let’s go to the newly created MainActivityTest.java


package com.genericslab.espressodemo;

import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    // This will launch the MainActivity before testing each method/case.
    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

}

Now we will write our first test case

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    // This will launch the MainActivity before testing each method/case.
    @Rule
    public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testCase1() {
        // Find a view with id = R.id.text
        // Check the text of that view matches with string = R.string.app_name
        onView(withId(R.id.text)).check(matches(withText(R.string.app_name)));
    }
}

Now Right click on the file MainActivityTest.java from project explorer and select “Create MainActivityTest…” -> OK.
Click on Run.

Now we will add our second test case

@Test
public void testCase2() {

    // Open options menu, whether as overflow or using a physical button
    // This will open the option menu as a pop up menu. Next we will click on an item.
    // If you need context then pass, InstrumentationRegistry.getTargetContext()
    openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());

    // From the options menu, we are going to click on an item having text = R.string.label_help
    onView(withText(R.string.label_help)).perform(click());

    // alternatively, you can leverage id property.
    onView(withId(R.id.menu_help)).perform(click());

    // verifying
    onView(withId(R.id.text)).check(matches(withText(R.string.label_updated)));
}

Android: SharedPreferences


There are several data storage options in Android. Such as,

  1. Shared Preferences
    • Stores primitive data types (int, String, float, boolean)
    • Stores as key-value pair
    • Not accessible to other applications
  2. Internal Storage
    • Stores data inside apps private storage
    • Not accessible to other applications
  3. External Storage
    • Stores data on shared external storage (SD Card)
    • Accessible to other applications/user
  4. SQLite Database
    • Stores structured data in apps private storage
    • Not accessible to other applications in general, but can be shared using ContentProviders.
  5. Network
    • Stores data in your own/company server
    • You need an active network connection for accessing/storing the data

We have two options to get the SharedPreferences object,

  1. getPreferences(int mode)
  2. getSharedPreferences(String name, int mode)

There is only one valid value for int mode and that is Context.MODE_PRIVATE

Previously, there were other valid values, such as Context.MODE_WORLD_READABLE and Context.MODE_WORLD_WRITEABLE, but these values got deprecated in API 17 and will throw a SecurityException from Android N.

If we use Context.MODE_PRIVATE then it means, no other apps will be allowed to access our shared preference values.

getPreferences

If we use getPreferences(int mode) then an XML file will be created by name of the Activity and it’s access level will be within the Activity. Separate XML files will be created for each Activity.

getSharedPreferences

If we use getSharedPreferences(String name, int mode) then an XML file will be created by name of String name and it’s access level will be within the Application (i.e any Activity can access the values). If you use a different name then a different XML by that name will be created.

Eaxmple#1

private void saveDataInActivitySharedPreferences() {
    SharedPreferences sharedPrefs = getPreferences(Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPrefs.edit();

    editor.putString("key_string", "value_string");
    editor.putBoolean("key_boolean", true);
    editor.putInt("key_int", 5);

    editor.apply();
    // apply will not return any value and work asynchronously

    // or you could call, editor.commit();
    // commit returns boolean based on un/successful operation and works synchronously
}

private void loadDataFromActivitySharedPreferences() {
    SharedPreferences sharedPrefs = getPreferences(Context.MODE_PRIVATE);

    String valueString = sharedPrefs.getString("key_string", "Default value");
    boolean valueBoolean = sharedPrefs.getBoolean("key_boolean", false);
    int valueInt = sharedPrefs.getInt("key_int", 0);

    String logMsg = valueString + " " + valueBoolean + " " + valueInt;

    Log.d("DEBUG_TAG", logMsg);
}

You can see the XML file content by selecting Tools -> Android -> Android Device Monitor -> (Tab) File Explorer -> data -> data -> APP_PACKAGE_NAME -> shared_prefs -> ACTIVITY_NAME.xml

File content should like below,

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="key_string">value_string</string>
    <boolean name="key_boolean" value="true" />
    <int name="key_int" value="5" />
</map>

If you tap on CLEAR DATA from Settings then this fill will be deleted. DB and Cache files will be deleted as well.

We can not load the values from another Activity because the created file has Activity level access. If we want to access the values from another Activity then we need to call getSharedPreferences instead of getPreferences. Remember that, in case of getSharedPreferences too we have only one value value for int mode = Context.MODE_PRIVATE

Example#2

editor.remove("key_string");
// the key and the associated value will be deleted.
editor.apply();
// do not forget to call apply() method.

editor.clear();
// clear all the data, but the XML file will not be deleted.
editor.apply();
// do not forget to call apply() method.

Demo contacts for Android emulator/genymotion


When we create an emulator or genymotion device, it is kind of blank. What if we need a list of contacts to experiment with. In that case we have two options

  1. We can use our PERSONAL device. urgh!
  2. We can insert a bunch of demo contacts into emulator/ genymotion.

Cons

What if we accidentally delete/call/send text to our personal contacts? shoot!

Or, we might need to discard the emulator/genymotion and create a new one. In that case all our demo data will be gone!

Besides, our demo data will always look like a DEMO data. I mean, anybody can take a look at our contacts list and can identify the data are dummy.

Solution

I have created some dummy data (which would look like real data to most of sane human beings, hopefully) and exported the contacts into a .vcf file format. Anybody can transfer the file into your emulator/genymotion and import the file from contacts app.

And voila! you will get a bunch of contacts (52 contacts as of now). I have also post the file in github repository and of course you will get the latest data from there.

Github repo: github.com/tausiq/demo-contacts-for-Android

Contacts.vcf: https://github.com/tausiq/demo-contacts-for-Android/blob/master/contacts.vcf

device-2016-05-10-195347.png

device-2016-05-10-195417.png

Data source: http://www.fakenamegenerator.com

Swift 2: Beyond the first look


Version:

I am using Apple Swift version 2.2 (swiftlang-703.0.18.8 clang-703.0.31)

How do I know which Swift version I am using?
Run the command in Terminal,

xcrun swift -version

Swift is a type-safe language. It infers data types from default value provided for variable/constant.

Variable

Each variable need an initial value OR have to be declared with a type.

var aStringVariable = "Hello world"
var anotherStringVariable: String
var anIntVariable: Int                  // 64-bit signed integer
var anInt8Variable: Int8                // 8-bit signed integer
var anInt16Variable: Int16              // 16-bit signed integer
var anInt32Variable: Int32              // 32-bit signed integer
var anInt64Variable: Int64              // 64-bit signed integer
var anUnsignedIntVariable: UInt         // 64-bit unsigned integer
var anUnsignedInt8Variable: UInt8       // 8-bit unsigned integer
var anUnsignedInt16Variable: UInt16     // 16-bit unsigned integer
var anUnsignedInt32Variable: UInt32     // 32-bit unsigned integer
var anUnsignedInt64Variable: UInt64     // 64-bit unsigned integer
var aDoubleVariable: Double
var aFloatVariable: Float
var aBooleanVariable: Bool
var aCharacterVariable: Character

Constant

Constant starts with ‘let’ keyword in Swift. Constant value can be set after the declaration, but only once.

let aConstant = 32
let anotherConstant: Int
anotherConstant = 64

Using ‘let’ is highly recommended whenever possible. Besides type safety there are some internal perfomance optimization by Swift compiler.

Conditional statement basics

  • Curly braces are REQUIRED, even if there is a single statement.
  • Parenthesis are not needed around the condition.
  • Pre-increment/decrement is deprecated and will be removed in Swift 3. (Post-increment/decrement too)

If-else condition

let x = 5

if x < 5 {
    print("x < 5")
} else if x == 5 {
    print("x == 5")
} else {
    print ("x >= 5")
}

While loop

var index = 0
let x = 5

while index < x {
    index += 1      // index++ is deprecated
}

For loop

for i in 0 ... 10 { // for (var i = 0; i <= 10; i++ )
    print("i = \(i)")
}

for i in 0 ..< 10 { // for (var i = 0; i < 10; i++ )
    print("i = \(i) and i * i = \(i * i)")
}

Do while loop

var index = 0
let x = 5

repeat {
    index += 1
} while index < x

Optional basics

  • Variable/constant has to be intialized before used. Otherwise it will produce compile error
  • Optional variable/constant can have a value or it will be ‘nil’, no exception
  • Optional variable/constant is strongly typed too. Either contain a valid value or ‘nil’
  • Opitonal variable/constant can be set to ‘nil’ explicitely
  • Optional variable/constant need to be unwrapped before use. Before unwrap you need to be sure it has a value.
var optionalString: String?
var optionalInt: Int?

if optionalInt != nil {
    var anIntVariable = optionalInt! // unwrapping
    print (anIntVariable)
}

// OR

if let anIntVariable = optionalInt {
    // execution will be here iff optinalInt != nil
    print(anIntVariable) // by default unwrapped
} else {
    print("optionalInt is nil")
}

String format

let a = 5
let b = "World"
let c = 3.6

print("Hello \(a) and \(b) but \(c)")

Function basics

  • Function params are by default constant.
  • On calling a function, you need to specify the name of all variable as key:value (except the first one)
func foo() {
    // no params, no return type
}

func boo() -> String {
    return ""
    // no params, String return type
}

func coo(first: String) -> String {
    return first
    // one String param, String return type
}

func doo(first: String, second: Int) -> Int {
    return second
    // one String param, one Int param, Int return type
}

func moo(first: String, second: Int, third: Int = 2) -> Int {
    return third
    // Default param third set to 2
}

func koo(first: String) {
    // first = "Haha" // Error: params are constant
    // var first: String will make it a varaible
}

foo()
boo()
coo("Haha")
doo("Haha", second: 5) // Error: doo("Haha, 5)
moo("Haha", second: 5) // omit the default param
moo("Haha", second: 5, third: 3) // default param value

Class

  • Instance variable need to initialized with default value OR the class need to have a constructor
  • Constructor is a special function with name ‘init’
  • Current instance reference is ‘self’
class Person {
    var firstName: String = "Sherlock"
    var lastName: String = "Holms"
    var age: Int
    
    init() {
        // Constructor
        self.age = 50
    }
    
    // Method
    func getDescription() -> String {
        return "FirstName: \(self.firstName) and LastName: \(self.lastName) and Age: \(self.age)"
    }
}

var p = Person()    // Creating object
print("FirstName: \(p.firstName)")
print(p.getDescription())

instanceof OR is of type

class Person {
    var firstName: String = "Sherlock"
    var lastName: String = "Holms"
}

class Student: Person {
    var id: String = "0123456789"
}

var s = Student()

if s is Person {
    print("s is a Person too")
    
    var p = s as Person // casting to Person
    print(p.firstName)
    
} else {
    print ("This will not be executed")
}