Xamarin SKPaymentQueue AddPayment throwing exception - xamarin.ios

In my Xamarin app when I call this method
private void MakePayment (SKProduct product)
{
SKPayment payment = SKPayment.PaymentWithProduct (product);
SKPaymentQueue.DefaultQueue.AddPayment (payment);
}
I get this error:
Failed to marshal the Objective-C object 0x14607110 (type:
SKPaymentTransaction). Could not find an existing managed instance for
this object, nor was it possible to create a new managed instance
(because the type 'MonoTouch.StoreKit.SKPaymentTransaction[]' does not
have a constructor that takes one IntPtr argument).
I'm not sure if I have something configured wrong or there is an issue in my code or Xamarin.
Here's the code for the Observer
internal class CustomPaymentObserver : SKPaymentTransactionObserver
{
private InAppPurchase inAppPurchase;
public CustomPaymentObserver (InAppPurchase inAppPurchase)
{
this.inAppPurchase = inAppPurchase;
}
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
Console.WriteLine ("UpdatedTransactions");
foreach (SKPaymentTransaction transaction in transactions) {
switch (transaction.TransactionState) {
case SKPaymentTransactionState.Purchased:
inAppPurchase.CompleteTransaction (transaction);
break;
case SKPaymentTransactionState.Failed:
inAppPurchase.FailedTransaction (transaction);
break;
default:
break;
}
}
}
public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
}
}
Here is the full stack trace:
System.Exception: Failed to marshal the Objective-C object 0x17ecb680 (type: SKPaymentTransaction). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'MonoTouch.StoreKit.SKPaymentTransaction[]' does not have a constructor that takes one IntPtr argument).
at MonoTouch.ObjCRuntime.Runtime.MissingCtor (IntPtr ptr, IntPtr klass, System.Type type, MissingCtorResolution resolution) [0x00046] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/.pp-Runtime.cs:352
at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject[NSObject] (IntPtr ptr, System.Type type, MissingCtorResolution missingCtorResolution) [0x00000] in :0
at MonoTouch.ObjCRuntime.Runtime.GetNSObject (IntPtr ptr, System.Type target_type, MissingCtorResolution missingCtorResolution, System.Boolean& created) [0x00073] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/.pp-Runtime.cs:514
at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (IntPtr ptr, IntPtr type_ptr, System.Boolean& created) [0x0000c] in /Developer/MonoTouch/Source/monotouch/src/ObjCRuntime/.pp-Runtime.cs:686
at at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetNSObjectWrapped (intptr,intptr,int&)
at at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSend_IntPtr (intptr,intptr,intptr)
at MonoTouch.StoreKit.SKPaymentQueue.AddPayment (MonoTouch.StoreKit.SKPayment payment) [0x00014] in /Developer/MonoTouch/Source/monotouch/src/StoreKit/.pp-SKPaymentQueue.g.cs:109
at IOS.Util.IAP.InAppPurchase.ReceivedResponse (MonoTouch.StoreKit.SKProductsRequest request, MonoTouch.StoreKit.SKProductsResponse response) [0x0001d] in /Users/aaron/Projects/budget-ease-xamarin/IOS/Util/IAP/InAppPurchase.cs:43
at at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/.pp-UIApplication.cs:38
at IOS.Application.Main (System.String[] args) [0x00008] in /Users/aaron/Projects/budget-ease-xamarin/IOS/Main.cs:16

What's happened here is that the C# instance of your CustomPaymentObserver got garbage collected, while it's native ("Objective-C") counterpart lived on. When a notification was finally delivered, the native object tried to call into the now dead C# object and crashed your App.
To circumvent this, keep a reference to your CustomPaymentObserver e.g. in your AppDelegate to keep it alive.
I'm not sure this is documented somewhere for Xamarin.iOS (couldn't find something on a quick look), but I believe very similar for Xamarin.Droid (e.g. http://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/)

I'm not really sure what was causing this. I thought it was perhaps something related to the linker. But I uninstalled Xamarin completely from my Mac (including all the MonoTouch stuff) and reinstalled everything and now it's working.

Related

No parametless constructor defined Hangfire Ninject

I'm having a problem activating instance of my class with no parametless constructor defined.
The constructor:
public HangfireExecutor(ICommandDispatcher commandDispatcher, IQueryDispatcher queryDispatcher, IMapper mapper)
How I register and configure Hangfire (three dots are used instead of sensitive info):
[assembly: OwinStartupAttribute(typeof(Web2.Startup))]
public partial class Startup
private IAppBuilder _app;
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
_app = app;
GlobalConfiguration.Configuration.UseSqlServerStorage("...");
_app.UseHangfireDashboard("/...", new DashboardOptions
{
Authorization = new[] { new HangfireDashboardAuthorizationFilter() },
AppPath = "/Identity/Create"
});
_app.UseHangfireServer();
_app.UseNinjectMiddleware(CreateKernel);
}
Registration in IoC container:
public partial class Startup
{
...
protected IKernel CreateKernel()
{
var kernel = new StandardKernel();
...
kernel.Bind<HangfireExecutor>().ToSelf().InBackgroundJobScope();
GlobalConfiguration.Configuration.UseNinjectActivator(kernel);
return kernel;
The error:
System.MissingMethodException
No parameterless constructor defined for this object hangfire ninject System.RuntimeTypeHandle.CreateInstance
System.MissingMethodException: No parameterless constructor defined for this object
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Hangfire.JobActivator.ActivateJob(Type jobType)
at Hangfire.JobActivator.SimpleJobActivatorScope.Resolve(Type type)
at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
For me it looks like the Hangfire does not use Ninject activator (?) but I don't know why.
I've followed both tutorials: on Hangfire site and Hangfire.Ninject github and several github repos and SO questions.
Instatiating other classes not used by Hangfire works well; also instatiating Hangfire executor with parametless constructor works properly.
I'm using:
ASP .NET MVC 5
.NET Framework 4.6.1,
Hangfire 1.6.21
Hangfire.Ninject 1.2
As method _app.UseNinjectMiddleware(CreateKernel); does not create kernel (just keeps delegate to the metod creating the kernel) the correct order of commands in Hangfire configuration in my case should be:
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
_app = app;
GlobalConfiguration.Configuration.UseSqlServerStorage("...");
_app.UseHangfireDashboard("/...", new DashboardOptions
{
Authorization = new[] { new HangfireDashboardAuthorizationFilter() },
AppPath = "/Identity/Create"
});
_app.UseNinjectMiddleware(CreateKernel);
}
and then at the end of CreateKernel method:
kernel.Bind<HangfireExecutor>().ToSelf().InBackgroundJobScope();
GlobalConfiguration.Configuration.UseNinjectActivator(kernel);
_app.UseHangfireServer();
return kernel;
Now Hangfire started resolving dependencies. I think that it is important to create kernel as soon after starting the app as possible - otherwise Hangfire may not be initialized and background jobs will not be executed.

MvvmCross Xamarin IOS TextView Binding with conversion does no longer work

I have a Xamarin.IOS application and use MvvmCross and the ResxPlugin for translations. That workes without issues in debug. But since I updated from I guess 5.3.x to 5.6.3 the app crashes in release mode with the linker set to "Link Framework SDKs only" when I try to execute the following line:
bindingSet.Bind(textViewWelcomeMessage)
.For(txt => txt.Text)
.To(vm => vm.TextSource)
.WithConversion(new MvxLanguageConverter(), "WelcomeMessage");
This works without issues:
bindingSet.Bind(textFieldAgreementText)
.For(lbl => lbl.AttributedText)
.To(vm => vm.GeneralAgreementText)
.WithConversion("StringToHtml");
So I assume the problem lies somewhere in the MvxLanguageConverter in combination with textFields.
In my "LinkerPleaseInlude" file I have this added:
public void Include(UITextView textView)
{
textView.Text = textView.Text + "";
textView.AttributedText = new NSAttributedString();
textView.Changed += (sender, args) => { textView.Text = ""; };
}
The error message in the output is:
2018-01-24 09:37:39.415 ConnectContacts.Ios[27680:1063685] System.ArgumentNullException: missing source event info in MvxWeakEventSubscription
Parameter name: sourceEventInfo
at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`2[TSource,TEventArgs]..ctor (UIKit.NSTextStorage source, System.Reflection.EventInfo sourceEventInfo, System.EventHandler`1[TEventArgs] targetEventHandler) [0x00017] in <6adc0d5857264558a9d45778a78ae02a>:0
at MvvmCross.Platform.WeakSubscription.MvxWeakEventSubscription`2[TSource,TEventArgs]..ctor (UIKit.NSTextStorage source, System.String sourceEventName, System.EventHandler`1[TEventArgs] targetEventHandler) [0x00012] in <6adc0d5857264558a9d45778a78ae02a>:0
at MvvmCross.Platform.WeakSubscription.MvxWeakSubscriptionExtensionMethods.WeakSubscribe[TSource,TEventArgs] (TSource source, System.String eventName, System.EventHandler`1[TEventArgs] eventHandler) [0x00000] in <6adc0d5857264558a9d45778a78ae02a>:0
at MvvmCross.Binding.iOS.Target.MvxUITextViewTextTargetBinding.SubscribeToEvents () [0x00053] in <614c9ef828c14ba687a40ec2656f480f>:0
at MvvmCross.Binding.Bindings.MvxFullBinding.CreateTargetBinding (System.Object target) [0x00057] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.Bindings.MvxFullBinding..ctor (MvvmCross.Binding.MvxBindingRequest bindingRequest) [0x0002f] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.Binders.MvxFromTextBinder.BindSingle (MvvmCross.Binding.MvxBindingRequest bindingRequest) [0x00000] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.Binders.MvxFromTextBinder+<>c__DisplayClass2_0.<Bind>b__0 (MvvmCross.Binding.Bindings.MvxBindingDescription description) [0x00018] in <866b1e46764b48aab0d408952a6f006f>:0
at System.Linq.Enumerable+SelectArrayIterator`2[TSource,TResult].MoveNext () [0x0003a] in <8bc31b0df50a4d32b3f1d5af764165ad>:0
at MvvmCross.Binding.BindingContext.MvxBindingContextOwnerExtensions.AddBindings (MvvmCross.Binding.BindingContext.IMvxBindingContextOwner view, System.Object target, System.Collections.Generic.IEnumerable`1[T] bindings, System.Object clearKey) [0x0001d] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.BindingContext.MvxBindingContextOwnerExtensions.AddBindings (MvvmCross.Binding.BindingContext.IMvxBindingContextOwner view, System.Object target, System.Collections.Generic.IEnumerable`1[T] bindingDescriptions, System.Object clearKey) [0x00018] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.BindingContext.MvxBindingContextOwnerExtensions.AddBinding (MvvmCross.Binding.BindingContext.IMvxBindingContextOwner view, System.Object target, MvvmCross.Binding.Bindings.MvxBindingDescription bindingDescription, System.Object clearKey) [0x0000b] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.BindingContext.MvxBaseFluentBindingDescription`1[TTarget].Apply () [0x0001f] in <866b1e46764b48aab0d408952a6f006f>:0
at MvvmCross.Binding.BindingContext.MvxFluentBindingDescriptionSet`2[TOwningTarget,TSource].Apply () [0x00016] in <866b1e46764b48aab0d408952a6f006f>:0
at ConnectContacts.Ios.Views.Wizard.WelcomeView.ViewDidLoad () [0x001ae] in <b2a318752d5d4fbeb6d32a83c8b6f752>:0
--- End of stack trace from previous location where exception was thrown ---
Do I have to make something different with the new version?
You need to add the following to your LinkerPleaseInlude for UITextView
textView.TextStorage.DidProcessEditing += (sender, e) => textView.Text = "";
See this GitHub issue

Selector invoked from objective-c on a managed object that has been GC'ed, how to avoid viewcontrollers from being GC'd

We have an app in the appstore that works without any issues on iPhone 4g/4gs but when I tested it on an iPod I got a surprise because it crashes all the time at "random" places. Looking at the strack traces it seems my viewcontrollers have been GC'ed.
Will the viewcontroller be garbagecollected if I write methods like this:
public void PushShowTeamController (Object a)
{
var teamController = new TeamController (a);
NavigationController.PushViewController (teamController, true);
}
Because the iPod suddently throws an error like this:
Jan 6 18:52:09 unknown MyApp[5197] <Warning>: Received memory warning.
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: Unhandled Exception: System.Exception: Selector invoked from objective-c on a managed object that has been GC'ed ---> System.MissingMethodException: No constructor found for MyApp.TeamController::.ctor(System.IntPtr)
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: at System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <filename unknown>:0
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00000] in <filename unknown>:0
Jan 6 18:52:10 unknown UIKitApplication:mypackage.app[0x9db2][5197] <Notice>: --- End of inner exception stack trace ---
This will happen when an managed object is disposed (when no reference is left to an instance) and the object is later resurfaced by native code.
You need to ensure that a reference to MyApp.TeamController is kept in managed code as long as it can be required (e.g. accessed) by native code.
In most case MonoTouch will ensure a reference is kept. Your code:
NavigationController.PushViewController (teamController, true);
is correct and UINavigationController will keep a reference to your teamController. However if you call PushViewController on another controller then the first reference will be overwritten and will be collectable by the garbage collector (GC). This situation would lead to the exception you are seeing.
Note: because you can't predict when the GC will collect unreferenced object instance the exception will appear to be thrown randomly.
From my experience this happens when i use a lot of dispose() on managed objects instead of setting them to null and leaving the GC to do its job. Also anonymous delegates combined with dispose() can lead to such problems

No constructor found for ViewController::.ctor(System.IntPtr)

I'm having an issue where my Monotouch application sometimes crashes just after receiving a memory warning. Please see that stack trace below.
Received memory warning. Level=2
DTMobileIS[2299] : _memoryNotification : {
OSMemoryNotificationLevel = 2;
timestamp = "2011-04-11 14:29:09 +0000";
}
Toplevel exception: System.MissingMethodException: No constructor found for Myapp.UI.BoardController::.ctor(System.IntPtr)
at System.Activator.CreateInstance (System.Type type, BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x00000] in :0
at System.Activator.CreateInstance (System.Type type, System.Object[] args, System.Object[] activationAttributes) [0x00000] in :0
at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in :0
at MonoTouch.ObjCRuntime.Runtime.ConstructNSObject (IntPtr ptr, IntPtr klass) [0x00000] in :0
at MonoTouch.ObjCRuntime.Runtime.GetNSObject (IntPtr ptr) [0x00000] in :0
at MonoTouch.ObjCRuntime.Runtime.GetNSObjectWrapped (IntPtr ptr) [0x00000] in :0
at (wrapper native-to-managed) MonoTouch.ObjCRuntime.Runtime:GetNSObjectWrapped (intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00000] in :0
at Myapp.Free.Application.Main (System.String[] args) [0x00000] in /Users/haakon/Code/Myapp-work/iOS/Myapp.Free/Myapp.Free/Main.cs:12
The stack trace is correct in that the indicated class (BoardController, which is a UIViewController subclass) lacks a constructor taking a IntPtr parameter. But this is intentional as I don't use Interface Builder at all in my application. So why does this happen?
I did find a similar question that seemed to suggest that this can happen if you allow your views (or possibly view controllers) to become garbage collected. But I don't see how this can happen here. Some background: My application delegate holds a strong reference to a navigation controller, which in turn holds a strong reference to the root view controller in the navigation stack. This root view controller also holds a strong reference to the BoardController instance. So I don't understand how it's possible that BoardController gets garbage collected.
Any ideas?
The IntPtr constructor is used when a native object needs to be surfaced to a managed object. In this particular case, you could be creating, like this:
var foo = new Foo ();
SomeObject.Property = foo;
This assigns the Foo object to the property, but if the Property is an Objective-C object, if you do not keep a reference to "foo", then Mono's GC will go ahead and dispose the linkage between the managed Foo and the unmanaged Foo.
Then, later on, you try to retrieve it:
var bar = SomeObject.Property;
Here, MonoTouch will know that there is no managed object anymore than maps to it, so it has to construct a new one, but all it has is the IntPtr to the Objective-C code. This is why you need the constructor.
You might be tempted to just add the native constructor, and this is fine in many cases, but it is a problem if your object has its own state stored in the managed world, for example:
public class Foo : UIView {
string Name;
public Foo () { Name= "Hello"; }
public Foo (IntPtr ptr) : base (ptr) {}
}
In this case, the IntPtr constructor can not completely reconstruct the managed object and its state merely from the IntPtr. So the likely source of your problem is that you are not keeping a reference to your object.
So the real fix in short is: keep a reference to your BoardController in your managed code to prevent the object from being collected when you are still going to use it later on.

Monotouch - NSInvalidArgumentException

I've got this error:
2011-03-28 15:38:07.154 FolderNavigation[264:207] -[Subfolder _setViewDelegate:]: unrecognized selector sent to instance 0x6eaafd0
Unhandled Exception: MonoTouch.Foundation.MonoTouchException: Objective-C exception thrown. Name: NSInvalidArgumentException Reason: -[Subfolder _setViewDelegate:]: unrecognized selector sent to instance 0x6eaafd0
at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:26
at MonoTouch.UIKit.UIApplication.Main (System.String[] args) [0x00000] in /Users/plasma/Source/iphone/monotouch/UIKit/UIApplication.cs:31
at FolderNavigation.Application.Main (System.String[] args) [0x00000] in /Users/claudio/Projects/FolderNavigation/FolderNavigation/Main.cs:16
Error connecting stdout and stderr (127.0.0.1:10001)
and following de code using Debug(using Step Into)
Starting on Main.cs:
static void Main (string[] args)
{
UIApplication.Main (args);
}
Subfolder.xib.cs(next Step Into)
[Export("initWithCoder:")]
public Subfolder (NSCoder coder) : base(coder)
{
Initialize ();
}
void Initialize ()
{
}
and in the next step, I have got this error.
Does anybody have an idea?
Thanks in advance!
Is this a View or ViewController? My auto-generated files have a public Subfolder() : base("Subfolder", null) constructor, which I don't see here.
Also, which version of XCode & MT are you running?

Resources