I am still a beginner and am currently working on a SwiftUI project. I wanted to know what the standard practices or things to consider while writing models in Swift. I couldn’t find a detailed guide anywhere related to it and I don’t have an educational background in CS. I used a common protocol and three structs conforming to the protocol. I wanted to know if there was a better way for knowledge’s sake.
I have a search results screen with 4 different tabs, Player, Groups, Matches(the 3 categories) and, Recent(common), each with their own associated APIs and views to display the objects. The API responses contain an array of related objects. The Player and Matches APIs have only one type of models in their responses while the Groups array contains a single type of object, but some have an additional field. The Recent API has an array containing all three types of objects and some additional fields to the Player object.
The three screens have different views to show the objects, while the Recent screen’s list uses all three views, but are inside an enclosing view with an additional button to remove the object from the array.
Example of the APIs: (Shorter modified response for example purposes)
Player API
{
"status": "SUCCESS",
"message": "Successful response.",
"data": [
{
"id": 7, //Mandatory field
"playerName": "Ronaldo", //Mandatory field
"nickname": "CR7",
"positions": "Striker, Winger, Forward",
"place": "Portugal",
"height": null,
"category": "PLAYER" //Mandatory field
},
{
"id": 10,
"playerName": "Messi",
"nickname": null,
"positions": "Winger, Forward",
"place": "null",
"height": null,
"category": "PLAYER"
}
]
}
** Matches** API
"data": [
{
"id": 1,
"title": "Pool Match 1",
"poolId": 1,
"court": "Santiago Bernabeu",
"searchHistoryId": null,
"category": "MATCHES"
},
...
]
Groups API (Some objects have an additional field based on their subCategory).
"data": [
{
"id": 1,
"title": "Mavericks",
"subCategory": "TEAM",
},
{
"id": 2,
"title": "East Side",
"subCategory": "cluster",
"subCategoryGroupID": 4
}
]
Recent API:
"data": [
{
"id": 1,
"title": "Pool Match 1",
"poolId": 1,
"court": "Santiago Bernabeu",
"searchHistoryId": null,
"category": "MATCHES"
},
{
"id": 1,
"title": "Mavericks",
"subCategory": "TEAM",
"category": "GROUPS",
"subCategoryGroupID": null,
"subCategoryURL": null
},
{
"id": 7,
"playerName": "Ronaldo",
"nickname": "CR7",
"positions": "Striker, Winger, Forward",
"place": "Portugal",
"height": null,
"category": "PLAYER",
"injuryStatus": "Healthy", //Additional field
"bloodGroup": null //Additional field
}
]
I utilised a protocol with the common field and conforming structs in my code.
protocol SearchItem {
id: Int { get set }
category: String { get set }
}
struct PlayerSearchItem: SearchItem {
id: Int
category: String
playerName: String
...
}
struct MatchesSearchItem: SearchItem {
...
In the Recent screen, I stored the data in an array [SearchItem]
and inside the container view, in a switch case based on the ‘category’ type, cast the object as! PlayerSearchItem
or as! MatchesSearchItem
and then pass it to the corresponding view.
switch data.category {
case SearchCategory.Player.rawValue:
let playerData: PlayerSearchItem = data as? PlayerSearchItem
PlayerSearchItemView(data: playerData)
case SearchCategory.Matches.rawValue:
let matchData: MatchesSearchItem = data as? MatchesSearchItem
MatchesSearchItemView()
...
It would be helpful if you could provide insights on how I could improve this. Also about crucial things to consider in general like while writing data models or handling API response models and their corresponding data models. Would using classes be better?