iOS Question Strange behaviour of map

hatzisn

Expert
Licensed User
Longtime User
Hi everyone:

Consider the following two code parts:
B4X:
Sub CreateConfig
    Dim m As Map
    m = CommonFunctions2.ReadConfig
    If m.IsInitialized = False Then m.Initialize
    m.Put("NetNav2", imgNetNavig.Tag)
End Sub

B4X:
Sub ReadConfig As Map
    Dim m1 As Map
    m1 = DBUtils.ExecuteMap(Starter.conn, "SELECT cfg FROM [01_AppSettings]", Null)
    Dim m2 As Map
    Try
        Dim jp As JSONParser
        jp.Initialize(m1.Get("cfg"))
        m2 = jp.NextObject
    Catch
        Log(LastException)
        Dim m3 As Map
        Return m3 'Return uninitialized map
    End Try
    Return m2
End Sub

The code snippet 2 is in a code module called CommonFunctions2. My problem is that in the first code snippet the NetNav2 key with the corresponding value is never added to the map. There is no logic in this.

Any suggestions are welcome.
 

OliverA

Expert
Licensed User
Longtime User
My problem is that in the first code snippet the NetNav2 key with the corresponding value is never added to the map
How do you know this? Btw, m is local to CreateConfig and once that function is called, m is not available anymore.
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
That's correct. It is only the part that I am interested. The full code is the following. The reason I know it is because it is not saved. I checked the code step by step and in Sub CreateConfig after the "If m.IsInitialized..." it is not added the key NetNav2 with the corresponding value (checked with breakpoint and F8). There is already one key with a corresponding value in the map (different key).

B4X:
Sub CreateConfig
    Dim m As Map
    m = CommonFunctions2.ReadConfig
    If m.IsInitialized = False Then m.Initialize
    m.Put("NetNav2", imgNetNavig.Tag)
    CommonFunctions2.SaveConfig(m)
End Sub

B4X:
Sub ReadConfig As Map
    Dim m1 As Map
    m1 = DBUtils.ExecuteMap(Starter.conn, "SELECT cfg FROM [01_AppSettings]", Null)
    Dim m2 As Map
    Try
        Dim jp As JSONParser
        jp.Initialize(m1.Get("cfg"))
        m2 = jp.NextObject
    Catch
        Log(LastException)
        Dim m3 As Map
        Return m3 'Return uninitialized map
    End Try
    Return m2
End Sub

B4X:
Sub SaveConfig(m As Map)
    Dim wf As Map
    wf.Initialize
    wf.Put("ID", 1)
    Dim jg As JSONGenerator
    jg.Initialize(m)
    Dim sJSON As String = jg.ToString
    DBUtils.UpdateRecord(Starter.conn, "01_AppSettings", "cfg", sJSON, wf)
End Sub
 
Last edited:
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Here attached is a test project that demonstrates the problem.
 

Attachments

  • MapProblem.zip
    9.7 KB · Views: 288
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I'm guessing that JSONParser is based on Apple's JSONSerialization (https://developer.apple.com/documentation/foundation/jsonserialization). That class can produce NSArray and NSDictionary objects (among others). Looks like NSDictionary is a non-mutable object (cannot be changed). So either 1) the underlying JSONParser code has to be changed to return a NSMutableDictionary or 2) you have to iterate over the map generated by JSONParser's NextObject and copy it's contents to another map and then return the new, changeable map.
 
Upvote 0

hatzisn

Expert
Licensed User
Longtime User
Thanks OliverA, I tried the second solution which I could perform myself and it worked like a charm. Here is the code:

B4X:
Sub ReadConfig As Map
    Dim m1 As Map
    m1 = DBUtils.ExecuteMap(Starter.conn, "SELECT cfg FROM [01_AppSettings]", Null)
    Dim m2 As Map
    Dim m3 As Map
    Try
        Dim jp As JSONParser
        jp.Initialize(m1.Get("cfg"))
        m2 = jp.NextObject
        m3.Initialize
        For Each k As String In m2.Keys
            m3.Put(k, m2.Get(k))
        Next
    Catch
        Log(LastException)
    End Try
    Return m3
End Sub
 
Upvote 0
Top