Customizing the model in Swift

Tram Ho

  • As programmers, we often work on applications and systems that consist of many components that are connected in different ways. Especially when using a highly rigorous programming language like Swift , it is difficult to find a way to model the data part that satisfies both the compiler and the easy-to-read codebase .
  • Let’s look at a case that involves customizing multiple model data of the same model data and several different techniques and methods that allow us to handle data safely.

1 / Mixed structures:

  • Assuming that we are working on a cooking application that includes both videos and recipes in text form and the content we get returned from the web service in JSON format is as follows:

  • Structured JSON as above is extremely popular, but creating struct fit it can be quite difficult. We get an array of item including recipes and videos. We will need to write a model where we can decode both customizations simultaneously.
  • One way to do that is to create an ItemType enum that includes instances for our two customizations as well as a unified model data that contains all the properties we encounter and encapsulates ItemCollection :

  • The above approach allows us to decode JSON but it is still not optimal because we are forced to implement most custom properties such as this VideoPlayer :

2 / Complete polymorphism:

  • We try to model data a collection of data into different types. We can create a protocol Item contains all the attributes to be shared between two variants and two type separately:

  • We also want to modify the wrapper ItemCollection of us to include the array for each type either type because otherwise how we will have to constantly enter values for Video or Recipe :

  • To be able to reuse previous Item and ItemCollection implementations and rename them to fit the new purpose:

  • We are ready to Decodable but because we will need to add a few options when doing that:

  • Now let’s write the actual decode . We will start by decode a version of. We will convert ItemCollection items into Video and Recipe as follows:

  • Instead of treating instance as separate implementations with protocol , treat them as instance of the same model . That will have a pretty big impact on our final stage of the model structure.
  • Rename the previous protocol Item to ItemVariant and remove its type attribute:

  • We model our actual item type as an enum as follows:

  • We can greatly simplify the decode implementation that takes place entirely within the new Item itself, and simply check each JSON item’s type value to determine which type of decode :

  • Since our Item implementation is responsible for decode its own instance , we can ItemCollection return ItemCollection simply as an array of Item values ​​allowed based on the default implementation of Decodable :

  • The benefit is that we continue to use specialized models while keeping our decode simple and the overall order of the item remains the same, but the downside is that it requires decompressing each item before using it. use:

  • Although we will have to continue writing the above code whenever we need to access specific data for recipes or Video . We can do it to provide direct access to any of the attributes defined in the ItemVariant protocol and use Swift ‘s subscription lookup feature.
  • Adding the @dynamicMemberLookup attribute to our main item declaration:

  • Since Swift 5.1 we have added support for subscription in a completely safe and easy way as follows:

  • We can now access any properties shared between Video and Recipe (via the ItemVariant protocol ) as if that attribute were defined within the Item type itself. We can convert the allTitle method to the following:

Share the news now

Source : Viblo