連接地址:http://www.open-open.com/lib/view/open1443194127763.htmlphp
For more infomation ,welcome to follow my twitterhtml
How to deal with the SSL in iOS9,One solution is to do like: ios
As the Apple say :git
iOS 9 and OSX 10.11 require TLSv1.2 SSL for all hosts you plan to request data from unless you specify exception domains in your app's Info.plist file.github
The syntax for the Info.plist configuration looks like this:web
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>yourserver.com</key> <dict> <!--Include to allow subdomains--> <key>NSIncludesSubdomains</key> <true/> <!--Include to allow insecure HTTP requests--> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> <!--Include to specify minimum TLS version--> <key>NSTemporaryExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> </dict> </dict>
If your application (a third-party web browser, for instance) needs to connect to arbitrary hosts, you can configure it like this:算法
<key>NSAppTransportSecurity</key> <dict> <!--Connect to anything (this is probably BAD)--> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
If you're having to do this, it's probably best to update your servers to use TLSv1.2 and SSL, if they're not already doing so. This should be considered a temporary workaround.chrome
As of today, the prerelease documentation makes no mention of any of these configuration options in any specific way. Once it does, I'll update the answer to link to the relevant documentation.api
If your server is support TLSv1.2 ,but you also have to do what I say just now if you want to connect success in iOS9:xcode
After some discussion with Apple Support, the issue is due to the self signed certificate.
ATS trusts only certificate signed by a well known CA, all others are rejected. As a consequence the only solution with a Self signed certificate is to set an exception with NSExceptionDomains.
If you're using CoreLocation framework in your app in Xcode7(pre-released),and you may notice that there is a newly added property called allowsBackgroundLocationUpdates in CLLocationManager class.
This new property is explained in the WWDC session "What's New in Core Location".
The default value isNOif you link against iOS 9.
If your app uses location in the background (without showing the blue status bar) you have to setallowsBackgroundLocationUpdatestoYESin addition to setting the background mode capability in Info.plist. Otherwise location updates are only delivered in foreground. The advantage is that you can now have location managers with background location updates and other location managers with only foreground location updates in the same app. You can also reset the value toNOto change the behavior.
The documentation is pretty clear about it:
By default, this is NO for applications linked against iOS 9.0 or later, regardless of minimum deployment target.
With UIBackgroundModes set to include "location" in Info.plist, you must also set this property to YES at runtime whenever calling -startUpdatingLocation with the intent to continue in the background.
Setting this property to YES when UIBackgroundModes does not include "location" is a fatal error.
Resetting this property to NO is equivalent to omitting "location" from the UIBackgroundModes value. Access to location is still permitted whenever the application is running (ie not suspended), and has sufficient authorization (ie it has WhenInUse authorization and is in use, or it has Always authorization). However, the app will still be subject to the usual task suspension rules.
See -requestWhenInUseAuthorization and -requestAlwaysAuthorization for more details on possible authorization values.
The syntax for the Info.plist configuration looks like this:
<key>NSLocationAlwaysUsageDescription</key> <string>微博@iOS程序犭袁 請求後臺定位權限</string> <key>UIBackgroundModes</key> <array> <string>location</string> </array>
Use like:
_locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) { [_locationManager requestAlwaysAuthorization]; } if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) { _locationManager.allowsBackgroundLocationUpdates = YES; } [_locationManager startUpdatingLocation];
Since iOS9 there is no option to trust an enterprise build. Before iOS9,it's very easy to use:if you touch the app,it'll apear this :
Now:
You have to let the user do like: Go to Settings - General - Profiles - tap on your Profile - tap on Trust button.
After Xcode 7,bitcode option will be enabled by default,If your library was compiled without bitcode but the bitcode option is enabled in your project settings.You can
- Update your library with bit code, or you'll get warnings like:
(null): URGENT: all bitcode will be dropped because '/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)' was built without bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. Note: This will be an error in the future.
and the Library Build Settings to remove the warnings
For more information,go to documentation of bitcode in developer library
,and WWDC 2015 Session 102: "Platforms State of the Union"
iOS 9 has made a small change to the handling of URL scheme. You must whitelist the url's that your app will call out to using theLSApplicationQueriesSchemeskey in yourInfo.plist.
Please see post here: http://awkwardhare.com/post/121196006730/quick-take-on-ios-9-url-scheme-changes
The main conclusion is that:
If you call the 「canOpenURL」 method on a URL that is not in your whitelist, it will return 「NO」, even if there is an app installed that has registered to handle this scheme. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.
If you call the 「openURL」 method on a URL that is not in your whitelist, it will fail silently. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.
The author also speculates that this is a bug with the OS and Apple will fix this in a subsequent release.
This is a new security feature of iOS 9. Watch WWDC 2015 Session 703 for more information.
Any app built with SDK 9 needs to provide aLSApplicationQueriesSchemesentry in its plist file, declaring which schemes it attempts to query.
<key>LSApplicationQueriesSchemes</key> <array> <string>urlscheme</string> <string>urlscheme2</string> <string>urlscheme3</string> <string>urlscheme4</string> </array>
Assuming two apps TestA and TestB. TestB wants to query if TestA is installed. "TestA" defines the following URL scheme in its info.plist file:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>testA</string> </array> </dict> </array>
The second app "TestB" tries to find out if "TestA" is installed by calling:
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"TestA://"]];
But this will normally return NO in iOS9 because "TestA" needs to be added to the LSApplicationQueriesSchemes entry in TestB's info.plist file. This is done by adding the following code to TestB's info.plist file:
<key>LSApplicationQueriesSchemes</key> <array> <string>TestA</string> </array>
A working implementation can be found here: https://github.com/gatzsche/LSApplicationQueriesSchemes-Working-Example
How to transition an an older project to support Slide Over and Split View of iOS 9? You may find that all the demo projects was written by storyboard or xib, but the older project's UI is written by code!
I would suggest switching to storyboards to make your life easy.
I would highly recommend you watch the following WWDC videos and then think about what exactly you need to do in order to support multi tasking.
Posted by 微博@iOS程序犭袁
中文
[摘要]爲了強制加強數據訪問安全, iOS9 默認會把 全部的http請求 全部從NSURLConnection、CFURL、NSURLSession發出的 HTTP 請求,都改成 HTTPS 請求:iOS9.x-SDK編譯時,默認會讓全部從NSURLConnection、CFURL、NSURLSession發出的 HTTP 請求統一採用TLS 1.2 協議。由於 AFNetworking 如今的版本底層使用了NSURLConnection,衆多App將被影響(基於iOS8.x-SDK的App不受影響)。服務器所以須要更新,以解析相關數據。如不更新,可經過在 Info.plist 中聲明,倒退回不安全的網絡請求。而這一作法,官方文檔稱爲ATS,全稱爲App Transport Security,是iOS9的一個新特性。
一個符合 ATS 要求的 HTTPS,應該知足以下條件:
官方文檔 App Transport Security Technote 對ATS 的介紹:
注:有童鞋反映:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。
那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的 NSExceptionDomains,並將大家公司的域名掛在下面。下文也會詳細描述該問題。
官方文檔 App Transport Security Technote 對CA頒發的證書要求:
Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection
在討論以前,跟往常同樣,先說下iOS程序猿們最關心的問題:
首先我們來看下業內對Apple這一作法的評論:
這是某社交App上討論,看來業內仍是吐槽聲和確定聲同在。
結論是:
跟你頗有關係,加班吧,少年!
書歸正傳【嚴肅臉】,咱們正式討論下 WHAT,WHY,HOW:
什麼是SSL/TLS? SSL你必定知道,在此不作贅述。主要說下什麼是TLS,還有跟HTTP和HTTPS有什麼關係。
TLS 是 SSL 新的別稱:
「TLS1.0」之於「SSL3.1」,猶「公元2015」之於「民國104」,「一千克」之於「一公斤」:稱呼不一樣,意思相同。
SSL 3.0版本以後的迭代版本被從新命名爲TLS 1.0:TLS 1.0=SSL 3.1。因此咱們日常也常常見到 「SSL/TLS」 這種說法。
目前,應用最普遍的是TLS 1.0,接下來是SSL 3.0。目前主流瀏覽器都已經實現了TLS 1.2的支持。
經常使用的有下面這些:
那爲何標題是「使用HTTPS」而沒有說起SSL和TLS什麼事? 「SSL/TLS」跟HTTP和HTTPS有什麼關係?
要理解這個,要看下他們之間的關係:
HTTP+SSL/TLS+TCP = HTTPS
或者
HTTPS = 「HTTP over SSL」
也就是說:
Apple讓你的HTTP採用SSL/TLS協議,就是讓你從HTTP轉到HTTPS。而這一作法,官方文檔稱爲ATS,全稱爲App Transport Security。
不使用SSL/TLS的HTTP通訊,就是不加密的通訊!
不使用SSL/TLS的HTTP通訊,全部信息明文傳播,帶來了三大風險:
SSL/TLS協議是爲了解決這三大風險而設計的,但願達到:
SSL/TLS的做用,打個比方來說:
若是原來的 HTTP 是塑料水管,容易被戳破;那麼現在新設計的 HTTPS 就像是在原有的塑料水管以外,再包一層金屬水管(SSL/TLS協議)。一來,原有的塑料水管照樣運行;二來,用金屬加固了以後,不容易被戳破。
正如文章開頭所說:
TLS 1.2 協議 強制加強數據訪問安全 系統 Foundation 框架下的「相關網絡請求」將再也不默認使用 HTTP 等不安全的網絡協議,而默認採用 TLS 1.2。服務器所以須要更新,以解析相關數據。如不更新,可經過在 Info.plist 中聲明,倒退回不安全的網絡請求。
總之:
要麼我們iOS程序猿加班,要麼後臺加班:
方案一:當即讓公司的服務端升級使用TLS 1.2,以解析相關數據。
方案二:雖Apple不建議,但可經過在 Info.plist 中聲明,倒退回不安全的網絡請求依然能讓App訪問指定http,甚至任意的http,具體作法見gif圖,示例Demo見 Demo1
這也是官方文檔和WWDC給出的解決方案:
即便你的應用使用的是:你沒有權限控制的CDN (Content Delivery Network),並且它不支持HTTPS!
也別擔憂,Apple都替你考慮好了:
正如你在上圖中看到的:蘋果官方提供了一些可選配置項來決定是否開啓ATS模式,也就是能夠選擇開啓或者不開啓。
開發者能夠針對某些肯定的URL不使用ATS,這須要在工程中的info.plist中標記NSExceptionDomains。在NSExceptionDomains字典中,能夠顯式的指定一些不使用ATS的URL。這些你可使用的例子能夠是:
NSIncludesSubdomains
NSExceptionAllowInsecureHTTPLoads
NSExceptionRequiresForwardSecrecy
NSExceptionMinimumTLSVersion
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
這些關鍵字使咱們能夠更加細緻的設置針對不使用ATS的域名狀況下禁用ATS或者一些特殊的ATS選項。
你可能注意到一些關鍵字像是使用了一些其餘關鍵字中的詞可是在前面加上了"ThirdParty"字樣,好比列表裏最後三個:
NSThirdPartyExceptionAllowsInsecureHTTPLoads
NSThirdPartyExceptionMinimumTLSVersion
NSThirdPartyExceptionRequiresForwardSecrecy
在功能上,這些關鍵字與不含有"ThirdParty"的關鍵字有一樣的效果。並且實際運行中所調用的代碼將會徹底忽略是否使用"ThirdParty"關鍵字。你應該使用適用於你的場景的關鍵字而沒必要過多考慮這些。
關於App Transport Security,每一個應用都屬於4個大類當中的一類。咱們來看看每個大類都是怎樣影響應用的。
-- | 分類名 | 解釋 |
---|---|---|
1. | HTTPS Only (只有HTTPS,全部狀況下都使用ATS) | 若是你的應用只基於支持HTTPS的服務器,那麼你太幸運了。你的應用不須要作任何改變。可是,注意App Transport Security要求TLS 1.2並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。 |
2. | Mix & Match(混合) | 你的應用與一個不符合ATS要求的服務器工做是頗有可能的。在這種狀況下,你須要告訴操做系統哪些站點是涉及到的而後在你的應用的 Info.plist文件中指明哪些要求沒有達到。 |
3. | Opt Out(禁用ATS) | 若是你在建立一個網頁瀏覽器,那麼你有一個更大的麻煩。由於你不可能知道你的用戶將要訪問那個網頁,你不可能指明這些網頁是否支持ATS要求且在HTTPS上傳輸。在這種狀況下,除了所有撤銷 App Transport Security 沒有其它辦法。 |
4. | Opt Out With Exceptions(除特殊狀況外,都不使用ATS) | 當你的應用撤消了App Transport Security,,但同時定義了一些例外。這很是有用就是當你的應用從不少的服務器上取數據,可是也要與一個你可控的API交互。在這種狀況下,在應用的Info.plist文件中指定任何加載都是被容許的,可是你也指定了一個或多個例外來代表哪些是必需要求 App Transport Security的。 |
下面分別作一下介紹:
若是你的應用只基於支持HTTPS的服務器,那麼你太幸運了。你的應用不須要作任何改變。
惟一須要作的事情就是使用NSURLSession。若是你的開發目標是iOS 9或者 OS X EI Capitan以後,ATS 的最佳實踐將會應用到全部基於NSURLSession的網絡。
但也有人遇到過這樣的疑惑:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。
那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的 NSExceptionDomains,並將大家公司的域名掛在下面。
官方文檔 App Transport Security Technote 對CA頒發的證書要求:
Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection
你的應用與一個不符合ATS要求的服務器工做是頗有可能的,
當你遇到如下三個不符合 ATS 要求的服務器的域名時:
你能夠分別設置以下:
api.insecuredomain.com
Info.plist 配置中的XML源碼以下所示:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>api.insecuredomain.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> </dict> </dict>
在 plist 文件裏顯示以下:
咱們定義的第一個「例外」(Exception)告訴ATS當與這個子域交互的時候撤銷了必須使用HTTPS的要求。注意這個僅僅針對在「例外」 (Exception)中聲明瞭的子域。很是重要的一點是要理解NSExceptionAllowsInsecureHTTPLoads關鍵字並不只僅只是與使用HTTPS相關。這個「例外」(Exception)指明瞭對於那個域名,全部的App Transport Security的要求都被撤銷了。
cdn.domain.com Info.plist 配置中的XML源碼以下所示:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>cdn.somedomain.com</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> </dict> </dict>
在 plist 文件裏顯示以下:
極可能你的應用是與一個支持HTTPS傳輸數據的服務器交互,可是並無使用TLS 1.2或更高。在這種狀況下,你定義一個「例外」(Exception),它指明應該使用的最小的TLS的版本。這比徹底撤銷那個域名的App Transport Security要更好更安全。
thatotherdomain.com
Info.plist 配置中的XML源碼以下所示:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>thatotherdomain.com</key> <dict> <!--適用於這個特定域名下的全部子域--> <key>NSIncludesSubdomains</key> <true/> <!--擴展可接受的密碼列表:這個域名可使用不支持 forward secrecy 協議的密碼--> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <!--容許App進行不安全的HTTP請求--> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <!--在這裏聲明所支持的 TLS 最低版本--> <key>NSExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> </dict> </dict>
在 plist 文件裏顯示以下:
NSIncludesSubdomains關鍵字告訴 App Transport Security 這個「例外」(Exception)適用於這個特定域名的全部子域。這個「例外」(Exception)還進一步經過擴展可接受的密碼列表來定義這個域名可使用不支持forward secrecy(NSExceptionRequiresForwardSecrecy) 協議的密碼。想了解更多關於forward secrecy的信息,推薦去看官方文檔 Apple's technote 。
若是你的App中同時用到了這三個域名,那麼應該是這樣:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>api.insecuredomain.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> <key>cdn.somedomain.com</key> <dict> <key>NSThirdPartyExceptionMinimumTLSVersion</key> <string>TLSv1.1</string> </dict> <key>thatotherdomain.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>
上面是比較嚴謹的作法,指定了能訪問哪些特定的HTTP。固然也有暴力的作法:完全倒退回不安全的HTTP網絡請求,能任意進行HTTP請求,好比你在開發一款瀏覽器App,或者你想偷懶,或者後臺想偷懶,或者公司不給你升級服務器。。。
你能夠在Info.plist 配置中改用下面的XML源碼:
<key>NSAppTransportSecurity</key> <dict> <!--完全倒退回不安全的HTTP網絡請求,能任意進行HTTP請求 (不建議這樣作)--> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
在 plist 文件裏顯示以下:
上面已經介紹了三種情景,還有一種可能你也會遇到:
當你的應用撤消了App Transport Security,,但同時定義了一些「例外」(Exception)。當你的應用從不少的服務器上取數據,可是也要與一個你可控的API交互。在這種狀況下,在應用的Info.plist文件中指定任何加載都是被容許的,可是你也指定了一個或多個「例外」(Exception)來代表哪些是必需要求 App Transport Security的。下面是Info.plist文件應該會有的內容:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> <key>NSExceptionDomains</key> <dict> <key>api.tutsplus.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> </dict> </dict> </dict>
在 plist 文件裏顯示以下:
【注:以上在Info.plist配置中的作法已經驗證可行,但目前Apple的prerelease版本的官方文檔並未說起Info.plist中配置的代碼,我將密切關注官方文檔,若有說起,再來更新本文 .你若發現官方文檔有說起了,也可在微博@iOS程序犭袁通知下我。】(官方文檔已經有闡述)
雖然ATS大多數安全特性都是默承認用的,Certificate Transparency 是必須設置的。若是你有支持Certificate Transparency的證書,你能夠檢查NSRequiresCertificateTransparency關鍵字來使用Certificate Transparency。再次強調,若是你的證書不支持Certificate Transparency,此項須要設置爲不可用。
若是須要調試一些因爲採用了ATS而產生的問題,須要設置CFNETWORK_DIAGNOSTICS爲1,這樣就會打印出包含被訪問的URL和 ATS錯誤在內的NSURLSession錯誤信息。要確保處理了遇到的全部的錯誤消息,這樣才能使ATS易於提升可靠性和擴展性。
Q:我用xcode7編譯的app,若是不在plist裏面加關鍵字說明,ios9下不能進行網絡請求,由於咱們服務器並不支持 TLS 1.2 ,我要是直接下載app store上的,什麼也沒有作,也是能正常網絡請求。
A:本文中所羅列的新特性,多數狀況下指的是 iOS9.X-SDK 新特性,AppStore 的版本是基於 iOS8.X-SDK或 iOS7.X-SDK,因此並不受 iOS9新特性約束。也就是說:Xcode7給iOS8打設備包能夠請求到網絡,Xcode7給iOS9設備打的包請求不到網絡,Xcode7和iOS9缺一不可,才須要網絡適配ATS。
那麼,如何確認本身項目所使用的 SDK?在Targets->Build Setting-->Architectures
Q:服務器已支持TLS 1.2 SSL ,但iOS9上仍是不行,還要進行本文提出的適配操做。
A:那是由於:要注意 App Transport Security 要求 TLS 1.2,並且它要求站點使用支持forward secrecy協議的密碼。證書也要求是符合ATS規格的,ATS只信任知名CA頒發的證書,小公司所使用的 self signed certificate,仍是會被ATS攔截。。所以慎重檢查與你的應用交互的服務器是否是符合ATS的要求很是重要。對此,建議使用下文中給出的 NSExceptionDomains,並將大家公司的域名掛在下面。
官方文檔 App Transport Security Technote 對CA頒發的證書要求:
Certificates must be signed using a SHA256 or better signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection
Q:我使用的是第三方的網絡框架,好比 AFNetworking 、ASIHTTPRequest、CFSocket 等,這個有影響沒有?
A: AFNetworking 有影響,其它沒影響。
ATS 是隻針對NSURLConnection、CFURL、NSURLSession,若是底層涉及到這三個類就會有影響。
如今的 AFNetworking 的 AFHTTPRequestOperationManager 實現是使用的NSURLConnection。
但 AFNetworking 也有更新計劃,移除NSURLConnection相關API,遷移到 AFHTTPSessionManager ,但還未執行,詳情見:https://github.com/AFNetworking/AFNetworking/issues/2806。
Q:試了一下禁用 ATS 的方法 可是仍是沒法聯網 仍然提示要使用https?
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.
A:遇到這類問題,90%是出如今「一個 Project 多 Target 」的狀況下,因此請確保你修改的,確實是你的 Target 所屬的 Info.plist !
如何確認?請前往這裏,確認你 Target 所屬的 Info.plist 到底是哪一個:
Project -> Your Target -> Build Settings -> Info.plist File
或者更直截了當一點,直接修改:
Project -> Your Target —>info-> Custom iOS target properties-> 添加禁用 ATS 的屬性
還有一種可能性是:禁用 ATS 的代碼粘貼進 plist 時,位置不對,能夠嘗試放在 diwuhang
Q:個人項目是「一個 Project 多 Target 」,按照本文禁用 ATS 的方法,是否是每一個 Info.plist 都要修改?
A:不須要,用到哪一個 Target 修改哪一個的 Info.plist ,Target 是獨立的,不受其餘 Target 的影響,也不會影響其餘 Target。
Q:如何檢測咱們公司 HTTPS 是否符合 ATS 的要求?
A:若是你的 App 的服務也在升級以適配ATS要求,可使用以下的方式進行校驗:
在OS X EI Capitan系統的終端中經過nscurl命令來診斷檢查你的HTTPS服務配置是否知足Apple的ATS要求:
$ nscurl --verbose --ats-diagnostics https://<your_server_domain>
固然,你也可讓公司服務端的同事參考Apple提供官方指南App Transport Security Technote進行服務的升級配置以知足ATS的要求:
一個符合 ATS 要求的 HTTPS,應該知足以下條件:
【iOS9在定位的問題上,有一個壞消息一個好消息】壞消息:若是不適配iOS9,就不能偷偷在後臺定位(不帶藍條,見圖)!好消息:將容許出現這種場景:同一App中的多個location manager:一些只能在前臺定位,另外一些可在後臺定位,並可隨時開啓或者關閉特定location manager的後臺定位。
若是沒有請求後臺定位的權限,也是能夠在後臺定位的,不過會帶藍條:
如何偷偷在後臺定位:請求後臺定位權限:
// 1. 實例化定位管理器 _locationManager = [[CLLocationManager alloc] init]; // 2. 設置代理 _locationManager.delegate = self; // 3. 定位精度 [_locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; // 4.請求用戶權限:分爲:⓵只在前臺開啓定位⓶在後臺也可定位, //注意:建議只請求⓵和⓶中的一個,若是兩個權限都須要,只請求⓶便可, //⓵⓶這樣的順序,將致使bug:第一次啓動程序後,系統將只請求⓵的權限,⓶的權限系統不會請求,只會在下一次啓動應用時請求⓶ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) { //[_locationManager requestWhenInUseAuthorization];//⓵只在前臺開啓定位 [_locationManager requestAlwaysAuthorization];//⓶在後臺也可定位 } // 5.iOS9新特性:將容許出現這種場景:同一app中多個location manager:一些只能在前臺定位,另外一些可在後臺定位(並可隨時禁止其後臺定位)。 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9) { _locationManager.allowsBackgroundLocationUpdates = YES; } // 6. 更新用戶位置 [_locationManager startUpdatingLocation];
可是若是照着這種方式嘗試,而沒有配置Info.plist,100%你的程序會崩潰掉,並報錯:
*** Assertion failure in -[CLLocationManager setAllowsBackgroundLocationUpdates:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/CoreLocationFramework_Sim/CoreLocation-1808.1.5/Framework/CoreLocation/CLLocationManager.m:593
對應的 Info.plist 的XML源碼是:
<key>NSLocationAlwaysUsageDescription</key> <string>微博@iOS程序犭袁 請求後臺定位權限</string> <key>UIBackgroundModes</key> <array> <string>location</string> </array>
有兩處變化:
iOS9以前,企業級分發十分方便:點擊App出現「信任按鈕」,
iOS9之後,企業級分發ipa包將遭到與Mac上dmg安裝包同樣的待遇:默認不能安裝,也再也不出現「信任按鈕」
必須讓用戶進行gif圖中的設置:
iOS9升級後衆多企業分發的 app 已經出現了不能安裝的狀況,而iOS8或更早的系統不受影響。那是由於從iOS9之後,系統會在 ipa 包下載完以後,拿ipa包中的 bundle ID 與網頁中的 plist 文件中的 bundle ID 進行比對,不一致不容許安裝。
錯誤提示以下:
網頁中的 plist 文件中的 bundle ID 的做用可參考 《iOS:蘋果企業證書經過網頁分發安裝app》 。
正如這篇文章提到的,「網頁中的 plist 文件」是習慣的叫法,也有人稱做「manifest文件」,好比 這篇文章。
而iOS9以前,蘋果不會檢查這一項,所以iOS9以前能夠安裝。
致使這一錯誤的緣由除了粗心,還有開發者是故意設置不一致,據開發者說:
當初服務器 plist 的 bundle id 上故意作成成不一致。是爲了解決一些人安裝不上的問題。
詳情可參考: 《升級到ios 9,企業版發佈如今沒法安裝成功了,有人遇到了這種問題嗎?》
如何知道是由於 bundle id 不一致形成的沒法安裝?
經過查看設備上的日誌信息:有一個 itunesstored 進程提示安裝信息:
itunesstored → <Warning>: [Download]: Download task did finish: 8 for download: 2325728577585828282 itunesstored → <Warning>: [ApplicationWorkspace] Installing download: 2325728577585828282 with step(s): Install itunesstored → <Warning>: [ApplicationWorkspace]: Installing software package with bundleID: com.***.***: bundleVersion: 1.01 path: /var/mobile/Media/Downloads/2325728577585828282/-1925357977307433048 itunesstored → <Warning>: BundleValidator: Failed bundleIdentifier: com.***.**** does not match expected bundleIdentifier: com.***.********* itunesstored → <Warning>: [ApplicationWorkspace]: Bundle validated for bundleIdentifier: com.****.******success: 0 itunesstored → <Warning>: LaunchServices: Uninstalling placeholder for app <LSApplicationProxy: 0x12677be70> com.****.*******(Placeholder) <file:///private/var/mobile/Containers/Bundle/Application/B62D8EA3-2052-4393-8A7E-3FD27228BFC2/2325728577585828282.app> itunesstored → <Warning>: LaunchServices: Uninstalling app <LSApplicationProxy: 0x12677be70> com.****.*****(Placeholder) <file:///private/var/mobile/Containers/Bundle/Application/B62D8EA3-2052-4393-8A7E-3FD27228BFC2/2325728577585828282.app>
其中的這一句很重要:
itunesstored → <Warning>: BundleValidator: Failed bundleIdentifier: com.***.**** does not match expected bundleIdentifier: com.***.*********
通過覈對,果真是.ipa文件中真實的Bundle ID和manifest文件中配置的信息不匹配,而後測試發現:
iOS 9是校驗bundle-identifier值的,而iOS 9如下版本是不校驗,一旦iOS 9發現bundle-identifier不匹配,即便下載成功了,也會 Uninstall(日誌中提示的)app的。
適配方法:
二者的 bundle id 修改一致
一旦出現iOS9可以安裝企業版本APP,iOS9如下版本不能安裝,必定先查看安裝日誌,而後覈對每一個參數配置。
manifest文件的參考配置。
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <!-- array of downloads. --> <key>items</key> <array> <dict> <!-- an array of assets to download --> <key>assets</key> <array> <!-- software-package: the ipa to install. --> <dict> <!-- required. the asset kind. --> <key>kind</key> <string>software-package</string> <!-- optional. md5 every n bytes. --> <!-- will restart a chunk if md5 fails. --> <key>md5-size</key> <integer>10485760</integer> <!-- optional. array of md5 hashes --> <key>md5s</key> <array> <string>41fa64bb7a7cae5a46bfb45821ac8bba</string> <string>51fa64bb7a7cae5a46bfb45821ac8bba</string> </array> <!-- required. the URL of the file to download. --> <key>url</key> <string>http://www.example.com/apps/foo.ipa</string> </dict> <!-- display-image: the icon to display during download. --> <dict> <key>kind</key> <string>display-image</string> <!-- optional. icon needs shine effect applied. --> <key>needs-shine</key> <true/> <key>url</key> <string>http://www.example.com/image.57×57.png</string> </dict> <!-- full-size-image: the large 512×512 icon used by iTunes. --> <dict> <key>kind</key> <string>full-size-image</string> <!-- optional. one md5 hash for the entire file. --> <key>md5</key> <string>61fa64bb7a7cae5a46bfb45821ac8bba</string> <key>needs-shine</key> <true/> <key>url</key> <string>http://www.example.com/image.512×512.jpg</string> </dict> </array><key>metadata</key> <dict> <!-- required --> <key>bundle-identifier</key> <string>com.example.fooapp</string> <!-- optional (software only) --> <key>bundle-version</key> <string>1.0</string> <!-- required. the download kind. --> <key>kind</key> <string>software</string> <!-- optional. displayed during download; --> <!-- typically company name --> <key>subtitle</key> <string>Apple</string> <!-- required. the title to display during the download. --> <key>title</key> <string>Example Corporate App</string> </dict> </dict> </array> </dict> </plist>
使用fir.im等第三方分發平臺:上述「 bundle id 不一致致使下載失敗」這種狀況只會出如今企業本身搭建網頁分發的情形下,事實證實第三方的分發平臺更加專業,已經很好地規避了該狀況的發生。
Q:企業分發,企業版證書在iOS9上安裝應用報Ignore manifest download, already have bundleID: com.mycom.MyApp只有個人手機沒法安裝,別人 iOS9 均可以安裝
A:這並不是 iOS9的問題,iOS8及之前的系統也會出現,和緩存有關係,請嘗試關機重啓手機,而後就能夠安裝了。
【前言】將來, Watch 應用必須包含 bitcode ,iOS不強制,Mac OS不支持。但最坑的一點是: Xcode7 及以上版本會默認開啓 bitcode 。
什麼是 bitcode ?
通俗解釋:在線版安卓ART模式。
Apple 官方文檔-- App Distribution Guide – App Thinning (iOS, watchOS) 是這樣定義的:
Bitcode is an intermediate representation of a compiled program. Apps you upload to iTunes Connect that contain bitcode will be compiled and linked on the App Store. Including bitcode will allow Apple to re-optimize your app binary in the future without the need to submit a new version of your app to the store.
翻譯過來就是:
bitcode 是被編譯程序的一種中間形式的代碼。包含 bitcode 配置的程序將會在 App Store 上被編譯和連接。 bitcode 容許蘋果在後期從新優化咱們程序的二進制文件,而不須要咱們從新提交一個新的版本到 App Store 上。
在 Xcode簡介--- What’s New in Xcode-New Features in Xcode 7 中這樣描述:
Bitcode. When you archive for submission to the App Store, Xcode will compile your app into an intermediate representation. The App Store will then compile the bitcode down into the 64 or 32 bit executables as necessary.
也就是
當咱們提交程序到 App Store上時, Xcode 會將程序編譯爲一箇中間表現形式( bitcode )。而後 App store 會再將這個 bitcode 編譯爲可執行的64位或32位程序。
再看看這兩段描述都是放在App Thinning(App瘦身)一節中,能夠看出其與包的優化有關了。
打個比方,沒有 bitcode 的 AppStore 裏所提供的 App,相似在新華書店裏賣捆綁銷售的《四大名著叢書--精裝版》,要買只能全買走,有了 bitcode 就比如這套四大名著每本均可以單賣,顧客就能按需購買。咱們開發者在這個過程當中扮演的角色是圖書出版商的角色,應該照顧那些沒錢一次買四本的顧客。(不要作不珍惜用戶流量和存儲空間的奸商。。)
那爲何第三方的 SDK 不支持 bitcode,個人 app 也就不能支持?打個比方,《四大名著叢書》只要有一本是能夠單賣的,那麼你很難再賣捆綁銷售款的《四大名著叢書》了,因此乾脆全均可以單賣,這大概就是 Apple 的邏輯。
App Thinning 官方文檔解釋以下:
The App Store and operating system optimize the installation of iOS and watchOS apps by tailoring app delivery to the capabilities of the user’s particular device, with minimal footprint. This optimization, called app thinning, lets you create apps that use the most device features, occupy minimum disk space, and accommodate future updates that can be applied by Apple. Faster downloads and more space for other apps and content provides a better user experience.
開發者都知道,當前 iOS App 的編譯打包方式是把適配兼容多個設備的執行文件及資源文件合併一個文件,上傳和下載的文件則包含了全部的這些文件,致使佔用較多的存儲空間。
App Thinning是一個關於節省iOS設備存儲空間的功能,它可讓iOS設備在安裝、更新及運行App等場景中僅下載所需的資源,減小App的佔用空間,從而節省設備的存儲空間。
根據Apple官方文檔的介紹,App Thinning主要有三個機制:
Slicing
開發者把App安裝包上傳到AppStore後,Apple服務會自動對安裝包切割爲不一樣的應用變體(App variant),當用戶下載安裝包時,系統會根據設備型號下載安裝對應的單個應用變體。
On-Demand Resources
ORD(隨需資源)是指開發者對資源添加標籤上傳後,系統會根據App運行的狀況,動態下載並加載所需資源,而在存儲空間不足時,自動刪除這類資源。
Bitcode 開啓Bitcode編譯後,可使得開發者上傳App時只需上傳Intermediate Representation(中間件),而非最終的可執行二進制文件。 在用戶下載App以前,AppStore會自動編譯中間件,產生設備所需的執行文件供用戶下載安裝。
(喵大(@onevcat)在其博客 《開發者所須要知道的 iOS 9 SDK 新特性》 中也描述了iOS 9中蘋果在App瘦身中所作的一些改進,你們能夠轉場到那去研讀一下。)
其中,Bitcode的機制能夠支持動態的進行App Slicing,而對於Apple將來進行硬件升級的措施,此機制能夠保證在開發者不從新發布版本的狀況下而兼容新的設備。
Bitcode 是一種中間代碼,那它是什麼格式的呢? LLVM 官方文檔有介紹這種文件的格式: LLVM Bitcode File Format。
若是你的應用也準備啓用 Bitcode 編譯機制,就須要注意如下幾點:
如何適配?
在上面的錯誤提示中,提到了如何處理咱們遇到的問題:
You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
正如開頭所說的:
將來, Watch 應用必須包含 Bitcode ,iOS不強制,Mac OS不支持。但最坑的一點是: Xcode7 及以上版本會默認開啓 Bitcode 。
Xcode 7 + 會開啓 Bitcode。
也就是說,也兩種方法適配:
方法一:更新 library 使包含 Bitcode ,不然會出現如下中的警告;
(null): URGENT: all bitcode will be dropped because '/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/foldername/appname/GoogleMobileAds.framework/GoogleMobileAds(GADSlot+AdEvents.o)' was built without bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. Note: This will be an error in the future.
甚至有的會報錯誤,沒法經過編譯:
ld: ‘/Users//Framework/SDKs/PolymerPay/Library/mobStat/libSDK.a(**ForSDK.o)’ does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
或:
ld: -undefined and -bitcode_bundle (Xcode settingENABLE_BITCODE=YES) cannot be used together clang: error: linker command failed with exit code 1 (use -v to see invocation)
不管是警告仍是錯誤,獲得的信息是:咱們引入的一個第三方庫不包含bitcode。
方法二:關閉Bitcode,方法見下圖
咱們能夠在」Build Settings」->」Enable Bitcode」選項中看到:
用 Xcode 7+ 新建一個 iOS 程序時, bitcode 選項默認是設置爲YES的。如今須要改爲NO。
若是咱們開啓了 bitcode ,在提交包時,下面這個界面也會有個 bitcode 選項:
那麼 SDK 廠商如何支持 bitcode 呢?答案是隻要在 Xcode7上從新編譯一下就 ok 了。(請確保默認開啓的 bitcode 沒有去主動關閉)
更多信息,請移步
WWDC 2015 Session 102: "Platforms State of the Union"
WWDC 2015 Session 703: "Privacy and Your App ( 時間在30:18左右)關於URL scheme的介紹,指出:
也就是說:在iOS9中,若是使用canOpenURL:方法,該方法所涉及到的URL scheme必須在"Info.plist"中將它們列爲白名單,不然不能使用。key叫作LSApplicationQueriesSchemes ,鍵值內容是
<key>LSApplicationQueriesSchemes</key> <array> <string>urlscheme</string> <string>urlscheme2</string> <string>urlscheme3</string> <string>urlscheme4</string> </array>
白名單上限是50個:
WWDC 2015 Session 703: "Privacy and Your App )有說明:
「So for apps that are linked before iOS 9 and are running on iOS 9, they will be given 50 distinct URL schemes.」 -- WWDC 2015 session 703 Privacy and Your App
然而,咱們卻發現了一件意外的事:當咱們在 iOS9-beta(截至本文發佈時,iOS9正式版還未發佈)中,使用openURL:方法時,不在白名單中的 URL 會報錯 > 「This app is not allowed to query for scheme xxx」 。不管是官方文檔仍是 WWDC 的視頻中都沒有說起openURL:方法的這一變更,因此猜想這是 beta 版本一個 bug ,截至本文發佈時,iOS9正式版還未發佈,指望在正式版中能得以修復。在此以前,可經過將openURL:用到的URL scheme列入白名單來解決這個 bug 。(經測試:iOS9 beta5中已經修復)
iOS9中openURL:方法沒有什麼實質性的變化,僅僅多了一個確認動做:
蘋果爲何要這麼作?
在 iOS9 以前,你可使用canOpenURL:監測用戶手機裏到底裝沒裝微信,裝沒裝微博。可是也有一些別有用心的 App ,這些 App 有一張經常使用 App 的URL scheme,而後他們會屢次調用canOpenURL:遍歷該表,來監測用戶手機都裝了什麼 App ,好比這個用戶裝了叫「大姨媽」的App,你就能夠知道這個用戶是女性,你就能夠只推給這個用戶女性用品的廣告。這是侵犯用戶隱私的行爲。
這也許就是緣由。
本項目中給出了一個演示用的 Demo ,倉庫的文件夾叫「Demo3_iOS9URLScheme適配_引入白名單概念」,Demo引用自 LSApplicationQueriesSchemes-Working-Example
Demo結構以下:
主要演示的情景是這樣的:
假設有兩個App: weixin(微信) and 個人App. 個人App 想監測 weixin(微信) 是否被安裝了. "weixin(微信)" 在 info.plist 中定義了 URL scheme :
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>weixin</string> </array> </dict> </array>
個人App 想監測 weixin(微信) 是否被安裝了 :
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"weixin(微信)://"]];
即便你安裝了微信,在iOS9中,這有可能會返回NO:
由於你須要將 "weixin(微信)" 添加到 「個人App」 的 info.plist 文件中:
<key>LSApplicationQueriesSchemes</key> <array> <string>weixin</string> </array>
(以上只是爲了演示,實際開發中,你不只須要添加「weixin」還須要「wechat」這兩個。具體 )
關於openURL:這個問題,可在 Demo3 中自行測試,若是該 bug 修復了的話,請私信微博@iOS程序犭袁,我再來更新本文。(經測試:iOS9 beta5中已經修復)
另外,推薦一篇博文,其中最關鍵的是如下部分:
If you call the 「canOpenURL」 method on a URL that is not in your whitelist, it will return 「NO」, even if there is an app installed that has registered to handle this scheme. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.
> If you call the 「openURL」 method on a URL that is not in your whitelist, it will fail silently. A 「This app is not allowed to query for scheme xxx」 syslog entry will appear.
若是想一次性集成最經常使用的微信、新浪微博、QQ、支付寶四者的白名單,則配置以下:
<key>LSApplicationQueriesSchemes</key> <array> <!-- 微信 URL Scheme 白名單--> <string>wechat</string> <string>weixin</string> <!-- 新浪微博 URL Scheme 白名單--> <string>sinaweibohd</string> <string>sinaweibo</string> <string>sinaweibosso</string> <string>weibosdk</string> <string>weibosdk2.5</string> <!-- QQ、Qzone URL Scheme 白名單--> <string>mqqapi</string> <string>mqq</string> <string>mqqOpensdkSSoLogin</string> <string>mqqconnect</string> <string>mqqopensdkdataline</string> <string>mqqopensdkgrouptribeshare</string> <string>mqqopensdkfriend</string> <string>mqqopensdkapi</string> <string>mqqopensdkapiV2</string> <string>mqqopensdkapiV3</string> <string>mqzoneopensdk</string> <string>wtloginmqq</string> <string>wtloginmqq2</string> <string>mqqwpa</string> <string>mqzone</string> <string>mqzonev2</string> <string>mqzoneshare</string> <string>wtloginqzone</string> <string>mqzonewx</string> <string>mqzoneopensdkapiV2</string> <string>mqzoneopensdkapi19</string> <string>mqzoneopensdkapi</string> <string>mqzoneopensdk</string> <!-- 支付寶 URL Scheme 白名單--> <string>alipay</string> <string>alipayshare</string> </array>
plist 文件看起來會是這樣的:
其餘平臺可在下面的列表中查詢:各平臺OpenURL白名單說明
平臺名稱 | URL Schem | 補充說明 |
---|---|---|
微信 | wechat, weixin | |
支付寶 | alipay,alipayshare | |
mqqOpensdkSSoLogin, mqqopensdkapiV2,mqqopensdkapiV3,wtloginmqq2,mqq,mqqapi | ||
QZONE | mqzoneopensdk, mqzoneopensdkapi,mqzoneopensdkapi19,mqzoneopensdkapiV2,mqqOpensdkSSoLogin,mqqopensdkapiV2,mqqopensdkapiV3,wtloginmqq2,mqqapi,mqqwpa,mqzone,mqq | [注:若同時使用QQ和QZONE,則直接添加本格便可] |
新浪微博 | sinaweibo,sinaweibohd,sinaweibosso,sinaweibohdsso,weibosdk,weibosdk2.5 | [後兩個若導入新浪SDK則須要] |
豆瓣 | 無需配置 | |
開心網 | 無需配置 | |
易信 | yixin, yixinopenapi | |
Google+ | googlechrome, googlechrome-x-callback,hasgplus4,com.google.gppconsent,com.google.gppconsent.2.2.0,com.google.gppconsent.2.3.0,com.google.gppconsent.2.4.0,com.google.gppconsent.2.4.1 | |
人人網 | renrenapi,renrenios,renreniphone,renren, | |
fbauth2 | ||
無需配置 | ||
pocket-oauth-v1 | ||
pinit | ||
Line | line | |
KakaoTalk | kakaolink | |
KaokaoStory | storylink | |
無需配置 | ||
Tumblr | 無需配置 | |
非平臺類 | 無需配置 | ( 如短信,複製,郵件等) |
Q:我用xcode7編譯的app,若是不在plist裏面加scheme,ios9下qq就會不顯示,由於我用了qqsdk裏的判斷是否安裝qq的方法,我要是直接下載app store上的,沒有加scheme,qq也是能顯示。
A:本文中所羅列的新特性,多數狀況下指的是 iOS9.X-SDK 新特性,AppStore 的版本是基於 iOS8.X-SDK或 iOS7.X-SDK,因此並不受 iOS9新特性約束。也就是說:Xcode7給iOS8打設備包不須要白名單也能調用「canOpenURL」 ,Xcode7給iOS9設備打的包則否則,Xcode7和iOS9缺一不可,才須要適配URL Scheme。
那麼,如何確認本身項目所使用的 SDK?在Targets->Build Setting-->Architectures
Q:咱們本身的應用跳到微信、支付寶、微博等的URLScheme是固定幾個,可是從微信、支付寶、微博跳回到咱們的應用的URLScheme多是成千上萬個,那他們那些大廠是如何作這個白名單?
A:白名單策略影響的僅僅是 canOpenURL: 接口,OpenURL: 不受影響,這些大廠只調用 openURL: 因此不受 iOS9 的影響。
Q:文中提到了設置白名單的緣由,然而,若是這些別有用心的APP在它本身的白名單列出它關心的APP, 而後依次調用canOpenURL來檢測,照樣能夠監控用戶都安裝了哪些APP啊?因此我依然不明白蘋果這樣作得緣由。
A:白名單的數目上限是50個。蘋果這樣子作,使得最多隻能檢測50個App。
Q:按照文中的適配方法,error緣由就沒有了的確沒問題了,可是仍是會打印以下信息:
-canOpenURL: failed for URL: "XXXXXXXXXX" - error: "(null)"。
A:這個模擬器的一個 bug,不管使用iOS9的真機仍是模擬器均出現該問題,估計 Xcode 後續的升級中會修復掉。
那如何判斷日誌到底是 Xcode bug 形成的仍是沒有適配形成的?看error的值,若是是null,則是 bug。(2015-09-21更)
【iPad適配Slide Over 和 Split View】若想適配multi tasking特性,惟一的建議:棄純代碼,改用storyboard、xib,縱觀蘋果WWDC全部Demo均是如此:
iOS8中,字體是Helvetica,中文的字體有點相似於「華文細黑」。只是蘋果手機自帶渲染,因此看上去可能比普通的華文細黑要美觀。 iOS9中,中文系統字體變爲了專爲中國設計的「蘋方」 有點相似於一種word字體「幼圓」。字體有輕微的加粗效果,而且最關鍵的是字體間隙變大了!
因此不少本來寫死了width的label可能會出現「...」的狀況:
狀況 | 顯示 | 解釋 |
---|---|---|
XIB | 將 label 的 width 寫死 | 下面這兩張圖也能夠直觀的看出同一個界面,同一個label的變化。 |
iOS8 | 正常 | |
iOS9 | 最後四位數字、、、 |
若是不將 label 的 width 寫死,僅僅添加左端約束則右端的四個數字會越界
狀況 | 顯示 | 解釋 |
---|---|---|
XIB | 若是僅僅添加左端約束 | |
iOS8 | 正常 | |
iOS9 | 「3199」這四個數字越界了 |
因此爲了在界面顯示上不出錯,就算是固定長度的文字也仍是建議使用sizetofit 或者ios向上取整 ceilf() 或者提早計算:
CGSize size = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14.0f]}]; CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
app was compiled with optimization - stepping may behave oddly; variables may not be available
打印出來這句話,而後崩潰。可能是啓動的過程當中程序就崩潰。
在iOS9下,新浪微博SDK裏面使用的 JSONKit 在部分機型可能致使崩潰。崩潰信息以下圖。
解決:更新新浪微博SDK,新浪的SDK最新版作了對iOS9兼容。
咱們在使用時候一直將 leading 與 left 劃爲等號,這樣作在 iOS8(及之前)上是正常的,但在 iOS9 上這樣的觀念可能會引發崩潰,好比:
make.left.equalTo(self.mas_leading).offset(15);
應該爲:
make.left.equalTo(self.mas_left).offset(15);
同理 mas_training 也須要改成right
<Error>: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. <Error>: CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. <Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
出錯緣由:設置 app 的狀態欄樣式的時候,使用了舊的方式,在 info.plist 裏面的View controller-based status bar appearance默認會爲 YES,即便不設置也是 YES,但通常 iOS6 的時候爲了設置狀態欄樣式,須要將其設爲NO,iOS7,8也兼容,可是到了iOS9 就會報警告。
解決辦法:
刪除原先的設置代碼,一般老的設置方式是這樣的:
//設置狀態欄的白色 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
刪除的緣由見下:
// Setting the statusBarStyle does nothing if your application is using the default UIViewController-based status bar system. @property(readwrite, nonatomic) UIStatusBarStyle statusBarStyle NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]"); - (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated NS_DEPRECATED_IOS(2_0, 9_0, "Use -[UIViewController preferredStatusBarStyle]");
修改方式是在Info.plist文件中作以下修改:
將View controller-based status bar appearance刪除(默認爲 YES),或設置爲YES:
對應的 plist 裏的 XML源碼:
<key>UIViewControllerBasedStatusBarAppearance</key> <true/>
看起來長這樣:
而後使用新的方式來實現狀態欄的樣式:
- (UIStatusBarStyle)preferredStatusBarStyle; - (UIViewController *)childViewControllerForStatusBarStyle; - (void)setNeedsStatusBarAppearanceUpdate
好比,你想將狀態欄設置爲白色,就能夠這樣寫:
//設置狀態欄的白色 -(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }
記得要 clean 下或者刪除應用程序從新運行
若是你按照上面的方法設置了,但仍是不行。八成是 rootViewController 設置的問題,你必須設置 rootViewController,編譯器纔會去 rootViewController 中重載 preferredStatusBarStyle 方法。
另外當你在 appdelegate 中將 navigationController 設爲 rootViewController 的時候:
self.window.rootViewController = self.navigationController;
由於 rootViewController 變爲了 navigationController,你在 ViewController 裏重寫 preferredStatusBarStyle 方法是不會起做用的。因此最好的方法是
- (void)viewDidLoad { [super viewDidLoad]; self.title = @"微博@iOS程序犭袁"; self.navigationController.navigationBar.barStyle = UIBarStyleBlack; }
若是你仍是想重寫 preferredStatusBarStyle 方法來達到做用,那最好使用分類來解決:
.h文件:
// // UINavigationController+StatusBarStyle.h // 微博@iOS程序犭袁 // // Created by https://github.com/ChenYilong/iOS9AdaptationTips/ on 15/6/8. // Copyright (c) 2015年 http://weibo.com/luohanchenyilong/ . All rights reserved. // #import <UIKit/UIKit.h> @interface UINavigationController (StatusBarStyle) @end
.m文件:
// // UINavigationController+StatusBarStyle.m // 微博@iOS程序犭袁 // // Created by https://github.com/ChenYilong/iOS9AdaptationTips/ on 15/6/8. // Copyright (c) 2015年 http://weibo.com/luohanchenyilong/ . All rights reserved. // #import "UINavigationController+StatusBarStyle.h" @implementation UINavigationController (StatusBarStyle) - (UIStatusBarStyle)preferredStatusBarStyle { //also you may add any fancy condition-based code here return UIStatusBarStyleLightContent; } @end
我在倉庫裏給出了 navigation 的設置方法,見Demo4。
參考連接: preferredStatusBarStyle isn't called--For anyone using a UINavigationController:
Xcode6 的工程升級到 Xcode7上來,會報警告:
這是 debug 編譯時導出符號文件出現的告警,
然而新建的Xcode7工程不會有該問題。
解決方法是讓 debug 編譯的時候不生成符號文件:
Xcode7調試iOS8.x的真機,須要確保項目名改成英文,中間含有中文會報錯there is an intenal API error
按照下面的步驟檢查:
bulid settings -> packaging -> product name
咱們都知道,從網易新聞分享一條新聞到QQ,而後從QQ中打開連接再用safari打開連接,在iOS8上,這個時候會跳轉到網易新聞App。可是如今(2015年09月23日)版本的網易新聞在 iOS9 就不能正常跳轉,會跳轉到 App Store 頁面並提示要不要打開 App Store。
這是極可能是由於使用了 HTML 的 iframe 元素,並將自定義的連接放進了該元素中
舉例說明:
我以前寫的一個 Demo: 模仿 《簡書 App》 的效果:在html中跳轉到App中的對應頁面,並能從App跳轉到原來的網址,在例子中直接調用自定義連接在 iOS9上是能夠跳轉到 App 中的,然而,若是用 iframe 元素包起來就會變不可用。
參考連接:
導入兩個 framework,
而後像設置tableView 的 cell 同樣設置下每個「搜索元素」,詳情見代碼。
既然剛纔說了搜索元素與 tableView 的 cell 很是類似:那麼咱們就展現一下如何讓 tableView 與 CoreSpotlightSearch 進行結合:
詳見 Demo6,Demo6 與 Demo5 的主要差別在於:在點擊搜索結果跳轉到 App 後,還會進一步根據搜索的內容 push 到相應的詳情頁中:
若是你在開發中遇到什麼新的 iOS9 的坑,或者有什麼適配細節本文沒有說起,歡迎給本倉庫提 pull request。也歡迎在微博@iOS程序犭袁 或在「iOS9開發學習交流羣:141607754」中交流。