Xojo.Timer.CallLater sometimes causes a NilObjectException

In a few places in my app I want to save some data a few seconds after the user has entered it — like autosave — so I have code in the TextChange event like this:

//Cancel any pending save
Timer.CancelCall(WeakAddressOf SaveRecord)

//Perform a save 5 seconds from now
Timer.CallLater(5000, WeakAddressOf SaveRecord)

I also use the same Timer.CancelCall line to cancel any pending save in the Close event of my view.

That works fine except that every now and then a user gets a NilObjectException error in Delegate.IM_Invoke which is called immediately after Xojo.Core._CallLaterTimer.Event_Action (based on the call stack that I log when I get an unhandled exception).

Am I doing something wrong that causes the NilObjectException to occur? Is there any way to test for/handle this?

Have you tried to use AddressOf instead of WeakAddressOf?

No I haven’t. I can see why that would help because AddressOf would make it hang on to the reference but I don’t think I really want that to happen?

A better way is to use a weakRef for the called object and a local method in the call
When the call timer fire the local method check if the weakRef exists and is valid then calls the object method.

Hi Jason,

Your right about WeakAddressOf when creating event handlers, because removing the event is automatic. This code does not seem to have an event handler added.

CallLater appears to only send the pointer, as the sample code in the Xojo website only seems to use AddressOf. My guess is that using WeakAddressOf will attempt to remove the event handler, which doesn’t exist in this case. This is probably why the program is giving a nil object exception.

As Antonio suggested, maybe try it with AddressOf instead. :slight_smile:

Post the call stack (only for the thread which crashed).

OK so let me see if I’ve got this right. SaveRecord is a local method (local to the iOSView). There’s no object method involved here. So are you suggesting I use AddressOf when calling CancelCall and keep WeadAddressOf for the CallLater call?, eg:

//Cancel any pending save
Timer.CancelCall(AddressOf SaveRecord)

//Perform a save 5 seconds from now
Timer.CallLater(5000, WeakAddressOf SaveRecord)

As long the method is local and you cancel it in the Close event, AddressOf in both call should be fine

Interestingly if I use AddressOf the iOSView Close event doesn’t fire, probably because there’s a reference to the SaveRecord method being held on to. So I’d need to CancelCall outside of the Close event but I can’t see a way to intercept the back button being tapped except in the view’s Close event. If I leave it as WeakAddressOf then it seems to be fine.

But that means I’m back at square one with the occasional exception that can’t be caught…

It looks like this is the same framework bug as reported here: <https://xojo.com/issue/40246>. This case has actually been closed as a duplicate of another case but the two don’t seem exactly the same to me. I hope this is not just going to slip under the carpet and never be fixed…

Wouldn’t it just be easier to wrap the failing code in a try-catch?

I’d love to, but it fails in Xojo’s Timer. CallLater method. It never reaches my code because my code is out of scope by then (hence the failure). It seems that CallLater is not checking for the delegate being null, or wrapping in its own try/catch, before attempting to call the method.

@Greg O’Lone the stack trace is:

RaiseNilObjectException
Delegate.IM_Invoke%%
Xojo.Core._CallLaterTimer.Event_Action%%o<Xojo.Core._CallLaterTimer>
-[XOJTimerAdapter timerFireMethod:]
__NSFireTimer