對於 Plus 機型,在打電話,錄音或開啓熱點等狀態下,狀態欄高度會從20變爲40(非Plus機型和全面屏,狀態欄高度不會變化)。狀態欄高度的變化,會對頁面佈局形成影響,以下圖所示ios
首先,開啓電話模擬狀態欄(模擬器上使用 Command
+ Y
開啓);而後,進入列表頁面;最後,關閉電話模擬狀態欄,在 Plus 機型上,能夠看到列表底部有大約20的間隙(以下圖所示)git
佈局時,採用了 Frame
佈局,進入頁面前,Plus 機型上狀態欄高度爲40,所以列表高度計算時,計算公式 列表高度 = 屏幕高度 - 導航欄高度 - 底部tabBar高度 - 狀態欄高度
中,狀態欄高度會按照40進行計算。github
進入頁面後,關閉電話模擬狀態欄,狀態欄高度會變爲20,列表總體會向上偏移 20 來適配狀態欄高度變化。可是此時,列表高度並無從新計算,賦值和更新,因此致使了上述問題。xcode
//常規狀態欄高度 20
#define KStatusBarHeight [JDBIPhoneGlobalConfig statusBarHight]
// Plus機型下,電話狀態會變成40
#define KNewStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height
複製代碼
分析下面代碼,能夠看到,在採用 Frame
佈局時,會根據初始狀態下的狀態欄高度,計算出列表的高度。後續狀態欄變化時,並無進行列表高度值的從新計算,賦值和更新。bash
#define kiPhoneXNaviBarTopMargin (22)
#define kTabViewHeight (50.0)
#define kTabViewiPhoneXHeight (83.0)
#define KSSSViewControllerHeight (KViewControllerHeight)
#define KSSSMainViewHeight (KSSSViewControllerHeight-kTabViewHeight)
#define KSSSMainViewiPhoneXHeight (KSSSViewControllerHeight-kTabViewiPhoneXHeight)
#define KStatusBarHeight [JDBIPhoneGlobalConfig statusBarHight]
// 電話狀態會變成40
#define KNewStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height
//計算列表高度
- (CGRect)p_getViewFrame {
CGFloat customeViewFrameHeight = isNotch ? KSSSMainViewiPhoneXHeight:KSSSMainViewHeight;
CGRect rect = CGRectMake(0.0, 0.0, CGRectGetWidth(self.view.bounds), customeViewFrameHeight);
return rect;
}
// 計算底部tabBar高度
- (CGRect)p_getTabbarViewFrame {
CGRect rect;
if(!isNotch){
CGFloat beginY = KSSSMainViewHeight;
rect = CGRectMake(0, beginY, SCREEN_WIDTH, kTabViewHeight);
} else {
CGFloat beginY = KSSSViewControllerHeight-kTabViewiPhoneXHeight;
rect = CGRectMake(0, beginY, SCREEN_WIDTH, kTabViewiPhoneXHeight);
}
return rect;
}
複製代碼
Ref - IOS 打電話、分享熱點狀態欄變化引發的UI變化 | CSDN網絡
方法1 - 監聽狀態欄變化,在監聽事件中進行適配app
//移除通知
- (void)dealloc {
//...
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationWillChangeStatusBarFrameNotification
object:nil];
}
//添加通知
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusChange) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
//...
}
//監聽事件
- (void)statusChange
{
self.isStatusChanged = YES;
[self.tableView reloadData]; //觸發reload 從新佈局
//或者 調用方法更新列表列表frame
}
複製代碼
UIViewAutoresizingFlexibleHeight
// xxx.autoresizingMask = UIViewAutoresizingFlexibleHeight;
- (void)loadView {
[super loadView];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, _customViewHeight)];
customView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.view = customView;
}
複製代碼
viewWillLayoutSubviews
生命週期函數中處理:狀態欄的變化,會觸發 viewWillLayoutSubviews
生命週期函數的調用,能夠進行對應的佈局操做- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.currentViewController.view.frame = [self p_getViewFrame]; //更新列表高度
self.tabBarView.frame = [self p_getTabbarViewFrame]; //更新底部tabBar高度
}
複製代碼
UILabel
添加漸變背景色後,能夠展現包含中文的字符串,對於純數字或者純英文字符串,沒法展現color
的 CAGradientLayer
與顯示字符串的 layer
層之間會有一箇中間 layer
(_UIContentLayer
),使中文字符串不會被覆蓋(正常顯示);而顯示純英文字符串時,是沒有這個中間 layer
的,致使 CAGradientLayer
覆蓋了 字符串layer,從而致使字符串沒法展現UIView
上添加 UILabel
, UIView
用於顯示漸變背景色,UILabel
用於展現字符串。UILabel
的寬或高爲小數時,會產生黑色邊界線ceilf()
NSUInteger assteId = 0;
NSDictionary *dict = @{@"assetId":assteId};
複製代碼
如上代碼,向字典對象插入基本類型值時,會報錯,顯示iphone
Collection element of type 'NSUInteger' (aka 'unsigned long') is not an Objective-C object
複製代碼
錯誤緣由爲,將一個基本類型值(好比 int
,char
等)賦值給一個對象變量(好比 NSNumber
)。函數
針對上述問題,其解決方案以下,使用 @()
包裹基本類型值。佈局
NSUInteger assteId = 0;
NSDictionary *dict = @{@"assetId":@(assteId)};
複製代碼
PingFangSC
。IOS 9.0之前的系統,是沒有平方字體的。UIFont
對象爲 nil
,處理不當,會致使 App 閃退UIFont *font = [UIFont fontWithName:@"PingFangSC-Regular" size:18];
//IOS 9.0以前的系統 font對象爲nil
複製代碼
font
爲 nil
,能夠考慮採用降級方案(使用其餘字體),或者手動導入第三方字體UIFont *font = [UIFont fontWithName:@"PingFangSC-Regular" size:18];
if(font == nil){
//手動導入第三方字體
// ...
}
複製代碼
for (NSString *fontFamilyName in [UIFont familyNames])
{
NSLog(@"fontFamilyName:'%@'", fontFamilyName);
for (NSString *fontName in [UIFont fontNamesForFamilyName:fontFamilyName])
{
NSLog(@"\tfont:'%@'",fontName);
}
NSLog(@"-------------");
}
複製代碼
執行上述代碼,在IOS 9.0+系統上輸出的平方字體信息以下
2019-09-24 16:45:35.837877+0800 fontFamilyName:'PingFang SC'
2019-09-24 16:45:35.837877+0800 font:'PingFangSC-Medium'
2019-09-24 16:45:35.837978+0800 font:'PingFangSC-Semibold'
2019-09-24 16:45:35.838068+0800 font:'PingFangSC-Light'
2019-09-24 16:45:35.838188+0800 font:'PingFangSC-Ultralight'
2019-09-24 16:45:35.838320+0800 font:'PingFangSC-Regular'
2019-09-24 16:45:35.839010+0800 font:'PingFangSC-Thin'
複製代碼
Showing Recent Messages:-1:
Multiple commands produce'/Users/admxjx/Library/Developer/Xcode/DerivedData/*****-fiyqckrgqvolmlefumieigxfboco/Build/Products/Debug-iphonesimulator/*****.app/Info.plist':
1) Target '*****' (project '*****') has copy command from '/Users/admxjx/coin-iOS/coin-ios1.0/*****/Info.plist' to '/Users/admxjx/Library/Developer/Xcode/DerivedData/*****-fiyqckrgqvolmlefumieigxfboco/Build/Products/Debug-iphonesimulator/*****.app/Info.plist'
2) Target '*****' (project '*****') has process command with output '/Users/admxjx/Library/Developer/Xcode/DerivedData/*****-fiyqckrgqvolmlefumieigxfboco/Build/Products/Debug-iphonesimulator/*****.app/Info.plist'
複製代碼
從報錯信息可知,Info.plist
文件重複。刪除重複的 info.plist
可。參考 - Stack Overflow
Xcode 中, 打開 File -> Project/Workspace settings
,將 Build System
更改成 Legacy Build system
,以下圖所示。
也能夠手動刪除多餘的info.plist
。Xcode 中,打開 target
> Build phase
> Copy Bundle Resource/Compile Sources
,刪除多餘的 info.plist
。
Xcode only builds what you say it should, so my guess is that the target's Compile step doesn't include those copied files in its compile list.
To fix this, select the target (normally your app), then select the Build Phases panel and open the Compile Sources step, then click the + button and add them (that list should include all sources needed to build the app).
To add new files in the future and repeating this manual compile list updating, right click on a project folder, click "Add Files to ...", select the file(s), click the Options button and select the target, then click Add.
在建立類時,注意將其關聯到對應的 target
。下面以京東秒殺代碼爲例,進行說明。
建立類時,Target
屬性中勾選 JDSeckillModule
。這樣,在建立的類文件中,文件頭部的註釋部分會顯示對應的 Target
,以下所示
//
// SSSSKMViewController.m
// JDSeckillModule // ---> 本行表示關聯的 Target
//
// Created by 劉保帥 on 2019/6/10.
//
複製代碼
NSInteger
爲基本類型,在接收網絡請求時,若無該字段下發,則默認值爲 0
。NSNumber
爲一個類,是個對象,在接收網絡請求時,若無該字段下發,則默認值爲 nil
。記錄以下 3 種方法
// 方法1 - 回滾到表的最頂端
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
// 方法2
[self.tableView setContentOffset:CGPointMake(0,0) animated:NO];
// 方法3
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
複製代碼