前言:隨著iPhone 11的發(fā)布,iOS 13已經(jīng)開始正式使用屉凯。每年發(fā)布新系統(tǒng)立帖,都會(huì)帶來一些新的變化,之前的一些方法的廢棄悠砚,又新增一些新的方法等等晓勇。因此作為應(yīng)用開發(fā)者,為了讓我們的應(yīng)用能在新的系統(tǒng)上流暢運(yùn)行灌旧,不出問題宵蕉,就需要對(duì)新系統(tǒng)進(jìn)行全方位的適配。本文將全面介紹即將到來的iOS 13系統(tǒng)上的一些注意點(diǎn)和新增的黑暗模式节榜,我們的應(yīng)用怎么去適配。
一:iOS 13系統(tǒng)的適配以及變化
1.私有KVC
iOS 13上不允許使用:valueForKey别智、setValue: forKey獲取和設(shè)置私有屬性宗苍,需要使用其它方式修改,不然會(huì)奔潰
如:
[textField setValue:[UIColor red] forKeyPath:@"_placeholderLabel.textColor"];
//UITextField有個(gè)attributedPlaceholder的屬性,我們可以自定義這個(gè)富文本來達(dá)到我們需要的結(jié)果薄榛,替換為
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"輸入"attributes:@{NSForegroundColorAttributeName: [UIColor red]}];
iOS 13 通過 KVC 方式修改私有屬性讳窟,有 Crash 風(fēng)險(xiǎn),謹(jǐn)慎使用敞恋!并不是所有KVC都會(huì)Crash丽啡,要嘗試!
2.通過計(jì)算TabBar上的圖片位置設(shè)置紅點(diǎn)硬猫,紅點(diǎn)位置有偏移
如果之前有通過TabBar上圖片位置來設(shè)置紅點(diǎn)位置补箍,在iOS13上會(huì)發(fā)現(xiàn)顯示位置都在最左邊去了。遍歷UITabBarButton的subViews發(fā)現(xiàn)只有在TabBar選中狀態(tài)下才能取到UITabBarSwappableImageView啸蜜,解決辦法是修改為通過UITabBarButton的位置來設(shè)置紅點(diǎn)的frame坑雅。
3.模態(tài)彈出默認(rèn)交互改變
Defines the presentation style that will be used for this view controller when it is presented modally. Set this property on the view controller to be presented, not the presenter.
If this property has been set to UIModalPresentationAutomatic, reading it will always return a concrete presentation style. By default UIViewController resolves UIModalPresentationAutomatic to UIModalPresentationPageSheet, but other system-provided view controllers may resolve UIModalPresentationAutomatic to other concrete presentation styles.
iOS 13 的 presentViewController 默認(rèn)有視差效果,模態(tài)出來的界面現(xiàn)在默認(rèn)都下滑返回衬横。 一些頁面必須要點(diǎn)確認(rèn)才能消失的裹粤,需要適配。如果項(xiàng)目中頁面高度全部是屏幕尺寸蜂林,那么多出來的導(dǎo)航高度會(huì)出現(xiàn)問題遥诉。
控制器的 modalPresentationStyle 默認(rèn)值變了:
查閱了下 UIModalPresentationStyle枚舉定義拇泣,赫然發(fā)現(xiàn)iOS 13新加了一個(gè)枚舉值:
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) {
UIModalPresentationFullScreen = 0,
UIModalPresentationPageSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
UIModalPresentationFormSheet API_AVAILABLE(ios(3.2)) API_UNAVAILABLE(tvos),
UIModalPresentationCurrentContext API_AVAILABLE(ios(3.2)),
UIModalPresentationCustom API_AVAILABLE(ios(7.0)),
UIModalPresentationOverFullScreen API_AVAILABLE(ios(8.0)),
UIModalPresentationOverCurrentContext API_AVAILABLE(ios(8.0)),
UIModalPresentationPopover API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(tvos),
UIModalPresentationBlurOverFullScreen API_AVAILABLE(tvos(11.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(watchos),
UIModalPresentationNone API_AVAILABLE(ios(7.0)) = -1,
UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2,
};
如果你完全接受蘋果的這個(gè)默認(rèn)效果,那就不需要去修改任何代碼矮锈。
如果霉翔,你原來就比較細(xì)心,已經(jīng)設(shè)置了modalPresentationStyle的值愕难,那你也不會(huì)有這個(gè)影響早龟。
對(duì)于想要找回原來默認(rèn)交互的同學(xué),直接設(shè)置如下即可:
self.modalPresentationStyle = UIModalPresentationOverFullScreen;
4.MPMoviePlayerController 在iOS 13已經(jīng)不能用了
'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
既然不能用了猫缭,就只能使用其他播放器了
5.UISearchBar顯示問題
升級(jí)到iOS13葱弟,UISearchController上的SearchBar顯示異常,查看后發(fā)現(xiàn)對(duì)應(yīng)的高度只有1px,目前沒找到具體導(dǎo)致的原因猜丹,解決辦法是使用KVO監(jiān)聽frame值變化后設(shè)置去應(yīng)該顯示的高度,另外芝加,也可能出現(xiàn)一些其他的顯示問題,這個(gè)需要自己去一個(gè)個(gè)查看射窒,在去解決相應(yīng)的問題藏杖。
黑線處理crash
之前為了處理搜索框的黑線問題會(huì)遍歷后刪除UISearchBarBackground,在iOS13會(huì)導(dǎo)致UI渲染失敗crash;解決辦法是設(shè)置UISearchBarBackground的layer.contents為nil
public func clearBlackLine() {
for view in self.subviews.last!.subviews {
if view.isKind(of: NSClassFromString("UISearchBarBackground")!) {
view.backgroundColor = UIColor.white
view.layer.contents = nil
break
}
}
}
6.iOS 13 DeviceToken有變化
NSString *dt = [deviceToken description];
dt = [dt stringByReplacingOccurrencesOfString: @"<" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @">" withString: @""];
dt = [dt stringByReplacingOccurrencesOfString: @" " withString: @""];
這段代碼運(yùn)行在 iOS 13 上已經(jīng)無法獲取到準(zhǔn)確的DeviceToken字符串了脉顿,
iOS 13 通過[deviceToken description]獲取到的內(nèi)容已經(jīng)變了蝌麸。
解決方案:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
if (![deviceToken isKindOfClass:[NSData class]]) return;
const unsigned *tokenBytes = [deviceToken bytes];
NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
NSLog(@"deviceToken:%@",hexToken);
}
7.提供第三方登錄的注意啦
Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.
如果 APP 支持三方登陸(Facbook、Google艾疟、微信来吩、QQ、支付寶等)蔽莱,就必須支持蘋果登陸弟疆,且要放前邊。關(guān)于蘋果登錄的盗冷,大家可以自行百度: ASAuthorizationAppleIDButton這個(gè)關(guān)鍵詞怠苔,進(jìn)行具體的查看
對(duì)于非iOS平臺(tái),Web仪糖、Android 可以使用 JS SDK柑司,網(wǎng)頁版本登錄,邏輯類似锅劝、Facebook帜羊、QQ登錄。
建議支持使用Apple提供的按鈕樣式鸠天,已經(jīng)適配各類設(shè)備讼育。個(gè)人理解蘋果的大概意思應(yīng)該是,使用第三方登錄的應(yīng)用,都要提供蘋果登錄這個(gè)模式奶段,如果不提供饥瓷,那么在審核的時(shí)候,審核應(yīng)該不給通過痹籍。
8.即將廢棄的 LaunchImage
從 iOS 8 的時(shí)候呢铆,蘋果就引入了 LaunchScreen,我們可以設(shè)置 LaunchScreen來作為啟動(dòng)頁蹲缠。當(dāng)然棺克,現(xiàn)在你還可以使用LaunchImage來設(shè)置啟動(dòng)圖。不過使用LaunchImage的話线定,要求我們必須提供各種屏幕尺寸的啟動(dòng)圖娜谊,來適配各種設(shè)備,隨著蘋果設(shè)備尺寸越來越多斤讥,這種方式顯然不夠 Flexible纱皆。而使用 LaunchScreen的話,情況會(huì)變的很簡(jiǎn)單芭商, LaunchScreen是支持AutoLayout+SizeClass的派草,所以適配各種屏幕都不在話下。
注意啦??铛楣,從2020年4月開始近迁,所有使? iOS13 SDK的 App將必須提供 LaunchScreen,LaunchImage即將退出歷史舞臺(tái)簸州。
- Status Bar(狀態(tài)欄)更新
iOS13對(duì)Status BarAPI做了修改
之前Status Bar有兩種狀態(tài):
UIStatusBarStyleDefault 文字黑色
UIStatusBarStyleLightContent 文字白色
iOS13以前Status Bar樣式
iOS13以后有三種狀態(tài):
UIStatusBarStyleDefault自動(dòng)選擇黑色或白色
UIStatusBarStyleDarkContent文字黑色
UIStatusBarStyleLightContent文字白色
iOS13以后Status Bar有三種狀態(tài)
10.UIActivityIndicatorView加載視圖
iOS13對(duì)UIActivityIndicatorView的樣式也做了修改
之前有三種樣式:
UIActivityIndicatorViewStyleGray 灰色
UIActivityIndicatorViewStyleWhite 白色
UIActivityIndicatorViewStyleWhiteLarge 白色(大型)
iOS13廢棄了以上三種樣式钳踊,而用以下兩種樣式代替:
UIActivityIndicatorViewStyleLarge (大型)
UIActivityIndicatorViewStyleMedium (中型)
iOS13通過color屬性設(shè)置其顏色
示例:
- (UIActivityIndicatorView *)loadingView {
if (_loadingView == nil) {
_loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
[_loadingView setColor:[UIColor systemBackgroundColor]];
[_loadingView setFrame:CGRectMake(0, 0, 200, 200)];
[_loadingView setCenter:self.view.center];
}
return _loadingView;
}
效果:
iOS13之前的三種樣式
iOS13以后的兩種樣式
現(xiàn)在,我們來看看勿侯,在iOS 13系統(tǒng)新增的最重大的功能,就是黑暗模式缴罗,蘋果自己叫深色模式:Dark Mode:
Apps on iOS 13 are expected to support dark mode Use system colors and materials Create your own dynamic colors and images Leverage flexible infrastructure
Apps on iOS 13 are expected to support dark mode Use system colors and materials
查看了網(wǎng)上有些人說助琐,iOS 13系統(tǒng)上,必須要適配黑暗模式面氓,不然審核是通不過的兵钮,但我看了蘋果自己的說明,我個(gè)人的理解意思是舌界,這個(gè)不是強(qiáng)制要求掘譬,開發(fā)者可以自己選。好了呻拌,繼續(xù)往下看這個(gè)葱轩,下來會(huì)根據(jù)以下幾個(gè)方面講解黑暗模式:
一、適配Dark Mode:顏色適配,圖片適配
二靴拱、獲取當(dāng)前模式(Light or Dark)
三垃喊、其他內(nèi)容
四、總結(jié)
首先看看我們的效果圖:
image.png
一袜炕、適配Dark Mode
開發(fā)者主要從顏色和圖片兩個(gè)方面進(jìn)行適配本谜,我們不需要關(guān)心切換模式時(shí)該如何操作,這些都由系統(tǒng)幫我們實(shí)現(xiàn)
顏色適配:
iOS13 之前 UIColor只能表示一種顏色偎窘,而從 iOS13 開始UIColor是一個(gè)動(dòng)態(tài)的顏色乌助,在Light Mode和Dark Mode可以分別設(shè)置不同的顏色。
iOS13系統(tǒng)提供了一些動(dòng)態(tài)顏色
@property (class, nonatomic, readonly) UIColor *systemBrownColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemIndigoColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemGray2Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray3Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray4Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray5Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGray6Color API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *labelColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *secondaryLabelColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *tertiaryLabelColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *quaternaryLabelColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *linkColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *placeholderTextColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *separatorColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *opaqueSeparatorColor API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
@property (class, nonatomic, readonly) UIColor *systemBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemGroupedBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemGroupedBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemGroupedBackgroundColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *systemFillColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *secondarySystemFillColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *tertiarySystemFillColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
@property (class, nonatomic, readonly) UIColor *quaternarySystemFillColor API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos);
① 實(shí)例:
[self.view setBackgroundColor:[UIColor systemBackgroundColor]];
[self.titleLabel setTextColor:[UIColor labelColor]];
[self.detailLabel setTextColor:[UIColor placeholderTextColor]];
② 效果展示:
系統(tǒng)UIColor樣式
用法和iOS13之前的一樣陌知,使用系統(tǒng)提供的這些動(dòng)態(tài)顏色他托,不需要其他的適配操作
③ 自定義動(dòng)態(tài)UIColor
在實(shí)際開發(fā)過程,系統(tǒng)提供的這些顏色還遠(yuǎn)遠(yuǎn)不夠纵诞,因此我們需要?jiǎng)?chuàng)建更多的動(dòng)態(tài)顏色
初始化動(dòng)態(tài)UIColor方法
iOS13 UIColor增加了兩個(gè)初始化方法上祈,使用以下方法可以創(chuàng)建動(dòng)態(tài)UIColor
注:一個(gè)是類方法,一個(gè)是實(shí)例方法
- (UIColor *)colorWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
- (UIColor *)initWithDynamicProvider:(UIColor * (^)(UITraitCollection *))dynamicProvider API_AVAILABLE(ios(13.0), tvos(13.0)) API_UNAVAILABLE(watchos);
這兩個(gè)方法要求傳一個(gè)block進(jìn)去
當(dāng)系統(tǒng)在LightMode和DarkMode之間相互切換時(shí)就會(huì)觸發(fā)此回調(diào)
這個(gè)block會(huì)返回一個(gè)UITraitCollection類
我們需要使用其屬性u(píng)serInterfaceStyle浙芙,它是一個(gè)枚舉類型登刺,會(huì)告訴我們當(dāng)前是LightMode還是DarkMode
typedef NS_ENUM(NSInteger, UIUserInterfaceStyle) {
UIUserInterfaceStyleUnspecified,
UIUserInterfaceStyleLight,
UIUserInterfaceStyleDark,
} API_AVAILABLE(tvos(10.0)) API_AVAILABLE(ios(12.0)) API_UNAVAILABLE(watchos);
實(shí)例:
UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return [UIColor redColor];
}
else {
return [UIColor greenColor];
}
}];
[self.bgView setBackgroundColor:dyColor];
效果展示:
自定義UIColor效果
接下來我們看看如何適配圖片:
2.圖片適配
打開Assets.xcassets
新建一個(gè)Image set
默認(rèn)顯示效果
打開右側(cè)工具欄,點(diǎn)擊最后一欄嗡呼,找到Appearances纸俭,選擇Any,Dark
側(cè)邊欄
將兩種模式下不同的圖片資源都拖進(jìn)去
兩種不同模式
使用該圖片:
[_logoImage setImage:[UIImage imageNamed:@"icon_logo"]];
最終效果圖
大功告成南窗,完成顏色和圖片的Dark Mode適配揍很,是不是很easy呢!
獲取當(dāng)前模式(Light or Dark)
有時(shí)候我們需要知道當(dāng)前處于什么模式,并根據(jù)不同的模式執(zhí)行不同的操作
iOS13中CGColor依然只能表示單一的顏色
通過調(diào)用UITraitCollection.currentTraitCollection.userInterfaceStyle
獲取當(dāng)前模式
實(shí)例:
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.titleLabel setText:@"DarkMode"];
}
else {
[self.titleLabel setText:@"LightMode"];
}
其他
1.監(jiān)聽模式切換
有時(shí)我們需要監(jiān)聽系統(tǒng)模式的變化万伤,并作出響應(yīng)
那么我們就需要在需要監(jiān)聽的viewController中窒悔,重寫下列函數(shù)
/ 注意:參數(shù)為變化前的traitCollection
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection;
// 判斷兩個(gè)UITraitCollection對(duì)象是否不同
- (BOOL)hasDifferentColorAppearanceComparedToTraitCollection:(UITraitCollection *)traitCollection;
示例:
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
// trait發(fā)生了改變
if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
// 執(zhí)行操作
}
}
2.CGColor適配
我們知道iOS13后,UIColor能夠表示動(dòng)態(tài)顏色敌买,但是CGColor依然只能表示一種顏色简珠,那么對(duì)于CALayer等對(duì)象如何適配暗黑模式呢?當(dāng)然是利用前面提到的監(jiān)聽模式切換的方法啦。
方式一:resolvedColor
// 通過當(dāng)前traitCollection得到對(duì)應(yīng)UIColor
// 將UIColor轉(zhuǎn)換為CGColor
- (UIColor *)resolvedColorWithTraitCollection:(UITraitCollection *)traitCollection;
實(shí)例:
-
(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return [UIColor redColor];
}
else {
return [UIColor greenColor];
}
}];
UIColor *resolvedColor = [dyColor resolvedColorWithTraitCollection:previousTraitCollection];
layer.backgroundColor = resolvedColor.CGColor;
方式二:performAsCurrent
// 使用當(dāng)前trainCollection調(diào)用此方法
- (void)performAsCurrentTraitCollection:(void (^)(void))actions;
示例:
-
(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return [UIColor redColor];
}
else {
return [UIColor greenColor];
}
}];
[self.traitCollection performAsCurrentTraitCollection:^{
layer.backgroundColor = dyColor.CGColor;
}];
}
方式三:最簡(jiǎn)單的方法,直接設(shè)置為一個(gè)動(dòng)態(tài)UIColor的CGColor即可
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return [UIColor redColor];
}
else {
return [UIColor greenColor];
}
}];
layer.backgroundColor = dyColor.CGColor;
}
??!!! 設(shè)置layer顏色都是在traitCollectionDidChange中虹钮,意味著如果沒有發(fā)生模式切換聋庵,layer將會(huì)沒有顏色,需要設(shè)置一個(gè)基本顏色
3.模式切換時(shí)打印log
模式切換時(shí)自動(dòng)打印log芙粱,就不需要我們一次又一次的執(zhí)行po命令了
在Xcode菜單欄Product->Scheme->Edit Scheme
選擇Run->Arguments->Arguments Passed On Launch
添加以下命令即可:
-UITraitCollectionChangeLoggingEnabled YES
模式切換打印log
4.強(qiáng)行設(shè)置App模式
當(dāng)系統(tǒng)設(shè)置為L(zhǎng)ight Mode時(shí)祭玉,對(duì)某些App的個(gè)別頁面希望一直顯示Dark Mode下的樣式,這個(gè)時(shí)候就需要強(qiáng)行設(shè)置當(dāng)前ViewController的模式了
// 設(shè)置當(dāng)前view或viewCongtroller的模式
@property(nonatomic) UIUserInterfaceStyle overrideUserInterfaceStyle;
示例:
// 設(shè)置為Dark Mode即可
[self setOverrideUserInterfaceStyle:UIUserInterfaceStyleDark];
?? 注意!!!
當(dāng)我們強(qiáng)行設(shè)置當(dāng)前viewController為Dark Mode后春畔,這個(gè)viewController下的view都是Dark Mode
由這個(gè)ViewController present出的ViewController不會(huì)受到影響脱货,依然跟隨系統(tǒng)的模式岛都,
不想適配暗黑模式可以關(guān)閉暗黑模式:
在Info.plist文件中添加Key:User Interface Style,值類型設(shè)置為String,值為L(zhǎng)ight蹭劈,就可以不管在什么模式下疗绣,軟件只支持淺色模式,不支持黑暗模式铺韧,如果只想軟件支持黑暗模式多矮,則可以把類型設(shè)置為:Dark
5.NSAttributedString優(yōu)化:
對(duì)于UILabel、UITextField哈打、UITextView塔逃,在設(shè)置NSAttributedString時(shí)也要考慮適配Dark Mode,否則在切換模式時(shí)會(huì)與背景色融合料仗,造成不好的體驗(yàn)
不建議的做法:
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic];
推薦的做法:
// 添加一個(gè)NSForegroundColorAttributeName屬性
NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:16],NSForegroundColorAttributeName:[UIColor labelColor]};
NSAttributedString *str = [[NSAttributedString alloc] initWithString:@"富文本文案" attributes:dic];
6.iOS13 中設(shè)置 UITabBarItem的選中以及未選中字體顏色無效
iOS13 碰到設(shè)置tabbar字體為選中狀態(tài)顏色湾盗,正常切換沒有問題,push后再返回立轧,選中顏色變化系統(tǒng)藍(lán)色格粪,以及其他未選中的字體顏色也變?yōu)橄到y(tǒng)的藍(lán)牙
目前碰到這種狀況有兩種方法:
這個(gè)是子視圖影響所以用tintColor試試
tintColor有尋找和傳遞
1、尋找也就是通過get方法獲取屬性的值氛改。
2帐萎、傳遞也就是當(dāng)主動(dòng)改變tintColor時(shí)
解決辦法如下,在iOS 13上面可以用以下方法設(shè)置字體顏色,其他系統(tǒng)可以保持原來的設(shè)置方法不變:
if (@available(iOS 13, *)) {
self.tabBar.unselectedItemTintColor = [UIColor whiteColor]; //未選中字體的顏色
self.tabBar.tintColor = [UIColor whiteColor]; //選中字體的顏色
} else {
// Fallback on earlier versions
}
最后胜卤,關(guān)于iOS13 的介紹疆导,大概就這些吧。想要看的更加詳細(xì)的介紹的話葛躏,大家可以自己去查閱更多的資料澈段。
參考文章:iOS13 暗黑模式(Dark Mode)適配之OC版
作者:飛哥Andy
鏈接:http://www.reibang.com/p/0be7ce07cb4f
來源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)舰攒,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處败富。