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

Style not applied to UITabBarItem #1

Closed
ghost opened this issue Mar 12, 2017 · 8 comments
Closed

Style not applied to UITabBarItem #1

ghost opened this issue Mar 12, 2017 · 8 comments

Comments

@ghost
Copy link

ghost commented Mar 12, 2017

Hello,
I tried to apply a Style to UITabBarItem, but the Style-block is never called. (All other Styles are working)

Style<FooterFontStyle, UITabBarItem> { $0.setTitleTextAttributes([NSFontAttributeName: FontSmall], for: .normal) }
extension UITabBarItem: FooterFontStyle { }

Can you tell me, if I'm making something wrong, or fix this problem?
I could not figure out, why StyleSheet is not working for UITabBarItems.

Regards and Thanks

@werediver
Copy link
Owner

Hello.
StyleSheet is pretty close to UIAppearance under the hood. It means that StyleSheet needs a safe and universal method to inject its handler into a styled class. This is possible for UIView subclasses because of their known life-cycle, but not for any arbitrary class.

Notice that UITabBarItem inherits from UIBarItem and NSObject, but not from UIView, therefore you cannot directly apply neither StyleSheet nor UIAppearance to UITabBarItem or its subclasses.

You need to find a way to operate on UIView subclasses to achieve the desired look & feel.
Hope this help.

@ghost
Copy link
Author

ghost commented Mar 12, 2017

Hello,
Thank you for your quick response.
You are completely right.
I will use UIAppearance.

Thanks and regards

@ghost ghost closed this as completed Mar 12, 2017
@werediver
Copy link
Owner

I've thought over your question a bit more, and it seems my answer wasn't comprehensive.

First, UIBarItem conforms to UIAppearance protocol, and it means that UIAppearance can be applied to UIBarItem and its subclasses. It also means that StyleSheet can also be applied to them, just use RootStyle.autoapply(style: appStyle, mode: .Appearance) when setting up StyleSheet in your app.

StyleSheet supports two modes for installing its handler into UIKit. One is direct method-swizzling and the other is "hitchhiking" UIAppearance. The latter means that StyleSheet will work everywhere where UIAppearance does.

It seems that .Appearance mode should be the default one.

Second, it's possible to support styling for UIViewController and its subclasses, if it really makes sense.

I would appreciate you (and anyone interested) for providing additional feedback taking into account the above.

@werediver werediver reopened this Mar 13, 2017
@werediver
Copy link
Owner

werediver commented Mar 13, 2017

One more update.

StyleSheet v2.1.0 can't work with UIBarItem and its subclasses as is, though it's easy to cover this hierarchy. In theory. In practice, I can't manage to kickstart UIAppearance for UIBarButtonItem on an iOS 10 Simulator at all. Looks like Apple wrecked UIAppearance support in UIBarItem and/or UIBarButtonItem at some point. Can anyone check it, please?

Anyway, UIViewController styling support is still possible, if considered useful (so your feedback is welcome!).

@werediver
Copy link
Owner

werediver commented Mar 13, 2017

I've discovered very surprising behavior of UIBarButtonItem with relation to UIAppearance styling. It seems not possible to apply a style to an instance of UIBarButtonItem, and it's necessary to subclass first and apply a style directly to a subclass, otherwise the style is just ignored. Moreover, even after subclassing it's not possible to call a custom setter added in the subclass through its appearance-proxy.

In the absence of an adequate workaround, I would prefer not to deal with this mess. There is RootStyle.apply(to:) for manual style application and possibly a support for UIViewController styling.

Any thoughts?

@werediver
Copy link
Owner

And it's impossible to override a method in a UIBarButtonItem subclass. But it's not a class-cluster. Very dark voodoo there.

@ghost
Copy link
Author

ghost commented Mar 13, 2017

Hello.
First of all, I think .Swizzle should be the default one, because UIAppearance is very limited. And .Swizzle work like a charm (except in special cases like this one :)).

Second:
Currently I'm not able to apply a Style with .Appearance (The Block is not called) to a subclass of UITabBarItem.
try RootStyle.autoapply(style: StyleSheet(styles: [ Style<FooterFontStyle, TestBarItem> { $0.setTitleTextAttributes([NSFontAttributeName: FontMedium17], for: .normal) } ]), mode: .Appearance)
class TestBarItem: UITabBarItem, FooterFontStyle { }

@werediver
Copy link
Owner

Okay, here is the final conclusion.

UIBarItem, UIBarButtonItem and their subclasses doesn't have a view-like life-cycle, therefore StyleSheet can't hook up to them as it does with UIView subclasses using direct swizzling.

It's also not possible to hitchhike UIAppearance with these classes, because their appearance-proxy doesn't seems to forward invocations as expected (it possibly changes the target).

It doesn't seem possible to amend the behavior of the standard appearance-proxy (without dirty hacks) as well.

It also doesn't seem to be a good idea to monkey-patch all the (known) UIBarItem/UIBarButtonItem consumers to apply appearance.

So I see no appropriate way to solve the issue at the moment. Will document it in the README.md.

This was referenced Sep 28, 2018
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

No branches or pull requests

1 participant