Xojo.Timer.CallLater sometimes causes a NilObjectException

  1. 2 weeks ago

    Jason T

    Oct 8 Pre-Release Testers, Xojo Pro Sydney, Australia

    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?

  2. Antonio R

    Oct 9 Pre-Release Testers, Xojo Pro Europe (Italy)

    Have you tried to use AddressOf instead of WeakAddressOf?

  3. Jason T

    Oct 9 Pre-Release Testers, Xojo Pro Sydney, Australia

    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?

  4. Antonio R

    Oct 9 Pre-Release Testers, Xojo Pro Europe (Italy)

    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.

  5. Eugene D

    Oct 9 Pre-Release Testers, Xojo Pro Canada scispec.ca
    Edited 2 weeks ago by Eugene D

    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. :)

  6. Eli O

    is not verified Oct 9 Europe (Berlin, Germany)

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

  7. Jason T

    Oct 9 Pre-Release Testers, Xojo Pro Sydney, Australia

    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)
  8. Antonio R

    Oct 9 Pre-Release Testers, Xojo Pro Europe (Italy)

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

  9. Jason T

    Oct 9 Pre-Release Testers, Xojo Pro Sydney, Australia

    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...

  10. Jason T

    Oct 10 Pre-Release Testers, Xojo Pro Sydney, Australia
    Edited 2 weeks ago by Jason T

    It looks like this is the same framework bug as reported here: Feedback Case #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...

  11. Greg O

    Oct 11 Xojo Inc Somewhere near Raleigh, NC

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

  12. Jason T

    Oct 11 Pre-Release Testers, Xojo Pro Sydney, Australia

    @Greg OLone 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.

  13. Jason T

    Oct 11 Pre-Release Testers, Xojo Pro Sydney, Australia

    @Greg OLone the stack trace is:

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

or Sign Up to reply!