Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Draft for generic support #263

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")
        }
    }
}

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

Successfully merging this pull request may close these issues.

2 participants