Even though Liferay developed Liferay Screens for Xamarin with great care, you may still run into some common issues. This tutorial lists tips and solutions for these issues, as well as answers to common questions about Screens for Xamarin.
General Troubleshooting
Before exploring specific issues, you should first make sure that you’ve installed the correct versions of Visual Studio and the Mono .NET framework. Each Screenlet’s reference documentation (available for Android and iOS) lists these versions.
It may also help to investigate the sample Xamarin.Android and Xamarin.iOS apps developed by Liferay. Both are good examples of how to use Screenlets, Views (Android), and Themes (iOS):
If you get stuck at any point, you can post your question on our forum. We’re happy to assist you!
Common Issues
-
Build issues:
Running Clean in Visual Studio may not be enough. Close Visual Studio, remove all the
bin
andobj
folders that weren’t removed by the clean, then rebuild your project. -
NSUnknownKeyException
error in Xamarin.iOS:This error occurs when Liferay Screens for iOS has a wrong module name in an XIB file. You must solve this in Xcode, removing the module name in the XIB file’s Custom Class assignment in Interface Builder.
-
The selector is already registered
error in Xamarin.iOS:This error occurs because one or more methods share the same name. To fix this, the binding file must be updated. Please file a ticket in our Jira or post the issue on our forum.
-
Xamarin.iOS crashes unexpectedly without any error messages in the console:
Check the log file. On Mac OS, do this via the Console. On Windows, use the Event Viewer. In the app, you must click User Reports and then look for your app’s name. Note that there may be more than one log file.
-
The app doesn’t call delegate methods in Xamarin.iOS:
When you implement the delegate methods in your view controller, make sure to annotate them with
[Export(...)]
. You must also set the view controller to the Screenlet instance’sDelegate
property. Here’s an example of such a view controller that implements Login Screenlet’s delegate,ILoginScreenletDelegate
:public partial class ViewController : UIViewController, ILoginScreenletDelegate { protected ViewController(IntPtr handle) : base(handle) {} public override void ViewDidLoad() { base.ViewDidLoad(); this.loginScreenlet.Delegate = this; } [Export("screenlet:onLoginResponseUserAttributes:")] public virtual void OnLoginResponseUserAttributes(BaseScreenlet screenlet, NSDictionary<NSString, NSObject> attributes) { ... } ... }
DataType Mapping
For a better understanding of Xamarin code and example apps, see this list to compare type mapping between platforms. You must write Xamarin apps in C#, which has some differences compared to native code:
-
Delegate (iOS) or listener (Android) classes:
These classes are important because they listen for a Screenlet’s events. In Liferay Screens for Xamarin, Screenlet delegates and listeners are prefixed with an
I
. For example, Login Screenlet’s delegate in native code isLoginScreenletDelegate
, while in Xamarin it’sILoginScreenletDelegate
. Similarly, Login Screenlet’s listener in native code isLoginListener
, while in Xamarin it’sILoginListener
. Use a similar naming scheme when you define a class/interface pair where the class is a standard implementation of the interface. -
Getter and setter methods:
To get or set a value in native code, you use its getter and setter methods. In Liferay Screens for Xamarin, you should convert such methods to properties. If you have only one of these methods, you can call the method itself. For example:
// If you implemented a setter and a getter, call the property loginScreenlet.Listener = this; // Otherwise, call the method loginScreenlet.getListener();
-
Pascal case convention:
C# code is usually written in Pascal case. However, you should use Camel case for protected instance fields or parameters.
Language Equivalents between Swift and C#
-
Protocols in Swift are analogous to interfaces in C#:
// Swift protocol DoThings { func MyMethod() -> String } // C# interface DoThings { string MyMethod(); }
-
Initializers in Swift are analogous to constructors in C#:
// Swift class MyClass { var myVar : String = "" init(myVar : String) { self.myVar = myVar } } var testing = MyClass(myVar: "Test") // C# class MyClass { protected string myVar = ""; public MyClass() {} public MyClass(string myVar) { this.myVar = myVar; } } var testing = new MyClass(myVar: "Test");
To learn more about language equivalents between Swift and C#, see this quick reference.
Language Equivalents between Java and C#
To extend or implement a class or interface, Java requires that you use the
extends
or implements
keywords. C# doesn’t require this:
// Java
class Bird extends Vertebrate implements Actions {
...
}
// C#
class Bird : Vertebrate, Actions {
...
}
To learn more about language equivalents between Java and C#, see the C# for Java developers cheat sheet.
FAQs
-
Do I have to use Visual Studio?
No, but we strongly recommend it. If you wish, however, you can use Xamarin Studio or Visual Studio Code instead.
-
What’s the meaning of
[Export(...)]
above delegate method names?In short, this attribute makes properties and methods available in Objective-C. Xamarin’s documentation explains this attribute in detail.
Related Topics
Preparing Xamarin Projects for Liferay Screens
Using Screenlets in Xamarin Apps
Using Views in Xamarin.Android