前言
隨著iOS的更新汽纤,大的變動似乎沒有员魏,小的變動卻很多孟岛。而且國內(nèi)的開發(fā)者和國外的有一個很大的不同點兼呵,就是國內(nèi)的求穩(wěn)胆剧,國外的求創(chuàng)新垃沦。我接手過的幾個項目特姐,最低支持的還有iOS7的巷查,普遍的都是iOS8歌馍、9握巢。代碼很少會考慮到iOS12,13以上的新特性松却。2022年4月25號暴浦,蘋果強制打包的SDK必須升級到iOS15,之前是警告我都沒在意晓锻,現(xiàn)在成錯誤了歌焦。最開始我還以為可以像添加真機調(diào)試包那樣不用升級XCode就可以,后來發(fā)現(xiàn)我想多了砚哆。必須升級XCode13独撇,升級XCode的過程也是一波三折。XCode13.2.1必須要MacOS Big Sur(MacOS 11),我的電腦是12年的mini纷铣,然后各種求救卵史,發(fā)現(xiàn)可以通過打補丁升級。反正折騰了一天搜立,搞好了之后升級然后發(fā)現(xiàn)項目出現(xiàn)各種各樣的UIbug以躯,什么導(dǎo)航欄透明變白的,UIBarButtonItem的顏色出現(xiàn)問題啊啄踊,TabBar也出現(xiàn)問題忧设。弄好了之后。我就發(fā)現(xiàn)了一個問題社痛。蘋果的代碼風(fēng)格變了见转,如果你寫過Flutter或者用過SwiftUI,你就越發(fā)覺得蘋果的代碼設(shè)計風(fēng)格變了蒜哀,特別是在UIKit里斩箫,頻繁的出現(xiàn)了一個詞Configuartion
,像UILabel
,UITabbar
,UIButton
,UINavigationBar
等等撵儿。都有與之對應(yīng)的Configuration對象乘客。甚至像基礎(chǔ)類型UIColor
,backgroundColor
都有與之對應(yīng)的Configuration對象。這樣的設(shè)計風(fēng)格初看有些繁瑣淀歇,但用的多了易核,反而很順手,這種設(shè)計模式就是23種設(shè)計模式中的裝飾模式浪默。
UIButtonConfiguration作用的UI元素
UIButtonConfiguration
既然是裝飾模式的一種實踐牡直,那么它必然只會對UI元素做集成,像消息傳遞纳决、手勢碰逸、動作、它是不參與的阔加,顏色文本圖片背景樣式的饵史,它都可以涉及到。
API詳述
弄清楚一個類的成員屬性和方法胜榔,就是寫個案例試一下胳喷。這樣是最快的,比google和百度都好的多夭织。但也僅限于UI類吭露。像一些抽象類,工具類查文檔更適合尊惰。
1. 初始化方法
///主要生成扁平純凈的ButtonConfiguration奴饮,不設(shè)置額外屬性
+ (instancetype)plainButtonConfiguration;
///著色類ButtonConfiguration纬向,主要特點是背景色會半透明化,比如設(shè)置yellowColor的背景色戴卜,而背景的顏色呈現(xiàn)半透明黃色
+ (instancetype)tintedButtonConfiguration;
///半透明灰色背景按鈕逾条,設(shè)置自定義basebackgroundColor會改變背景色,也就是它的優(yōu)先級低一點投剥。
+ (instancetype)grayButtonConfiguration;
///填充類ButtonConfiguration师脂,它的效果和plainButtonConfiguration
類似(暫時未發(fā)現(xiàn)不同)
+ (instancetype)filledButtonConfiguration;
///強制無邊框圓角類ButtonConfiguration,它的優(yōu)先級最高江锨,如果你設(shè)置了btn.layer.cornerRadius, 或者config.background也設(shè)置了圓角或者設(shè)置了config.cornerStyle都不會出現(xiàn)圓角吃警。
+ (instancetype)borderlessButtonConfiguration;
///內(nèi)置設(shè)置了一個圓角為5左右的ButtonConfiguration,但優(yōu)先級小于btn.layer.cornerRadius
+ (instancetype)borderedButtonConfiguration;
///圓角半透明背景的ButtonConfiguration
+ (instancetype)borderedTintedButtonConfiguration;
///圓角個性化ButtonConfiguration啄育,主要體現(xiàn)在背景色不透明酌心,文字和圖片著色和背景色相反(例如黑色背景,白色文字或者白色背景挑豌,黑色文字等)安券。這一前提在于不主動設(shè)置文字顏色和圖片顏色的前提。一般情況下氓英,如果不設(shè)置文字和圖片顏色侯勉,它們的顏色則為系統(tǒng)默認的系統(tǒng)藍色。
+ (instancetype)borderedProminentButtonConfiguration;
///init和new方法是不允許使用的
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
///這個方法铝阐,根據(jù)說明是復(fù)制指定button的ButtonConfiguration址貌。但有一個疑問,這個是實例方法徘键。我試了一下练对,它并不能復(fù)制指定狀態(tài)的configuration,比如normal狀態(tài)是ConfigA,selected狀態(tài)是configB,但復(fù)制只會復(fù)制normal狀態(tài)的值,這和直接btn.configuration = config貌似沒有什么區(qū)別吹害,可能是我研究不深螟凭,沒有發(fā)現(xiàn)它們的區(qū)別
- (instancetype)updatedConfigurationForButton:(UIButton *)button;
2. 屬性變量
///這個是一個關(guān)于background
相關(guān)的config對象,他能處理的內(nèi)容太多了赠制,背景色,圓角挟憔,邊框钟些,陰影,自定義繪圖(貝塞爾曲線繪圖等)绊谭,毛玻璃特效政恍,背景圖片等。只要和背景相關(guān)的UI元素达传,基本都能處理篙耗。
@property (nonatomic, readwrite, strong) UIBackgroundConfiguration *background;
///圓角風(fēng)格枚舉
-1迫筑,固定圓角,0:動態(tài)圓角這兩個值其實差不多宗弯,就是圓角值可以通過btn.layer.cornerRadius和config.background.cornerRadius兩種方式設(shè)置脯燃。1、2蒙保、3這三個值代表內(nèi)置的小辕棚、中、大三個內(nèi)置的圓角邓厕,他的優(yōu)先級比btn.layer.cornerRadius和config.background.cornerRadius
高逝嚎,4是膠囊風(fēng)格,就是圓角切成膠囊狀详恼,優(yōu)先級和1补君、2、3一樣昧互。
@property (nonatomic, readwrite, assign) UIButtonConfigurationCornerStyle cornerStyle;
///內(nèi)置的title字體大小挽铁,優(yōu)先級比attributedTitle
低,也就是你不想自己設(shè)置title和Subtitle字體大小時可以用這個枚舉來參考設(shè)置硅堆,一般來講如果自己的UI設(shè)計和審美不怎么樣屿储,或者無所謂時用一用系統(tǒng)推薦的也不錯,畢竟蘋果的審美你沒法說別人不好吧??渐逃。
@property (nonatomic, readwrite, assign) UIButtonConfigurationSize buttonSize;
///看字面意思就是適配mac端的按鈕樣式够掠。
@property (nonatomic, readwrite, assign) UIButtonConfigurationMacIdiomStyle macIdiomStyle;
///文本顏色,title和Subtitle茄菊,根據(jù)文檔疯潭,它的優(yōu)先級比attributedTitle
和attributedSubtitle
以及它倆的變形器都低。它是一個全局設(shè)置變量面殖,當你想按鈕任何狀態(tài)文本顏色不變時竖哩,可以設(shè)置這個值
@property (nonatomic, readwrite, strong, nullable) UIColor *baseForegroundColor;
///背景色,同理它的優(yōu)先級比background
低脊僚。
@property (nonatomic, readwrite, strong, nullable) UIColor *baseBackgroundColor;
///圖片
@property (nonatomic, readwrite, strong, nullable) UIImage *image;
///圖片顏色變形器相叁,他是一個輸入顏色,再輸出顏色的回調(diào)辽幌,目前不清楚設(shè)置成回調(diào)的好處增淹,反正你在回調(diào)里直接返回你想要設(shè)置的顏色即可
@property (nonatomic, readwrite, copy, nullable) UIConfigurationColorTransformer imageColorTransformer;
///內(nèi)置的系統(tǒng)矢量圖圖標config對象,你可以設(shè)置指定風(fēng)格,大小乌企,顏色的矢量圖圖標作為按鈕的image
@property (nonatomic, readwrite, copy, nullable) UIImageSymbolConfiguration *preferredSymbolConfigurationForImage;
///是否顯示加載轉(zhuǎn)圈的HUD圖標(菊花指示器)虑润,HUD的位置和image是一致的,且hud和image不能同時存在
@property (nonatomic, readwrite, assign) BOOL showsActivityIndicator;
///加載HUD指示器的顏色變形器
@property (nonatomic, readwrite, copy, nullable) UIConfigurationColorTransformer activityIndicatorColorTransformer;
///主標題的文本加酵,富文本及變形器
@property (nonatomic, readwrite, copy, nullable) NSString *title; @property (nonatomic, readwrite, copy, nullable) NSAttributedString *attributedTitle; @property (nonatomic, readwrite, copy, nullable) UIConfigurationTextAttributesTransformer titleTextAttributesTransformer;
///副標題的文本拳喻,富文本及變形器
@property (nonatomic, readwrite, copy, nullable) NSString *subtitle; @property (nonatomic, readwrite, copy, nullable) NSAttributedString *attributedSubtitle; @property (nonatomic, readwrite, copy, nullable) UIConfigurationTextAttributesTransformer subtitleTextAttributesTransformer;
///內(nèi)容四邊距
@property (nonatomic, readwrite, assign) NSDirectionalEdgeInsets contentInsets;
///恢復(fù)默認邊距
- (void)setDefaultContentInsets;
///圖標放置方位哭当,這是一個非常好用的屬性,在這之前冗澈,如果你想制作右圖左文钦勘,上圖下文的圖標,你得設(shè)置imageInset和titleInset渗柿,關(guān)鍵還要計算文本的size和圖標的size个盆。如果你的按鈕通過AutoLayout布局,那么這將計算更加困難朵栖,你必須將UIButton子類化颊亮,在-layoutSubviews
方法中調(diào)整,不然無法獲取titleLabel和imageView的正確尺寸≡山Γ現(xiàn)在有了這個屬性再配合imagePadding
一切變得那么美好了终惑,親愛的(grd)蘋果的工程師,為什么不早點拿出來懊派取雹有?有一點需要說明,這是個option枚舉臼寄,意思是可以多選霸奕,但實際應(yīng)用,并不能達到效果吉拳,比如你想圖標在右上角,你將值設(shè)置為NSDirectionalRectEdgeTop|NSDirectionalRectEdgeTrailing
實際上按鈕還是Y軸居中质帅,右邊顯示,沒有啥效果留攒,目前不明啥原因煤惩,我猜測可能需要配合UIButton的對齊屬性使用才有效果。
@property (nonatomic, readwrite, assign) NSDirectionalRectEdge imagePlacement;
///圖標距文本的距離
@property (nonatomic, readwrite, assign) CGFloat imagePadding;
///標題與子標題的間距炼邀,可以為負值
@property (nonatomic, readwrite, assign) CGFloat titlePadding;
///按鈕文本對齊風(fēng)格
@property (nonatomic, readwrite, assign) UIButtonConfigurationTitleAlignment titleAlignment;
///選中狀態(tài)時是否更新buttonConfigration魄揉,實際用不到,下面會體現(xiàn)
@property (nonatomic, readwrite, assign) BOOL automaticallyUpdateForSelection;
///下面是UIButton的屬性拭宁,這個也是核心洛退,根據(jù)按鈕不同的狀態(tài)切換不同的buttonConfiguration,值得注意的是每個分支結(jié)尾必須重新賦值,示例如下
btn.configurationUpdateHandler = ^(UIButton *b) {
if (b.state == UIControlStateHighlighted) {
btnConfig.showsActivityIndicator = YES;
btnConfig.attributedTitle = [[NSAttributedString alloc] initWithString:@"Highlighted Title" attributes:@{NSForegroundColorAttributeName:[UIColor systemRedColor]}];
btnConfig.attributedSubtitle = [[NSAttributedString alloc] initWithString:@"Highlighted Subtitle" attributes:@{NSForegroundColorAttributeName:[UIColor systemRedColor]}];
btnConfig.image = [UIImage systemImageNamed:@"square.and.arrow.up.fill"];
btnConfig.imageColorTransformer = ^UIColor * _Nonnull(UIColor * _Nonnull color) {
return [UIColor systemPurpleColor];
};
///這個賦值操作必須寫杰标,不然不生效
b.configuration = btnConfig;
}else {
btnConfig.showsActivityIndicator = NO;
btnConfig.attributedTitle = [[NSAttributedString alloc] initWithString:@"Normal Title" attributes:@{NSForegroundColorAttributeName:[UIColor systemRedColor]}];
btnConfig.attributedSubtitle = [[NSAttributedString alloc] initWithString:@"Normal Subtitle" attributes:@{NSForegroundColorAttributeName:[UIColor systemRedColor]}];
btnConfig.image = [UIImage systemImageNamed:@"square.and.arrow.up"];
btnConfig.imageColorTransformer = ^UIColor * _Nonnull(UIColor * _Nonnull color) {
return [UIColor systemOrangeColor];
};
///這個賦值操作必須寫兵怯,不然不生效
b.configuration = btnConfig;
}
};
還有一個要注意的點
///這行代碼生效
btnConfig.baseForegroundColor = [UIColor systemGreenColor];
btn.configuration = btnConfig;
///這行代碼不生效
btnConfig.baseForegroundColor = [UIColor systemRedColor];
總結(jié)
UIButtonConfiguration的優(yōu)點在我看來有以下幾點
- 使用裝飾模式,讓責任區(qū)分更加明確在旱。
- 更多內(nèi)置樣式摇零,在某些場景使用更方便推掸。
- API擴展性更強大了桶蝎,這可能是最重要的一點了驻仅。給按鈕加自定義背景視圖,比如毛玻璃登渣,多彩漸變等噪服。給按鈕添加加載指示器。調(diào)整按鈕的圖文布局等胜茧,在以前的環(huán)境的下粘优,要添加大量代碼。而現(xiàn)在變得更加簡單了呻顽。
唯一的缺點是版本要求太高雹顺,無法兼容低版本。