Post

Beer Diary version 1.2 released

image

Version 1.2 of my BeerDiary app is now live on the iOS AppStore! You can download it here.

Besides some polishing of the UI, the main new feature is import and export of user data. This is done to a ZIP file containing a JSON and jpg files for all photos.

Feel free to drop me a message if you have any comments or feature requests.

Implementation notes

Feel free to skip this section if you’re not that technical 😁

Import / export

Initially I built this feature with the very nice CoreDataJSONExport. I needed to slightly patch it to support the Transformable CoreData attribute.

The only downside of that solution was that my JSON became a quite literal 1:1 representation of my CoreData store. This is not exactly user friendly in case you want to manually generate your own JSON to import beers from another app. I have plenty of entries still in Apple Notes and did not look forward to having to generate all this JSON myself.

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
  "entity_names": [
    "Beer",
    "Photo"
  ],
  "Beer": [
    {
      "name": "Test import beer",
      "comment": "Pretty good",
      "rating": 3,
      "dateAdded": "2020-07-10T00:00:00+0200",
      "_object_id_": "coredata://A2DE09A5-F009-4916-8ABB-4E2125FE9CDB/Beer/p66",
      "brewery": "Vedett",
      "dateModified": "2023-12-18T14:27:40+0100"
    }
  ],
  "Photo": [
    {
      "comment": "",
      "timestamp": "2023-12-18T14:27:37+0100",
      "_object_id_": "x-coredata://A2DE09A5-F009-4916-8ABB-4E2125FE9CDB/Photo/p92",
      "thumbnailData": {
        "data": "todo_4298257A-E521-4A61-BD49-7C1B7133C2B7.jpg"
      },
      "beer": {
        "entity": "Beer",
        "record_id": "x-coredata://A2DE09A5-F009-4916-8ABB-4E2125FE9CDB/Beer/p66"
      },
      "imageData": {
        "data": "import.jpg"
      }
    }
  ]
}

So for each Photo I wanted to import I would need to create an entity with an unique ID and link it from the Beer

So in the end I rewrote the import/export functionality and settled on a custom and more compact JSON format. It was only a bit more work but it makes the output a lot cleaner:

1
2
3
4
5
6
7
8
9
10
11
12
13
[
  {
    "brewery": "San Miguel",
    "comment": "Really awesome",
    "dateAdded": "2021-09-02T22:00:00Z",
    "dateModified": "2023-12-31T14:13:45Z",
    "name": "San Miguel 0",
    "photos": [
      "6B4ADD80-A83F-42E2-82F2-47964617005B.jpg"
    ],
    "rating": 5
  }
]

Other

I have two views: a parent ListView that does some general UI things and embedded in there is a child GroupedView which is re-created each time the search field gets modified (or the user selects a different sort order in the menu).

I took a little shortcut and made the corresponding ListViewmodel available as @environmentObject in both views. One of the things I wanted to do is let the child view decide if the ‘Export’ menu option in parent view should be enabled or not (because this view has the actual SectionedFetchRequest and can count records). So the child view modified the shared ListViewmodel and the menu in the parent view would update as planned.

However, for some strange reason modifying the view model in the child view introduced a bug that any edits would be lost when returning from my detail screen. When I created a simple @State private var exportDisabled in the parent view and passed this as a @Binding to the child view, the problem went away.

So the lesson learned is: don’t modify the shared environment view model in a child view. At least until I properly understand why this interaction caused the bug. 🤓

This post is licensed under CC BY 4.0 by the author.