iOS開發 Xcode8中遇到的問題及改動

iOS開發 Xcode8中遇到的問題及改動

 

新版本發佈總會有不少坑,也會有不少改動。html

一個一個填吧。。。ios

1、遇到的問題

一、權限以及相關設置

iOS10系統下調用系統相冊、相機功能,或者蘋果健康都會遇到閃退的狀況,
調用系統相冊報錯描述以下:swift

This app has crashed because it attempted to access privacy-sensitive data without a usage description.The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data數組

解決辦法(fix method):
info.plist —Source Code中添加
UsageDescription相關的key, 描述字符串本身隨意填寫就能夠,可是必定要填寫,否則會引起包無效的問題,致使上傳打包後構建版本一直不顯示xcode

<!-- 相冊 --> 
<key>NSPhotoLibraryUsageDescription</key> 
<string>App須要您的贊成,才能訪問相冊</string> 
<!-- 相機 --> 
<key>NSCameraUsageDescription</key> 
<string>App須要您的贊成,才能訪問相機</string> 
<!-- 麥克風 --> 
<key>NSMicrophoneUsageDescription</key> 
<string>App須要您的贊成,才能訪問麥克風</string> 
<!-- 位置 --> 
<key>NSLocationUsageDescription</key> 
<string>App須要您的贊成,才能訪問位置</string> 
<!-- 在使用期間訪問位置 --> 
<key>NSLocationWhenInUseUsageDescription</key> 
<string>App須要您的贊成,才能在使用期間訪問位置</string> 
<!-- 始終訪問位置 --> 
<key>NSLocationAlwaysUsageDescription</key> 
<string>App須要您的贊成,才能始終訪問位置</string> 
<!-- 日曆 --> 
<key>NSCalendarsUsageDescription</key> 
<string>App須要您的贊成,才能訪問日曆</string> 
<!-- 提醒事項 --> 
<key>NSRemindersUsageDescription</key> 
<string>App須要您的贊成,才能訪問提醒事項</string> 
<!-- 運動與健身 --> 
<key>NSMotionUsageDescription</key> <string>App須要您的贊成,才能訪問運動與健身</string> 
<!-- 健康更新 --> 
<key>NSHealthUpdateUsageDescription</key> 
<string>App須要您的贊成,才能訪問健康更新 </string> 
<!-- 健康分享 --> 
<key>NSHealthShareUsageDescription</key> 
<string>App須要您的贊成,才能訪問健康分享</string> 
<!-- 藍牙 --> 
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>App須要您的贊成,才能訪問藍牙</string> 
<!-- 媒體資料庫 --> 
<key>NSAppleMusicUsageDescription</key> 
<string>App須要您的贊成,才能訪問媒體資料庫</string>

若是不起做用,能夠請求後臺權限,相似於這樣:安全

<key>UIBackgroundModes</key>
<array> 
<!-- 在這裏寫上你在後臺模式下要使用權限對應的key --> 
<string>location</string>
...
</array>

或者在info.plist—Property List中添加網絡

輸入 Privacy app

部分框架

麥克風權限:Privacy - Microphone Usage Description 異步

通信錄權限: Privacy - Contacts Usage Description 

藍牙權限:Privacy - Bluetooth Peripheral Usage Description 

語音轉文字權限:Privacy - Speech Recognition Usage Description 

日曆權限:Privacy - Calendars Usage Description 

定位權限:Privacy - Location When In Use Usage Description 

定位權限: Privacy - Location Always Usage Description 

定位的須要這麼寫,防止上架被拒。

二、代碼註釋不能用的解決辦法

這個是由於蘋果解決xcode ghost,把插件屏蔽了。
解決辦法(fix method):
打開終端,命令運行: sudo /usr/libexec/xpccachectl
重啓電腦後生效

注意:Xcode8內置了開啓註釋的功能:

Add Documentation

快捷鍵的設置:
Xcode-> Preferences -> Key Bindings

Documentation

三方插件解決辦法(fix method):
讓你的 Xcode8 繼續使用插件
可是看到文章最後的解釋,咱們知道若是用插件的話,可能安全上會有問題、而且提交審覈會被拒絕,因此建議你們仍是不要用了,解決辦法老是有的,好比在Xcode中添加註釋的代碼塊也是很方便的。

3.屏蔽雜亂無章的log

解決辦法(fix method):
Edit Scheme-> Run -> Arguments,
Environment Variables裏邊添加
OS_ACTIVITY_MODE = Disable
————這種方法會屏蔽掉真機的NSLog,解決方法請等待————

Edit Scheme

成功後的喜悅

4.UIStatusBar方法過時:

解決辦法(fix method):

//屬性&&方法
@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
@property(nonatomic, readonly) BOOL prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
- (UIStatusBarStyle)preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
// Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarAnimationFade
//能夠這樣寫
- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleDefault;
}

5.label中的文字顯示不全

用Xcode 8和Xcode 7.3
分別測試了下,以下圖:
Xcode 8

Xcode 7

建立一個Label而後讓它自適應大小,字體大小都是17最後輸出的寬度是不同的,咱們再看一下,下面的數據就知道爲何升iOS 10以後App中有的文字顯示不全了:

發現英文字母沒有問題,只有漢字有問題。目前只有一個一個修改控件解決這個問題。

解決辦法(fix method):

UILabel *myLabel = [UILabel new];
/*UIFont 的preferredFontForTextStyle: 意思是指定一個樣式,並讓字體大小符合用戶設定的字體大小。 */
myLabel.font =[UIFont preferredFontForTextStyle: UIFontTextStyleHeadline];
 /*
 Indicates whether the corresponding element should automatically update its font when the device’s UIContentSizeCategory is changed.
 For this property to take effect, the element’s font must be a font vended using +preferredFontForTextStyle: or +preferredFontForTextStyle:compatibleWithTraitCollection: with a valid UIFontTextStyle.
 */
//是否更新字體的變化
myLabel.adjustsFontForContentSizeCategory = YES;

6.使用Xib awakeFromNib的警告問題

Xcode 8以前咱們使用Xib初始化- (void)awakeFromNib {}都是這麼寫也沒什麼問題,可是在Xcode 8會有以下警告:

若是不喜歡這個警告的話,應該明確的加上[super awakeFromNib];

7.判斷系統版本

oc

//值爲10.0
[[UIDevice currentDevice] systemVersion]
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9, .minorVersion = 1, .patchVersion = 0}]) { 
    NSLog(@"Hello from > iOS 9.1");
}
if ([NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,3,0}]) {
    NSLog(@"Hello from > iOS 9.3");
}
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_0) {
 // do stuff for iOS 9 and newer
} 
else { 
// do stuff for older versions than iOS 9
}

swift

if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) { 
         // 代碼塊
}
if #available(iOS 10.0, *) { 
         // 代碼塊
} else { 
         // 代碼塊
}

8.ATS的問題

iOS 9中默認非HTTPS的網絡是被禁止的,固然咱們也能夠把NSAllowsArbitraryLoads設置爲YES禁用ATS。不過iOS 10從2017年1月1日起蘋果不容許咱們經過這個方法跳過ATS
,也就是說強制咱們用HTTPS,若是不這樣的話提交App可能會被拒絕。可是咱們能夠經過NSExceptionDomains來針對特定的域名開放HTTP能夠容易經過審覈。
參考學習文章以下:關於 iOS 10 中 ATS 的問題

9.Xib文件的注意事項

使用Xcode8打開xib文件後,會出現下圖的提示:

Choose Device


你們選擇Choose Device便可。
以後你們會發現佈局啊,frame亂了,只須要更新一下frame便可。以下圖

update frame

  • 注意:若是按上面的步驟操做後,在用Xcode7打開Xib會報一下錯誤,

Xcode 8.0 or later

  • 解決辦法:右鍵Xib文件->Open As Source Code 刪除下面的
    <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    這句話,以及把< document >中的toolsVersion和< plugIn >中的version改爲你正常的xib文件中的值,不過不建議這麼作,在Xcode8出來後,但願你們都快速上手,全員更新。這就跟Xcode5到Xcode6同樣,有變更,可是仍是要儘早學習,儘快適應喲!

10.tabbar隱藏上面的黑線

//UITabBarController裏面
[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:@"BarBackground.png"];   
[[UITabBar appearance] setShadowImage:[UIImage new]];

—————————————我是分割線—————————————

2、改動

1.UIColor 新增方法

iOS 10 蘋果官方建議咱們使用sRGB,由於它性能更好,色彩更豐富。若是你本身爲UIColor寫了一套分類的話也可嘗試替換爲sRGB,UIColor類中新增了兩個Api以下:

+ (UIColor *)colorWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);

- (UIColor *)initWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);

2.真彩色的顯示

真彩色的顯示會根據光感應器來自動的調節達到特定環境下顯示與性能的平衡效果,若是須要這個功能的話,能夠在info.plist-Source Code裏配置:

<key>UIWhitePointAdaptivityStyle</key>
它有五種取值,分別是:
<string>UIWhitePointAdaptivityStyleStandard</string> // 標準模式
<string>UIWhitePointAdaptivityStyleReading</string> // 閱讀模式
<string>UIWhitePointAdaptivityStylePhoto</string> // 圖片模式
<string>UIWhitePointAdaptivityStyleVideo</string> // 視頻模式
<string>UIWhitePointAdaptivityStyleStandard</string> // 遊戲模式

也就是說若是你的項目是閱讀類的,就選擇UIWhitePointAdaptivityStyleReading這個模式,五種模式的顯示效果是從上往下遞減,也就是說若是你的項目是圖片處理類的,你選擇的是閱讀模式,給選擇太好的效果會影響性能.

3.UITextContentType

// The textContentType property is to provide the keyboard with extra information about the semantic intent of the text document.
@property(nonatomic,copy) UITextContentType textContentType NS_AVAILABLE_IOS(10_0); // default is nil

iOS 10UITextField添加了textContentType枚舉,指示文本輸入區域所指望的語義意義。
使用此屬性能夠給鍵盤和系統信息,關於用戶輸入的內容的預期的語義意義。例如,您能夠指定一個文本字段,用戶填寫收到一封電子郵件確認uitextcontenttypeemailaddress。當您提供有關您指望用戶在文本輸入區域中輸入的內容的信息時,系統能夠在某些狀況下自動選擇適當的鍵盤,並提升鍵盤修正和主動與其餘文本輸入機會的整合。

4. UIRefreshControl的使用

在iOS 10 中, UIRefreshControl能夠直接在UICollectionView和UITableView中使用,而且脫離了UITableViewController.如今RefreshControl是UIScrollView的一個屬性.使用方法:

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(loadData) forControlEvents:UIControlEventValueChanged]; 
collectionView.refreshControl = refreshControl;

5.Notification(通知)

自從Notification被引入以後,蘋果就不斷的更新優化,但這些更新優化只是小打小鬧,直至如今iOS 10開始真正的進行大改重構,這讓開發者也體會到UserNotifications的易用,功能也變得很是強大。

iOS 9 之前的通知

  1. 在調用方法時,有些方法讓人很難區分,容易寫錯方法,這讓開發者有時候很苦惱。
  2. 應用在運行時和非運行時捕獲通知的路徑還不一致。
  3. 應用在前臺時,是沒法直接顯示遠程通知,還須要進一步處理。
  4. 已經發出的通知是不能更新的,內容發出時是不能改變的,而且只有簡單文本展現方式,擴展性根本不是很好。

iOS 10 開始的通知

  1. 全部相關通知被統一到了UserNotifications.framework框架中。
  2. 增長了撤銷、更新、中途還能夠修改通知的內容。
  3. 通知不在是簡單的文本了,能夠加入視頻、圖片,自定義通知的展現等等。
  4. iOS 10相對以前的通知來講更加好用易於管理,而且進行了大規模優化,對於開發者來講是一件好事。
  5. iOS 10開始對於權限問題進行了優化,申請權限就比較簡單了(本地與遠程通知集成在一個方法中)。

iOS 10 通知學習相關資料:

  1. UserNotifications: 蘋果官方文檔
  2. 蘋果官方視頻1
  3. 蘋果官方視頻2
  4. 蘋果官方視頻3
  5. 活久見的重構 - iOS 10 UserNotifications 框架解析
  6. WWDC2016 Session筆記 - iOS 10 推送Notification新特性

6.UICollectionViewCell

在iOS 10 以前,UICollectionView上面若是有大量cell,當用戶活動很快的時候,整個UICollectionView的卡頓會很明顯,爲何會形成這樣的問題,這裏涉及到了iOS 系統的重用機制,當cell準備加載進屏幕的時候,整個cell都已經加載完成,等待在屏幕外面了,也就是整整一行cell都已經加載完畢,這就是形成卡頓的主要緣由,專業術語叫作:掉幀.要想讓用戶感受不到卡頓,咱們的app必須幀率達到60幀/秒,也就是說每幀16毫秒要刷新一次.

iOS 10 以前UICollectionViewCell的生命週期是這樣的:

  1. 用戶滑動屏幕,屏幕外有一個cell準備加載進來,把cell從reusr隊列拿出來,而後調用prepareForReuse方法,在這個方法裏面,能夠重置cell的狀態,加載新的數據;
  2. 繼續滑動,就會調用cellForItemAtIndexPath方法,在這個方法裏面給cell賦值模型,而後返回給系統;
  3. 當cell立刻進去屏幕的時候,就會調用willDisplayCell方法,在這個方法裏面咱們還能夠修改cell,爲進入屏幕作最後的準備工做;
  4. 執行完willDisplayCell方法後,cell就進去屏幕了.當cell徹底離開屏幕之後,會調用didEndDisplayingCell方法.

iOS 10 UICollectionViewCell的生命週期是這樣的:

  1. 用戶滑動屏幕,屏幕外有一個cell準備加載進來,把cell從reusr隊列拿出來,而後調用prepareForReuse方法,在這裏當cell尚未進去屏幕的時候,就已經提早調用這個方法了,對比以前的區別是以前是cell的上邊緣立刻進去屏幕的時候就會調用該方法,而iOS 10 提早到cell還在屏幕外面的時候就調用;
  2. cellForItemAtIndexPath中建立cell,填充數據,刷新狀態等操做,相比於以前也提早了;
  3. 用戶繼續滑動的話,當cell立刻就須要顯示的時候咱們再調用willDisplayCell方法,原則就是:什麼時候須要顯示,什麼時候再去調用willDisplayCell方法;
  4. 當cell徹底離開屏幕之後,會調用didEndDisplayingCell
    方法,跟以前同樣,cell會進入重用隊列.在iOS 10 以前,cell只能從重用隊列裏面取出,再走一遍生命週期,並調用cellForItemAtIndexPath
    建立或者生成一個cell.在iOS 10 中,系統會cell保存一段時間,也就是說當用戶把cell滑出屏幕之後,若是又滑動回來,cell不用再走一遍生命週期了,只須要調用willDisplayCell
    方法就能夠從新出如今屏幕中了.iOS 10 中,系統是一個一個加載cell的,二之前是一行一行加載的,這樣就能夠提高不少性能;

iOS 10 新增長的Pre-Fetching預加載

這個是爲了下降UICollectionViewCell在加載的時候所花費的時間,在 iOS 10 中,除了數據源協議和代理協議外,新增長了一個UICollectionViewDataSourcePrefetching
協議,這個協議裏面定義了兩個方法:

- (void)collectionView:(UICollectionView *)collectionView prefetchItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(10_0);
- (void)collectionView:(UICollectionView *)collectionView cancelPrefetchingForItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(10_0);

ColletionView prefetchItemsAt indexPaths這個方法是異步預加載數據的,當中的indexPaths數組是有序的,就是item接收數據的順序;CollectionView cancelPrefetcingForItemsAt indexPaths這個方法是可選的,能夠用來處理在滑動中取消或者下降提早加載數據的優先級.注意:這個協議並不能代替以前讀取數據的方法,僅僅是輔助加載數據.Pre-Fetching預加載對UITableViewCell一樣適用.

7.UINavigationBar

iOS10以前的navigationBar的背景是@"_UINavigationBarBackground",到iOS10變成了@"_UIBarBackground"

#define iOS10 ([[UIDevice currentDevice].systemVersion intValue]>=10?YES:NO)
NSArray *subviews=self.navigationController.navigationBar.subviews;
for (UIView *view in subviews) {
        if (iOS10) {
            //iOS10,改變了狀態欄的類爲_UIBarBackground
            if ([view isKindOfClass:NSClassFromString(@"_UIBarBackground")]) {
                view.hidden = YES;
            }
        }else{
            //iOS9以及iOS9以前使用的是_UINavigationBarBackground
            if ([view isKindOfClass:NSClassFromString(@"_UINavigationBarBackground")]) {
                view.hidden = YES;
            }
        } 
}

—————————————我是分割線—————————————

iOS 10 蘋果官方文檔

給個贊喔O(∩_∩)O

參考文章:
iOS 平常工做之經常使用宏定義大全
兼容iOS 10 資料整理筆記
iOS開發 適配iOS10以及Xcode8
iOS 10 的適配問題

相關文章
相關標籤/搜索