Skip to content

Draft for generic support #263

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

foyoodo
Copy link

@foyoodo foyoodo commented Sep 17, 2024

Hi, I wanted to ask if there are any plans to add generic support to FlexLayout. This would allow for more flexible usage, such as the following code example:

extension Flex where Base: UILabel {

    var text: String? {
        get { base?.text }
        set { base?.text = newValue; markDirty() }
    }
}

I’ve made some changes to the code, and I’m submitting this as a draft for review. Let me know if this is something that could be considered.

Thanks!

@foyoodo foyoodo marked this pull request as ready for review December 14, 2024 17:27
@nuomi1
Copy link
Contributor

nuomi1 commented Dec 15, 2024

You could use this to enable auto markDirty. :)

extension UIView {

    static func enableFlexAutoMarkDirty() {
        swizzle(
            classType: UIView.self,
            origin: #selector(UIView.invalidateIntrinsicContentSize),
            swizzled: #selector(UIView.flex_invalidateIntrinsicContentSize)
        )

        // UILabel().invalidateIntrinsicContentSize doesn't call super in some iOS versions
        if class_getInstanceMethod(UILabel.self, #selector(UILabel.invalidateIntrinsicContentSize))
            != class_getInstanceMethod(UIView.self, #selector(UIView.invalidateIntrinsicContentSize)) {
            swizzle(
                classType: UILabel.self,
                origin: #selector(UILabel.invalidateIntrinsicContentSize),
                swizzled: #selector(UILabel.flex_uilabel_invalidateIntrinsicContentSize)
            )
        }

        // UITextView().invalidateIntrinsicContentSize doesn't call super in some iOS versions
        if class_getInstanceMethod(UITextView.self, #selector(UITextView.invalidateIntrinsicContentSize))
            != class_getInstanceMethod(UIView.self, #selector(UIView.invalidateIntrinsicContentSize)) {
            swizzle(
                classType: UITextView.self,
                origin: #selector(UITextView.invalidateIntrinsicContentSize),
                swizzled: #selector(UITextView.flex_uitextview_invalidateIntrinsicContentSize)
            )
        }
    }
}

private extension UIView {

    @objc
    func flex_invalidateIntrinsicContentSize() {
        flex_invalidateIntrinsicContentSize()

        if isFlexEnabled {
            flex.markDirty()
        }
    }
}

private extension UILabel {

    @objc
    func flex_uilabel_invalidateIntrinsicContentSize() {
        flex_uilabel_invalidateIntrinsicContentSize()

        if isFlexEnabled {
            flex.markDirty()
        }
    }
}

private extension UITextView {

    @objc
    func flex_uitextview_invalidateIntrinsicContentSize() {
        flex_uitextview_invalidateIntrinsicContentSize()

        if isFlexEnabled {
            flex.markDirty()
        }
    }
}

@foyoodo
Copy link
Author

foyoodo commented Dec 15, 2024

You could use this to enable auto markDirty. :)

Hi @nuomi1 👋 Thanks a lot for the response and code snippet. I believe this approach is effective, but could it potentially result in unnecessary markDirty calls, triggering a view relayout? For instance, when updating a grow-width UILabel that already has enough space to accommodate the updated text?

However, I still believe that adding generic support could offer better extensibility. For example, consider the following code - and yes, it might seem unusual, but I have indeed written similar code before :)

extension Flex where Base: UIVisualEffectView {
    func addItem<Item>(_ view: Item) -> Flex<Item> {
        if let host = base {
            return host.contentView.flex.addItem(view)
        } else {
            preconditionFailure("Trying to modify deallocated host view")
        }
    }
}

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants