iOS Question Problem with List.add

Discussion in 'iOS Questions' started by Shay, Mar 20, 2015.

  1. Shay

    Shay Well-Known Member Licensed User

    see this, very odd:

    I am adding in loop:
    MyPoint.Initialize(Lat1,Lng1)
    WayPoints.Add(MyPoint)

    this is from the log, each time I add another entry to list, all previous are changing as the last one

    <B4IList: (
    "Lat: 32.065900, Lon: 34.829300"
    )>
    <B4IList: (
    "Lat: 32.065870, Lon: 34.829910",
    "Lat: 32.065870, Lon: 34.829910"
    )>
    <B4IList: (
    "Lat: 32.066230, Lon: 34.829930",
    "Lat: 32.066230, Lon: 34.829930",
    "Lat: 32.066230, Lon: 34.829930"
    )>
    <B4IList: (
    "Lat: 32.066340, Lon: 34.829950",
    "Lat: 32.066340, Lon: 34.829950",
    "Lat: 32.066340, Lon: 34.829950",
    "Lat: 32.066340, Lon: 34.829950"
    )>
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    Add Dim MyPoint As Point before you initialize it. Otherwise you are using the same object instance each time.
     
  3. Shay

    Shay Well-Known Member Licensed User

    I have in the function code: (above this line)
    Private MyPoint As LatLng

    the log above is from:
    log(WayPoints)
    The problem is the entire list is changing all the time
     
  4. klaus

    klaus Expert Licensed User

    You should post the code of the whole routine.
     
  5. Brian Robinson

    Brian Robinson Active Member Licensed User

    Hi Shay,

    You need to Dim MyPoint inside the loop.

    You have only created 1 variable. Each time you add it to the list, it is creating a reference pointer to the original variable, which you change to the last way point.

    Example:
    Private MyPoint as LatLng create a position in memory of (X1)

    This is what happens in the loop
    Loop 1
    MyPoint = (Lat 111, Long 222) - this value is stored in (X1)
    List.Add(MyPoint) - This actually just adds a pointer to (X1)
    Loop 2
    MyPoint = (Lat 112, Long 221) - This value is stored in (X1)
    List.Add(MyPoint) - Adds another pointer to (X1)
    *** At this point, both list items are pointing to the same position in memory (X1) which has the value of (Lat 112, Long 221)
    End Loop

    Your code needs to look like this:

    Code:
    For iLoop = 0 to 10
      
    Dim MyPoint as LatLng
      MyPoint.Initialize(Lat1,Lng1)
      WayPoints.Add(MyPoint)
    Next
    Each time the loop is executed, MyPoint is reserved in memory (Dim) in a new location (X1,X2,X3....)

    Hope this helps.

    Cheers
    Brian
     
  6. Shay

    Shay Well-Known Member Licensed User

    I think my code is ok (not all the module)
    here it is:

    on class global:
    Private WayPoints As List

    here I have some loop of:
    decodePoly(OverViewPolyLine,listMpi)

    Code:
    Sub decodePoly(encoded As String, poly As List)
        
    Private b, index, Lat, Lng, dlat, dlng, flat, flng, shift, result As Int : index = 0 : Lat = 0 : Lng = 0
        
    Private MyPoint As LatLng
        
    Private Lat1, Lng1 As Double
       
        
    Do While index < encoded.Length      
            shift = 
    0 : result = 0       
            
    Do While True
                b = 
    Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
                result = 
    Bit.OR(result, Bit.ShiftLeft( Bit.AND( b, 0x1f), shift))
                shift = shift + 
    5
                
    If b < 0x20 Then Exit
            
    Loop
          
            
    If Bit.AND(result, 1) = 1 Then
                dlat = 
    Bit.Not(Bit.ShiftRight(result, 1))
            
    Else
                dlat = 
    Bit.ShiftRight(result, 1)
            
    End If
            Lat = Lat + dlat
           
            shift = 
    0 : result = 0
            
    Do While True
                b = 
    Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
                result = 
    Bit.OR(result, Bit.ShiftLeft(Bit.AND(b, 0x1f), shift))
                shift = shift + 
    5
                
    If b < 0x20 Then Exit
            
    Loop
           
            
    If Bit.AND(result, 1) = 1 Then
                dlng = 
    Bit.Not(Bit.ShiftRight(result, 1))
            
    Else
                dlng = 
    Bit.ShiftRight(result, 1)
            
    End If
            Lng = Lng + dlng
            flat = Lat
            flng = Lng
          
            
    Dim mpiCurrent As MapPointItem
            mpiCurrent.Initialize
            mpiCurrent.iPassed = 
    0
            Lat1 = flat / 
    1E5
            Lng1 = flng / 
    1E5
            MyPoint.Initialize(Lat1,Lng1)
            WayPoints.Add(MyPoint)
    Log(WayPoints)

        
    Loop
      
    End Sub
    anyway the list should not be changed completely since it is declared on global
     
  7. klaus

    klaus Expert Licensed User

    As Brian Robinson allready pointd out, you must dim MyPoint in the loop:
    Code:
    Dim MyPoint As LatLng
    MyPoint.Initialize(Lat1,Lng1)
    WayPoints.Add(MyPoint)
     
  8. Brian Robinson

    Brian Robinson Active Member Licensed User

    Actually it was Erel who pointed it out.

    I just tried to offer a bit of explanation around why to put it there. Hope I didn't confuse things.
     
  9. Shay

    Shay Well-Known Member Licensed User

    Thanks I moved the line
    on Sub decodePoly, line #2 to be above
    WayPoints.Add(MyPoint)
    and issue solved (I still can't understand why, since the list is declared on global, and entire list data cannot be changed - AFAIK)
     
  10. klaus

    klaus Expert Licensed User

    Brian Robinson explained it. If you dim MyPoint only once all MyPoints in the List point to the same instance of MyPoint.
    To have different values for each row you need to dim a new instance of MyPoint for each row.
     
  11. Brian Robinson

    Brian Robinson Active Member Licensed User

    Sorry, I tried my best with the explanation - English is my first language - but not my strong point. :(

    I think the best thing to do would be to grab a book on programming and learn about memory storage and value vs reference as well as the scope of variables. There are so many texts that explain this concept, and once you understand it, it seems very simple, and gives you a better understanding on why. The idea is generally the same from language to language because at the end of it all that is how it works in machine code.

    B4A, and most modern languages pretty much hide and make it much easier to work with these concepts, but they are concepts you need to know to understand what is going on. Sure you can just go "well I just need to remember that if I do the same sort of thing again I have to Instantiate (Dim) the variable just before I use it", but unless you actually understand why you could run into the same frustrations. I was lucky enough to learn to program in "C" and Assembler which gives a great understanding of memory usage and efficiency (but would never go back there).

    I was going to give an explanation here, but it would be re-inventing the wheel and it would be in English, and you may find it easier to understand in your own language.

    Long story short: do a search for "Value Types vs Reference Types" and also "Variable Scope"

    Also, any help you need with this, let me know.

    Cheers
    Brian
     
    moster67 likes this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice