Exercise 4: Clean up and complete a Xamarin.iOS binding project (IOS451)
The primary goal of this lab is to create and clean up the binding definition files created from a static Xcode library using Objective Sharpie and complete a Xamarin.iOS binding project using Visual Studio.
If you haven't already, you will need to download Objective Sharpie. Additionally, you will need to complete this exercise on a Mac running macOS 10.10 or newer for compatiblity with Objective Sharpie.
To complete the exercise, you will need Visual Studio for Windows or macOS with the Xamarin development tools installed. You will also need either an emulator/simulator or a device to run the exercise on. Please see the setup page if you need help installing the Xamarin development environment. For compatibility with Objective Sharpiew, you will need a machine running macOS 10.10 or newer.
Create API definition for WeatherGadget
Using a macOS machine, we will create the binding API definition files using the provided WeatherGadget library in the Exercise 4 > Assets folder of your copy of the cloned or downloaded course materials.
- Create a folder for you exercise content.
Note: there are versions of Xamarin.iOS that will not handle iOS binding projects correctly when the path contains spaces. If you can avoid spaces in your working path, it might be worth doing so for this exercise.
- Copy the WeatherGadget asset folder to your new exercise folder.
- Use Objective Sharpie to manually bind the WeatherGadget header files.
Run the following command in your exercise folder. It is broken into multiple lines for easier legibility; make sure to copy the whole command.
sharpie bind -output WeatherGadgetOut -namespace WeatherGadgetSDK \
-sdk iphoneos11.4 -scope WeatherGadget.framework/Headers \
WeatherGadget.framework/Headers/WeatherGadget.h
You may need to adjust the-sdk
parameter to match an installed SDK version on your PC. If you are unsure what SDKs you have installed, you can list available Xcode SDKs withsharpie xcode -sdks
.
Create Xamarin.iOS bindings library
Next, we will create a bindings library to contain our generated API definition.
With our binding API definition, you could now take the resulting files and the original WeatherGadget library from the Exercise 4 > Assets to Visual Studio on Windows or macOS for the remainder of this exercise.
You will still require a macOS build host when using Visual Studio on Windows.
- Create a new project from the File > New > Project... menu item.
- From the New Project window, select the iOS Bindings Library (Xamarin) template from the Visual C# > iPhone & iPad section.
- Create a new project from the File > New Solution... menu item.
- From the New Project window, select the Bindings Library template from the iOS > Library section.
- Name the project "WeatherGadgetSDK".
Import WeatherGadget API definition
- Replace the contents of the binding library's ApiDefinition.cs template-generated file with the contents of the Objective Sharpie-generated ApiDefinitions.cs file.
- Check and clean up any
[Verify]
attributes, if any were generated.
- Right-click the Native References section in the Solution Explorer and choose Add Native Framework Reference.
- Right-click the Native References section in the Solution pad and choose Add Native Reference.
- Navigate to the Exercise 4 > Assets folder and select the WeatherGadget.framework folder as a native reference.
The WeatherGadget.framework containts the static WeatherGadget binary. The library is automatically loaded by adding the framework as a Native Reference. Alternatively, you can also copy and rename WeatherGadget to WeatherGadget.a and add it as a Native Reference.
- Build the library to make sure it compiles successfully.
Create Xamarin.iOS application to test the binding
Now, we will create a Xamarin.iOS application that we can use to consume and test out our binding.
- Right-click the solution node in the Solution Explorer and click Add > New Project....
- Create a new Single View App project from the Visual C# > iPhone & iPad > iOS App (Xamarin) template.
- Name your new iOS app "WeatherGadgetApp" and click OK to make your new iOS app project. You can leave the defaults for Device Support and Minimum iOS Version for this exercise.
- Right-click your new project's References node and select Add Reference....
- Add a project reference to the WeatherGadgetSDK project and click OK.
- Right-click the solution node in the Solution pad and click Add > Add New Project....
- Create a new Single View App project from the iOS > App template section.
- Name your new iOS app "WeatherGadgetApp" and click Next. You can leave the remaining fields as their defaults for this exercise.
- Click Create to make your new iOS app project.
- Right-click your new project's References node and select Edit References....
- Add a project reference to the WeatherGadgetSDK project and click OK.
Verify the WeatherGadgetSDK binding in your iOS app
Now, we can test the bindings library is working correctly in the new iOS app.
- In your app view controller's
ViewDidLoad
method, create an instance of theWeather
type. - Set the
CurrentTemperature
property to99f
. - Call
Debug.WriteLine
with your instance variable'sCurrentTemperature
property to see if the value was set properly.
public override void ViewDidLoad() {
base.ViewDidLoad();
Weather myWeather = new Weather();
myWeather.CurrentTemperature = 99f;
Debug.WriteLine($"Temperature: {myWeather.CurrentTemperature}");
}
We can also test out the WeatherGadgetDelegate
class.
- Create a new
GadgetDelegate
class in the iOS app which inherits from theWeatherGadgetDelegate
class. - Implement the required delegate member
DidFetchWeather
. When implementing the member, make sure to check theNSError
parameter isnull
. - Call
Debug.WriteLine
to report the value of the returnedCurrentTemperature
.
using System.Diagnostics;
using Foundation;
using WeatherSDK;
namespace WeatherGadgetApp {
public class GadgetDelegate : WeatherGadgetDelegate{
public override void DidFetchWeather(Weather weather, NSError withError) {
if (withError == null) {
Debug.WriteLine($"Delegate Answering: {weather.CurrentTemperature}");
}
}
}
}
To test the delegate, we need to create a new GadgetDelegate for the WeatherGadget we created earlier.
- Back in your app view controller's
ViewDidLoad
method, create an instance ofGadgetDelegate
. - Set the
Delegate
property to the new GadgetDelegate instance. - Invoke the
FetchWeather
method on the WeatherGadget instance to test the delegate implementation.
public override void ViewDidLoad() {
base.ViewDidLoad();
...
WeatherGadget wGadget = new WeatherGadget();
wGadget.Delegate = new GadgetDelegate();
wGadget.FetchWeather();
}
- Run the application to make sure the expected
Debug
statements are logged.
If you followed along with the provided code, you should see the following output:
[0:] Temperature: 99
[0:] Delegate Answering: -20
Note: If your iOS app isn't building due to missing namespaces and classes from the API definition, you may be running a version of Xamarin.iOS that will not handle iOS binding projects correctly when the path contains spaces. Try moving your exercise code to a path without spaces and try again.
Exercise summary
In this exercise you created and cleaned up the binding definition files for a static Xcode library using Objective Sharpie. You then used the API definition files in a Xamarin.iOS binding project and tested this new bindings library in a Xamarin.iOS project.
You can view the completed solution in the Exercise 4 > Completed folder of your copy of the cloned or downloaded course materials.