I want to use variable names in dot notation in Swift.
I'm wrestling with trying to make sense of JSON in Swift, and having a really hard time doing things that are so easy in JS (like cycling through objects, etc).
I have variables of custom types:
var questionConfiguration: QuestionConfiguration
var priorityConfiguration: PriorityConfiguration
Each of these types has an attribute, displayOrder
, I want to access this dynamically. I have tried various things, including the following (i
is a variable of type Int):
var configs = [self.questionConfiguration, self.priorityConfiguration]
print([configs[i]].displayOrder)
var configs = ["questionConfiguration", "priorityConfiguration"]
print([configs[i]].displayOrder)
How can I achieve this?
EDIT:
struct QuestionConfiguration: Codable {
var displayOrder: Int
}
struct PriorityConfiguration: Codable {
var displayOrder: Int
}
CodePudding user response:
You can create a protocol for same property name then you can access it easily
protocol SameProp {
var displayOrder: Int {get set}
}
class QuestionConfiguration : SameProp {
var displayOrder : Int = 4
}
class PriorityConfiguration : SameProp {
var displayOrder : Int = 6
}
var questionConfiguration: QuestionConfiguration = QuestionConfiguration()
var priorityConfiguration: PriorityConfiguration = PriorityConfiguration()
var configs = [questionConfiguration, priorityConfiguration] as [SameProp]
for elements in configs{
print(elements.displayOrder) // will print 4 and 6
}
CodePudding user response:
Swift is very particular about data types and I suspect you are experiencing challenges because of it.
When you do this:
var configs = [self.questionConfiguration, self.priorityConfiguration]
In Swift, all the elements in an array have to have the same type. You've not given Swift any hints about what types this array should contain so the compiler has to infer a type. QuestionConfiguration
and PriorityConfiguration
are two different types. So the compiler is likely to infer that configs
is of type [Any]
also called Array<Any>
.
Then you try something like this:
configs[i].displayOrder
(not sure why your code has the extra brackets)
But configs[i]
is inferred to be of type Any
and that type doesn't have a displayOrder
property so the compiler complains.
You need to tell the compiler that these types share some properties. One way to do that would be to add a protocol
that describes what they share:
protocol DisplayOrderable {
var displayOrder: Int { get }
}
struct QuestionConfiguration: DisplayOrderable, Codable {
var displayOrder: Int
}
struct PriorityConfiguration: DisplayOrderable, Codable {
var displayOrder: Int
}
then you could use
var configs: [any DisplayOrderable] = [self.questionConfiguration, self.priorityConfiguration]
And configs[i].displayOrder
should work.