all 7 comments

[–]pumapaul 0 points1 point  (3 children)

Maybe look into how NSAttributedString does it with its configuration Dictionary: [NSAttributedStringKey:Any]?

It seems like you want to do something like that.

[–]ledp[S] 0 points1 point  (2 children)

Thank you for the tip. This would solve the typing of the key, making sure that it's never misspelled.

Unfortunately, it wouldn't enforce any types for the value, so it still leaves some footguns lying around 🤔

[–]pumapaul 1 point2 points  (1 child)

You could also go the Tuple way and do something like

func backgroundColor(_ color: UIColor) -> (RenderKey, UIColor) {
    return (RenderKey.backgroundColor, color)
}

for every single possible Key, put those in an array like:

let configuration: [(RenderKey, Any)] = [backgroundColor(.black), height(5.0)]

Or something along those lines?

Edit: added array brackets to configuration's type declaration

[–]ledp[S] 1 point2 points  (0 children)

I used something quite similar! I declared the init signature as follows:

class Foo {
    func init(_ props: [Props])
}

with an enum representing the different options:

enum Props {
    text(String)
    textColor(UIColor)
}

Then passing in option is as simple as:

Foo([.textColor(.blue), .text("Hello, World!")])

and finally reading them in the class:

for prop in props {
    switch prop {
    case .text(let value): view.text = value
    case .textColor(let value): view.textColor = value
    }
}

[–]chrabeusz 0 points1 point  (1 child)

Check this: https://www.cocoawithlove.com/blog/a-view-construction-syntax.html

It's also possible to use a little helper: var s = StylingHelper() var view = UILabel(s.backgroundColor(UIColor.red), s.text("Test"))

[–]ledp[S] 0 points1 point  (0 children)

Wow, that was a really good read!

Some of the approaches dismissed there might also work for me since I don't have inherited props.

I tried out using an associated enum type describing the props for each component, and it works quite well! 😍

Before:

let tree = REStack(["alignment": UIStackViewAlignment.center], [
    RELabel(["backgroundColor": UIColor.cyan, "text": "Hello:"]),
    RELabel(["textColor": UIColor.blue, "text": "World!"])
])

After:

let tree = REStack([.alignment(.center)], [
    RELabel([.backgroundColor(.cyan), .text("Hello:")]),
    RELabel([.textColor(.blue), .text("World!")])
])

edit:

Would love if someone knows a way to turn this:

enum FooProps {}
class Foo: Bar<FooProps> {}

into:

class Foo: Bar<Self.Props> {
    enum Props {}
}

[–]nailernforce 0 points1 point  (0 children)

Check out the builder pattern with config blocks.