I mentioned this at https://github.com/xamarin/Xamarin.Forms/issues/10111#issuecomment-606393783 but decided to make a separate bug report given its severity. This is different than the aforementioned bug report as it was about the SwipeView breaking the XAML previewer.
If you have a SwipeView in your project it runs fine on iOS, but on Android an exception is thrown with "The class, property, or method you are attempting to use ('.ctor') is part of SwipeView; to use it, you must opt-in by calling Forms.SetFlags("SwipeView_Experimental") before calling Forms.Init()".
It is definitely set in my MainActivity.cs before calling Forms.Init():
protected override void OnCreate(Bundle savedInstanceState)
{
...
global::Xamarin.Forms.Forms.SetFlags("SwipeView_Experimental");
...
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
...
}
Here is the full stack trace (UXDivers.Grial.Repeater is the view that contains the swipe view as a child):
03-31 07:13:46.483 I/MonoDroid( 6386): UNHANDLED EXCEPTION:
03-31 07:13:46.509 I/MonoDroid( 6386): System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: The class, property, or method you are attempting to use ('.ctor') is part of SwipeView; to use it, you must opt-in by calling Forms.SetFlags("SwipeView_Experimental") before calling Forms.Init().
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.ExperimentalFlags.VerifyFlagEnabled (System.String coreComponentName, System.String flagName, System.String constructorHint, System.String memberName) [0x0007d] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.SwipeView.VerifySwipeViewFlagEnabled (System.String constructorHint, System.String memberName) [0x00000] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Platform.Android.SwipeViewRenderer..ctor (Android.Content.Context context) [0x00007] in <a7ac3b6d91f842e994e10fc68a00fc53>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at (wrapper managed-to-native) System.Reflection.RuntimeConstructorInfo.InternalInvoke(System.Reflection.RuntimeConstructorInfo,object,object[],System.Exception&)
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00005] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): --- End of inner exception stack trace ---
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x0001d] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Reflection.RuntimeConstructorInfo.DoInvoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00086] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Reflection.RuntimeConstructorInfo.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) [0x0022b] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Activator.CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x0009c] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Internals.DependencyResolver.ResolveOrCreate (System.Type type, System.Object source, System.Type visualType, System.Object[] args) [0x000af] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Internals.Registrar`1[TRegistrable].GetHandler (System.Type type, System.Object source, Xamarin.Forms.IVisual visual, System.Object[] args) [0x00060] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Internals.Registrar`1[TRegistrable].GetHandlerForObject[TOut] (System.Object obj, System.Object[] args) [0x00041] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element, Android.Content.Context context) [0x00005] in <a7ac3b6d91f842e994e10fc68a00fc53>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Platform.Android.VisualElementPackager.AddChild (Xamarin.Forms.VisualElement view, Xamarin.Forms.Platform.Android.IVisualElementRenderer oldRenderer, Xamarin.Forms.Platform.Android.RendererPool pool, System.Boolean sameChildren) [0x000c4] in <a7ac3b6d91f842e994e10fc68a00fc53>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Platform.Android.VisualElementPackager.OnChildAdded (System.Object sender, Xamarin.Forms.ElementEventArgs e) [0x0000f] in <a7ac3b6d91f842e994e10fc68a00fc53>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.Element.OnChildAdded (Xamarin.Forms.Element child) [0x00022] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.509 I/MonoDroid( 6386): at Xamarin.Forms.VisualElement.OnChildAdded (Xamarin.Forms.Element child) [0x00000] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Xamarin.Forms.Layout`1[T].OnChildAdded (Xamarin.Forms.Element child) [0x00000] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Xamarin.Forms.Layout.OnInternalAdded (Xamarin.Forms.View view) [0x0001d] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Xamarin.Forms.Layout.InternalChildrenOnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00078] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at (wrapper delegate-invoke) <Module>.invoke_void_object_NotifyCollectionChangedEventArgs(object,System.Collections.Specialized.NotifyCollectionChangedEventArgs)
03-31 07:13:46.510 I/MonoDroid( 6386): at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00018] in <581a01d04fd142f28a938a6381816b26>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action, System.Object item, System.Int32 index) [0x00009] in <581a01d04fd142f28a938a6381816b26>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at System.Collections.ObjectModel.ObservableCollection`1[T].InsertItem (System.Int32 index, T item) [0x0001a] in <581a01d04fd142f28a938a6381816b26>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at System.Collections.ObjectModel.Collection`1[T].Insert (System.Int32 index, T item) [0x00027] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Xamarin.Forms.ObservableWrapper`2[TTrack,TRestrict].Insert (System.Int32 index, TRestrict item) [0x0003f] in <b5f62705a3ea4249ac22723294e68624>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at UXDivers.Grial.FixedSizeLayout.UpdateVisibleItems () [0x0012e] in <70947e6eb6c44297aac214af99a22940>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at UXDivers.Grial.FixedSizeLayout.SetViewPort (System.Double center, System.Double radius) [0x00015] in <70947e6eb6c44297aac214af99a22940>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at UXDivers.Grial.Repeater.UpdateViewport (System.Double width, System.Double height, System.Double scrollPosition) [0x00048] in <70947e6eb6c44297aac214af99a22940>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at UXDivers.Grial.Repeater.LayoutChildren (System.Double x, System.Double y, System.Double width, System.Double height) [0x00144] in <70947e6eb6c44297aac214af99a22940>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in <629bcb146d674f9e83b55f4a64e6918c>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <bbfb9f1091004c048ef9a9c1f37af2d0>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <bbfb9f1091004c048ef9a9c1f37af2d0>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <bbfb9f1091004c048ef9a9c1f37af2d0>:0
03-31 07:13:46.510 I/MonoDroid( 6386): at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.46(intptr,intptr)
Goes without saying that this is a major issue as it breaks Android as a whole.
I'm using the latest preview version 4.6.0.494-pre2.
What is the code in the dots for:
protected override void OnCreate(Bundle savedInstanceState)
{
...
global::Xamarin.Forms.Forms.SetFlags("SwipeView_Experimental");
...
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
...
}
Are you enabling any other flags? If you are, you should do that in one call and not multiple because one will override the other.
To be sure everything is in order, please read the documentation page about it here.
The dots are other random code not relevant to this, or so I thought. One of the sections indeed does set other experimental flags.
So is the SetFlags method SERIOUSLY not additive? Doesn't the SET FLAGS name imply actually setting flags, ie OR:ing in bits? There are so many gotchas in Xamarin, what if you have different libraries that need to turn on different experimental flags independently of each other, they will overwrite each other.
For what it's worth having several SetFlag calls on iOS works fine, the setup is identical there.
Thanks.
Please attach a zipped reproduction.
@Tommigun1980 that is why we have the issue template in place and ask for a reproduction. I see how you can think the code is not relevant, as you can see in this example, in fact the code _is_ relevant.
I don't think libraries should be the ones responsible for setting experimental flags in my code, if they do try to do it I would very much like to be notified before I suddenly put experimental code in production just by using a library.
The SetFlags name implies that you set the flags supplied as a collection. I see how you can think otherwise, I'll discuss that internally and see if we can add some flexibility here.
However, the experimental flags and features are just that: experimental. The way we go about this is to make you aware of that. Because of that I think we rather have one exception too many.
I doubt that the same code would work on iOS. But I'm happy to be proven wrong if you can provide me a reproduction.
Assuming that this fixed the issue for you, I'm closing this one. If you do find a bug in the way iOS handles the flags or have concrete ideas about how we can make the API around that better, please open a new issue.
Thanks!
@Tommigun1980 that is why we have the issue template in place and ask for a reproduction. I see how you can think the code is not relevant, as you can see in this example, in fact the code _is_ relevant.
I don't think libraries should be the ones responsible for setting experimental flags in my code, if they do try to do it I would very much like to be notified before I suddenly put experimental code in production just by using a library.
The
SetFlagsname implies that you set the flags supplied as a collection. I see how you can think otherwise, I'll discuss that internally and see if we can add some flexibility here.However, the experimental flags and features are just that: experimental. The way we go about this is to make you aware of that. Because of that I think we rather have one exception too many.
I doubt that the same code would work on iOS. But I'm happy to be proven wrong if you can provide me a reproduction.
Assuming that this fixed the issue for you, I'm closing this one. If you do find a bug in the way iOS handles the flags or have concrete ideas about how we can make the API around that better, please open a new issue.
Thanks!
@jfversluis Imho any behaviour of a method called SetFlags, that does not OR in flags does not work as expected.
And you can doubt all you want about the iOS part, but the experimental flags are set identically in iOS and it never complains there at all.
This is the iOS setup code:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Xamarin.Calabash.Start();
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
global::Xamarin.Forms.Forms.SetFlags("SwipeView_Experimental");
global::Xamarin.Forms.Forms.Init();
...
}
Android:
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.SetFlags("CollectionView_Experimental");
global::Xamarin.Forms.Forms.SetFlags("SwipeView_Experimental");
...
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
}
Feel free to try it yourself.
Thanks.
On android you have to change the order of SetFalgs like this :
global :: Xamarin.Forms.Forms.SetFlags ("SwipeView_Experimental");
global :: Xamarin.Forms.Forms.SetFlags ("CollectionView_Experimental");
I don't know why but it works for me
Most helpful comment
On android you have to change the order of SetFalgs like this :
global :: Xamarin.Forms.Forms.SetFlags ("SwipeView_Experimental");
global :: Xamarin.Forms.Forms.SetFlags ("CollectionView_Experimental");
I don't know why but it works for me