ClassyKit / Classy

Expressive, flexible, and powerful stylesheets for UIView and friends.
http://classykit.github.io/Classy/
MIT License
740 stars 76 forks source link

support for UISearchBar #98

Closed atsepkov closed 7 years ago

atsepkov commented 9 years ago

Thanks for the project guys. I really appreciate that Classy made it easy for me to style/simplify the UI of my app without spending days doing so in the code. One thing that still refuses to be styled, however, is UISearchBar. Having researched this element and its structure, I'm now convinced that it's the worst-designed element in all of UIKit.

The problem is that it stacks several UIView layers within itself, hardcoding a style that only fits basic UI, using background images to fake borders instead of the readily-available and consistent borderWidth/borderColor/cornerRadius properties, hardcodes an unnecessary top and bottom border that can't be removed (but can be hidden via secondary border) and doesn't properly expose any of its underlying hackery to the developer using or inheriting from this class. Luckily, I found a combination of hackery that counters the damage (I know, not the cleanest approach) and creates a simple and clean search box that I would expect:

searchBar.layer.borderColor = UIColor.whiteColor().CGColor // to remove the hardcoded top/bottom borders
searchBar.layer.borderWidth = 1 // same as above
searchBar.barTintColor = UIColor.whiteColor() // conceal ugly background image into the same color as hardcoded into the search window itself (white)

Problem is when I move this to the stylesheet as follows, it seems to have no effect:

UISearchBar {
    bar-tint-color: #ffffff;
    layer: @{
        border-width: 1;
        border-color: #ffffff;
    }
}

But when I replace UISearchBar with ^UIView, the properties set in layer are applied (but not the barTintColor, which is a UISearchBar-only property). I've been struggling with this for a few hours now and have come to a conclusion that UISearchBar is simply ignored by Classy. Is this a bug, a limitation, something else?

Thanks

atsepkov commented 9 years ago

Likewise, nothing that inherits from UISearchBar seems to work (I am using @objc tag, which has worked fine for my other classes).

keithnorm commented 9 years ago

The way Classy works is it swizzles UIView didMoveToWindow to a custom implementation that calls cas_updateStyling. UISearchBar inherits from UIView so you'd think it would call didMoveToWindow but it doesn't. My guess is that UISearchBar overrides didMoveToWindow and never calls super but I don't know for sure since there's no way to know.

So there are 2 ways to fix this. The easiest way is to just call cas_updateStyling manually in your view controller. e.g.

#import <Classy/Classy.h>
[mySearchBar cas_updateStyling];

This isn't ideal because you would have to do it for every UISearchBar instance in your app. This may or may not be a big deal depending on your app.

The other way is to write a UISearchBar extension that swizzles didMoveToWindow the same way Classy does it for UIView See https://github.com/cloudkite/Classy/blob/master/Classy/Additions/UIView%2BCASAdditions.m#L25 for details.

If that doesn't make sense I can send you an example app that fixes it. Also, this would be worth patching back into Classy, imo.

dnedrow commented 7 years ago

@atsepkov , can this issue be closed? I've added Keith's suggestion to a wish list I've created in the wiki.

dnedrow commented 7 years ago

Added to wishlist.