iOS Question [SOLVED?] Nasty bug - involving classes containing instances of other classes

JackKirk

Well-Known Member
Licensed User
I have spent most of the day getting my brain around this and think I have netted it down to the attached zip.

If you:

(1) compile the code in debug mode WITH A BREAKPOINT AT THE INDICATED LINE IN LAST MODULE
(2) F8 until a red button appears on phone
(3) tap the red button
(4) F8 repeatedly

everything works as you would expect - you end up with CLICK in the log.

If you delete the Bug icon on the phone (DO NOT SKIP THIS STEP) and then repeat the exercise with no breakpoints - when you tap on the red button nothing happens.

This is the primary module:

B4X:
#Region  Project Attributes

    #ApplicationLabel: Bug
    #Version: 1.0

    'This will allow running on iPhones (a la naturale) and iPads (in "iPhone" mode)
    #Target: iPhone

   'Orientation possible values: Portrait, LandscapeLeft, LandscapeRight and PortraitUpsideDown
    #iPhoneOrientations: Portrait
    #iPadOrientations: Portrait

#End Region
Private Sub Process_Globals

    Public App As Application
    Public NavControl As NavigationController
    Public Page1 As Page

End Sub

Private Sub Application_Start(Nav As NavigationController)

    NavControl = Nav
    Page1.Initialize("Page1")
    NavControl.ShowPage(Page1)

End Sub

Private Sub Page1_Resize(Width As Float, Height As Float)

    Page1.RootPanel.Color = Colors.White

    Private wrk_dialog As XDialog
    wrk_dialog.Initialize(Me, Page1.RootPanel)

End Sub

Public Sub garbage_Click

    Log("CLICK")

End Sub

Which creates an instance of this class:

B4X:
Private Sub Class_Globals

End Sub

Public Sub Initialize(in_host_parent1 As Object, in_host_panel1 As Panel)

    Private wrk_button As XSingleButton
           
    wrk_button.Initialize(in_host_parent1, in_host_panel1)

End Sub

Which in turn creates an instance of this class:

B4X:
Private Sub Class_Globals
   
    Private host_parent2 As Object
    Private host_panel2 As Panel

End Sub

Public Sub Initialize(in_host_parent2 As Object, in_host_panel2 As Panel)

    Private singlebutton As Button

    host_parent2 = in_host_parent2        '<<<<<<<<<<<<< put breakpoint on this line BEFORE compiling
    host_panel2 = in_host_panel2
    singlebutton.Initialize("Event_Button", singlebutton.STYLE_SYSTEM)
    host_panel2.AddView(singlebutton, host_panel2.Width/4, host_panel2.Height/4,host_panel2.Width/2, host_panel2.Height/2)
    singlebutton.Color = Colors.Red

End Sub

Private Sub Event_Button_Click

    If SubExists(host_parent2, "garbage_Click", 0) Then
   
        CallSub(host_parent2, "garbage_Click")
   
    End If

End Sub

This is a real showstopper for me - any help appreciated...
 

Attachments

  • Bug.zip
    1.7 KB · Views: 145
Last edited:

Erel

Administrator
Staff member
Licensed User
I tested your project. There is no nasty bug here. Actually there is no bug at all.

Check the logs. You will see that the two class instances are released because there are no live references to them. So the event is not handled.

You have two options:
1. Make wrk_dialog a global variable and wrk_button a global variable (inside the class).
2. The view that is created (singlebutton) will be kept alive as it was added to the layout. You can add:
B4X:
singlebutton.Tag = Me
This will cause the class instance to be kept alive as long as the view is alive.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Erel, I was able to use your second option with minimal pain.

I can't say I fully understand what is going on.

This came about as a byproduct of converting a major B4A app to B4I.

Attached is a zip of my understanding of the B4A code equivalent to Bug.zip in the first post.

This works fine in B4A...
 

Attachments

  • BugB4A.zip
    7.3 KB · Views: 152
Upvote 0

Erel

Administrator
Staff member
Licensed User
Android uses a garbage collector to manage the memory while iOS uses a simple reference counting mechanism. This means that reference cycles will cause memory leaks on iOS.
As a result of this, events handlers do not hold a strong reference to the class instance (otherwise there would have been a memory leak).
This doesn't happen in Android because the GC can handle reference cycles.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
I think I can just about understand this... almost... maybe...
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
If the class instance was released unexpectedly then there is probably a bug in your code.

By defaut I was also making the assumption that B4I would behave as per B4A more or less - I guess this is on the less side.

I appreciate that you are putting B4A/I on totally different platforms and the commonality can only go so far - but when something blows up trying to port a big bit of reasonably complex code you wonder is it the change in platform? is it something you stuffed up in the port? is it????

Anyrate I have just about got all the dialoging stuff ported - now for orientation sensors, cameras and Google maps :(:(:(
 
Upvote 0
Top