XHackers Team: Xamarin C# binding of a Cocoapods iOS SDK using Objective Sharpie

In this blog post, Let’s see how to generate Xamarin C# binding of IBM MobileFirst Foundation iOS Cocoapods SDK using Objective Sharpie.

Binding

Post my endeavour with Xamarin.Android Bindings  and Xamarin Apps with IBM MobileFirst, I received an interesting requirement from my colleague Chethan. He wants a Xamarin C# binding of our IBM MobileFirst Foundation Objective-C APIs. I thought this is an opportunity to try something new and accepted the challenge.

I immediately started exploring to find something called Objective Sharpie on Xamarin’s Objective-C binding page. While reading through the documentation, I found one more interesting scenario which will simplify my binding effort i.e., Effective version 3.0, Objective Sharpie supports binding CocoaPods.

Yay!! We already have IBM MobileFirst Platform Foundation iOS SDK available on Cocoapods and now it’s time to follow the steps mentioned in the documentation.

The first step is to download, setup and update objective Sharpie. Once we are all good, Our journey begins  towards achieving Xamarin C# binding.

Run the below command on a terminal.

$ sharpie pod init ios IBMMobileFirstPlatformFoundation

If all goes well, Here’s the expected output

Setup completed

** Searching for requested CocoaPods ...

** Working directory:

**   - Writing Podfile ...

**   - Installing CocoaPods ...

**     (running `pod install --no-repo-update`)

Analyzing dependencies

Downloading dependencies

Installing IBMMobileFirstPlatformFoundation (8.0.2016061012)

Generating Pods project

Sending stats

Pod installation complete! There is 1 dependency from the Podfile and 1 total pod

installed.

** ??  Success! You can now use other `sharpie pod` commands.

Success ! There’s one more command before we see the binding,

$ sharpie pod bind

Possible Errors & their fix:

Commands can go good and at the same time can error-out. In my case, there were a bunch of errors.

xcodebuild[56779:791166] [MT] PluginLoading: Required plug-in compatibility UUID ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C for plug-in at path '~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Unity4XC.xcplugin' not present in DVTPlugInCompatibilityUUIDs

xcodebuild[56779:791166] Failed to load plugin at: /Users/VMac/Library/Application Support/Developer/Shared/Xcode/Plug-ins/Unity4XC.xcplugin, skipping.  Reason for failure: *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]

User defaults from command line:

IDEDerivedDataPathOverride = /Users/VMac/Pods/sharpie-build

=== BUILD TARGET Pods-ObjectiveSharpieIntegration OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies

Code Sign error: No code signing identities found: No valid signing identities (i.e. certificate and private key pair) were found.

** BUILD FAILED **

The following build commands failed:

Check dependencies

(1 failure)

error: xcodebuild did not run successfully (exit code: 65)

No worries! We can fix the error in multiple ways,

  1. As the issue is with unity plugin, We can uninstall unity from the Mac and install again. If that doesn’t fix the error,
  2. Navigate to ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ folder and delete the plugin if the plugin is not in use.

There’s also a chance that the Cocoapods iOS SDK expects a lower iPhoneOS SDK like the error below,

** BUILD SUCCEEDED **

Submitting usage data to Xamarin...

Submitted - thank you for helping to improve Objective Sharpie!

Done. Exiting with error code 1.

error:  framework requires SDK 'iphoneos9.2' which is not installed. You may need a newer Xcode.

In reality, We may see SDK version higher than the one mentioned in the error description and our Xcode is up to date. To fix the error,

  • Download the version of Xcode with the SDK version you are looking for.
  • Right click on the Xcode_ .dmg file and Select “Show Package Contents” from the menu.
  • Now navigate to Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ and copy iPhoneOS<Version_number>.SDK folder.
  • Paste the copied folder to
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/

If all goes well, You should see a lengthy output on the terminal + a couple of warnings with a word Done. You should see the below binding files once you navigate to the base folder.

Binding output

Note: You can follow the above steps to generate Xamarin C# binding for any Cocoapods iOS SDK.

If you see any errors, post the same as a comment below.

Gerald Versluis: Spicing up your Xamarin (Forms/iOS) TabBar

One of the most popular navigation patterns on all platforms is by making use of the TabBar. Xamarin.Forms already acknowledged this by incorporating the TabbedPage in their default control set. While the tabs are platform independent – besides from the look on the specific platform – I want to talk a little bit about the iOS part specifically.

When I first started out with Xamarin and Forms I just put in the TabbedPage, specify some icons and be done with it. But looking at other iOS apps, mine always seemed to be odd. Soon I figured out why; on iOS a selected tab has a selected icon which is typically a filled icon. Let’s have a look.

TabBar Icons
TabBar Icons

This is how a TabBar icon and selected TabBar icon looks like in default Xamarin.Forms with iOS. If we compare this to the TabBar in the iOS App Store app we notice the difference immediately. It has filled icons! So how can we achieve this in our app?

AppStore TabBar icons
AppStore TabBar icons

Diving into this I quickly came across some Apple documentation which told me that it can be done out of the box on iOS with the selectionIndicatorImage property. So Xamarin Forms probably lacks the possibility due to the fact that only the most multi-platform features are implemented. But no worries! This is where Custom Renderers come in very handy!

So lets jump right in, go over to the iOS project, create a custom renderer – you remember how, right? – and put this into it.

using System;
using iOSTabBarSample.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;

[assembly: ExportRenderer (typeof (TabbedPage), typeof (TabBarRenderer))]

namespace iOSTabBarSample.iOS
{
    public class TabBarRenderer : TabbedRenderer
    {
        private bool _initialized;

        public override void ViewWillAppear (bool animated)
        {
            if (!_initialized) {
                if (TabBar?.Items == null)
                    return;

                var tabs = Element as TabbedPage;

                if (tabs != null) {
                    for (int i = 0; i < TabBar.Items.Length; i++) {
                        UpdateItem (TabBar.Items [i], tabs.Children [i].Icon, tabs.Children [i].StyleId);
                    }
                }

                _initialized = true;
            }

            base.ViewWillAppear (animated);
        }

        private void UpdateItem (UITabBarItem item, string icon, string badgeValue)
        {
            if (item == null)
                return;

            try {
                if (icon.EndsWith (".png"))
                    icon = icon.Replace (".png", "_selected.png");
                else
                    icon += "_selected";

                item.SelectedImage = UIImage.FromBundle (icon);
                item.SelectedImage.AccessibilityIdentifier = icon;
            } catch (Exception ex) {
                Console.WriteLine ("Unable to set selected icon: " + ex);
            }
        }
    }
}

So what happens here?

In the ViewWillAppear method we determine if there are any tab items to process. I’ve also included a boolean to make sure it only runs the first time the page is shown. If the SelectedImage is set, we don’t need to touch it again.

Then we are going to take those tab items and run them through the UpdateItem method we have created. Inside that method you see that first thing is to check how our icons are named. In Xamarin.Forms you can skip the extension and the images are correctly found on each platform. If you did add the extension for some reason, let’s just get that checked.

But either way, we append ‘_selected’ to it and set the SelectedImage property to that icon. And that’s it!
Of course, if you want another naming convention, feel free. Also, if you want to be completely free to give in a different name altogether, you might want to look at inheriting the Page and add a SelectedIcon property to it or something. Be creative!

If we run the app now, we directly see the effects.

Filled TabBar icons
Filled TabBar icons

Wow! Awesome! That’s what I’m talking about!

Now while we are at it, you can give it your own color as well. This can be done with something called the TintColor. This is useable on multiple types of controls, but is also used for coloring the icons and text in the TabBar.

To do this just add this one line in your AppDelegate.

[Register ("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching (UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init ();

            UITabBar.Appearance.TintColor = Color.Red.ToUIColor ();

            LoadApplication (new App ());

            return base.FinishedLaunching (app, options);
        }
    }

Check out the line starting with UITabBar. Now of course you can set any color there.

When we run it now it looks nice and red!

Red and selected TabBar icons
Red and selected TabBar icons

Now your Xamarin Forms iOS app wil look a lot more like an actual iOS app!

The code for this sample project can be found on GitHub right here. Enjoy!

Gone Mobile: Gone Mobile 35: Mobile Testing with Alexandra Marin

In this episode we’re joined by Alexandra Marin to talk about Behavior Driven Development for Xamarin Developers

Hosts: Greg Shackles, Jon Dick

Guest: Alexandra Marin

Links:

Thanks to our Sponsors!

http://raygun.com

Raygun Pulse
is now available for mobile – Real user monitoring for your mobile apps! Get deep detail into how your mobile applications are performing for your users.