?9 сентября выйдет новый релиз iOS и OS X. Времени остается все меньше, и многие разработчики уже оптимизировали свои приложения для работы на новых ОС. Тем, кто этого ещё не сделал, предлагаю коротко рассмотреть, что необходимо для поддержки iOS 9.




App Transport Security


В iOS 9 появилась технология App Transport Security, которая помогает сделать передачу данных по сети более безопасной. Она включена по умолчанию, поэтому если ваш сервер не удовлетворяет требованиям ATS, то соединение завершится с ошибкой
An SSL error has occurred and a secure connection to the server cannot be made.

Однако ATS можно настроить. Понять, какие настройки необходимо конфигурировать, поможет команда nscurl. Например, для Яндекса:
nscurl --ats-diagnostics http://ya.ru
<...>
Default ATS Secure Connection
---
ATS Default Connection
2015-08-28 11:51:06.868 nscurl[7019:8960694] NSURLSession/
NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
Result : FAIL
---
<...>
Configuring PFS exceptions for ya.ru
---
Disabling Perfect Forward Secrecy
Result : PASS
---
<...>

Видно, что успешно установить соединение удастся, только если отключить Perfect Forward Secrecy, поэтому в Info.plist файле для домена ya.ru необходимо указать NSExceptionRequiresForwardSecrecy=NO.

Рассмотрим основные конфигурации ATS.

Отключить ATS


Полностью отключить ATS можно, указав флаг NSAllowsArbitraryLoads=NO. Такая конфигурация рекомендуется только для отладки.?
?
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
	</dict>


Отключить ?PFS для всех поддоменов


	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>ya.ru</key>
			<dict>
				<key>NSIncludesSubdomains</key>
				<true/>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
			</dict>
		</dict>
	</dict>


??Отключить ATS для всех соединений кроме одного


Для приложений, которые открывают внешние ссылки во встроенном браузере, необходимо отключить ATS для всех соединений, кроме соединений к API серверу.
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsArbitraryLoads</key>
		<true/>
		<key>NSExceptionDomains</key>
		<dict>
			<key>ya.ru</key>
			<dict>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
				<key>NSExceptionAllowsInsecureHTTPLoads</key>
				<false/>
			</dict>
		</dict>
	</dict>


Биткод


В iOS 9 появилась техонология App Thinning, которая позволяет оптимизировать размер устанавливаемого приложения. Теперь в Xcode 7 во время компиляции генерируется биткод для платформ, которые поддерживаются приложением. Это опция включена по умолчанию. Однако некоторые сторонние библиотеки пока ещё не скомпилированы с биткодом. Если ваше приложение использует такие библиотеки, то генерацию биткода необходимо отключить. Ставим в проекте ENABLE_BITCODE=NO.
?

Переходы в сторонние приложения


В iOS 9 изменилось поведение метода canOpenURL:. Теперь необходимо объявлять список схем, которые используются для перехода в сторонние приложения. Это делается с помощью ключа LSApplicationQueriesSchemes в файле Info.plist. Например, если ваше приложение открывает Яндекс.Навигатор, то конфигурация будет выглядеть так:
	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>yandexnavi</string>
	</array>

?

Facebook SDK


Если ваше приложение использует Facebook SDK, то необходимо настроить ATS и список схем так, как рекомендует Facebook на странице Preparing Your Apps for iOS 9. Также стоит обратить внимание на другие сторонние библиотеки, которые устанавливают соединение со своими серверами или открывают сторонние приложения.

Итог


Корректная настройка ATS, биткода и списка схем — это основное, что необходимо сделать для корректной работы приложения на iOS 9. Это несложно, особенно если понять, для чего это необходимо и как правильно это делается. Ведь эти знания пригодятся не только при переходе с iOS 8 SDK, но и в будущем при создании новых проектов.

Успехов!

Комментарии (19)


  1. InViZz
    01.09.2015 12:16

    спасибо за статью)

    а что за утилита nscurl?


    1. zaazza
      01.09.2015 12:21
      +1

      в OS X 10.11 утилита для отладки сетевых соединений
      поищите по слову «nscurl» на странице developer.apple.com/library/prerelease/mac/releasenotes/General/rn-osx-10.11


      1. InViZz
        01.09.2015 12:30

        спасибо)


      1. IRuslan
        10.09.2015 10:48

        Может кто подскажет — есть ли возможно сделать эту же проверку не с El Capitan (более ранние версии либо не OS X)?


  1. Dreddik
    01.09.2015 14:49
    +1

    LSApplicationQueriesSchemes бред какой-то. В упор не понимаю, зачем задавать список схем, которые будет открывать твоё приложение.


    1. usgleb
      01.09.2015 14:55

      что бы Apple знали что Вы планируете открывать в своей апе и, если этот список не будет соответствовать логике приложения, не допустить его в стор. *моё личное предположение*


    1. zaazza
      01.09.2015 14:58
      +2

      Перед тем как открыть стороннее приложение вы должны убедиться что оно установлено, с помощью вызова метода `canOpenURL:`. В iOS9 этот метод будет всегда возвращать `NO` (плюс сообщение об ошибке в консоль) до тех пор, пока вы не объявите схему стороннего приложения в `LSApplicationQueriesSchemes`. Это сделано для того, чтобы вы не могли узнать какие приложения установлены на девайсе пользователя (так делает твиттер например).


    1. KLUBS
      01.09.2015 15:50
      +2

      Возможно для того, чтобы приложение не перебирало все возможные схемы (приложения), чтобы понять какие установлены. Таким образом нарушалась конф. инф.


    1. Makc666
      02.09.2015 09:06

      Если читать описание LSApplicationQueriesSchemes, то получается, что разработчик приложения указывает типы ссылок, с которыми может работать приложение (Specifies the URL schemes you want the app to be able to use), тем самым «не позволяет» другим приложением через canOpenURL открывать через своё приложение иные типы ссылок (URL schemes (http, ftp, and so on)), чем это было разработчиком предусмотрено/задумано.

      Ссылки
      LSApplicationQueriesSchemes — https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW26

      Specifies the URL schemes you want the app to be able to use — https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW26

      URL schemes (http, ftp, and so on) — https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102207


    1. ChapayHabr
      03.09.2015 17:08

      сейчас всякие сдк могут трэкать, какие аппы стоят на телефоне по схемам

      тупо качают аппы из стора платные-бесплатные, достают список схем из ipa так набивают базу «приложение — его схемы»
      затем на девайсах юзера проверяют какие аппы стоят
      за несколько секунд можно проверить десятки тысяч апп таким образом + делать это можно не в основном потоке, так что никто ничего не заметит

      потом полученный список передают на сервак вместе с advert ID
      смотрят какие аппы стоят, определяют интересы юзера и делают более качественный таргетинг по рекламе

      К примеру трэкают юзера и у него постоянно новые платные аппы из стора появляются, какой-то направленности, => это нормальный платящий юзер который покупает и не грузится

      Вот и сейчас эппл эту лавочку прикрывает практически запретить они не могут поэтому вводят такого рода ограничения


      1. kaspartus
        10.09.2015 18:08

        Со сторонними SDK — в точку. Самому же разработчику никто не мешает прописать там бесконечный список приложений и самому отсматривать список установленных приложений.


        1. Pr0Ger
          10.09.2015 18:48

          С большей вероятностью это просто реджектнут, или попросят объяснить в чем необходимость делать столько проверок


          1. zaazza
            10.09.2015 18:50

            максимум 50 схем, который можно проверить. после 50 схемы canOpenURL будет всегда возвращать NO. этож все написано в доках


  1. zaazza
    01.09.2015 14:58

    -


  1. IgorFedorchuk
    05.09.2015 09:33

    Как обойтись без этого ключа (NSAllowsArbitraryLoads), если приложение использует webView и заранее не контролируешь какие url будут использованы?


    1. zaazza
      05.09.2015 20:40
      +1

      никак не обойтись, только `NSAllowsArbitraryLoads=YES`, чтобы разрешить все коннекты + `NSExceptionDomains`, чтобы обезопасить коннекты к API


  1. egormerkushev
    12.09.2015 13:04

    Что-то вот этот способ не работает «Отключить ?PFS для всех поддоменов», а «Отключить ATS» — работает.


    1. egormerkushev
      12.09.2015 13:36

      Так как Apple расcказывает в сессии про ATS совсем не работает. Что тут не так?

      <key>NSAppTransportSecurity</key>
          <dict>
              <key>NSAllowsArbitraryLoads</key>
              <false/>
              <key>NSExceptionDomains</key>
              <dict>
                  <key>yourdomain.com</key>
                  <dict>
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <key>NSExceptionAllowInsecureHTTPLoads</key>
                      <true/>
                  </dict>
              </dict>
          </dict>
      


      1. egormerkushev
        12.09.2015 13:42

        А вот это уже работает, хотя я не понимаю принципиальной разницы. Похоже, что в документации Apple есть ошибка ( href=«http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ ).

        <key>NSAppTransportSecurity</key>
            <dict>
                <key>NSAllowsArbitraryLoads</key>
                <false/>
                <key>NSExceptionDomains</key>
                <dict>
                    <key>yourdomain.com</key>
                    <dict>
                        <key>NSIncludesSubdomains</key>
                        <true/>
                        <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                        <true/>
                        <key>NSTemporaryExceptionMinimumTLSVersion</key>
                        <string>TLSv1.1</string>
                    </dict>
                </dict>
            </dict>