Содержание
Сравнение производительности iOS 9.3.2 и iOS 10 beta 2
25.09.2017
Сравнение производительности iOS 9.3.2 и iOS 10 beta 2
5-го июля корпорация Apple выпустила вторую бета версию операционной платформы для iPhone – iOS 10, которую производитель назвал самым крупным релизом самой совершенной во всем мире операционной системы для смартфонов. В новой операционной системе была представлена возможность при помощи новых и интересных способов продемонстрировать свое настроение в приложении iMessage, также в нее встроено приложение для управления «умным домом», а такие приложения как Карты, Музыка, Apple Music теперь имеют новое оформление с более удобными и интуитивными функциями. Ранее вы могли убедиться в том, что корпорация Apple проделала немало работы над улучшением быстродействия в операционной системе iOS 9.3.2. Автор канала iAppleBytes на YouTube решил сравнить скорость работы операционной системы iOS 10 beta 2 и последнего релиза девятой версии ОС iPhone.
Владелец данного канала тщательно тестирует каждую новую ОС и новые программные продукты компании Apple. В своем видео он сравнил работу этих двух операционных систем на двух устройствах – iPhone 6s и iPhone 5s. Положив рядом два смартфона, он открывал последовательно на них различные приложения и оценивал скорость работы. Во время тестирования использовались следующие приложения – Фото, Музыка, Панель многозадачности, Пункт Управления, Телефон, Настройки, App Store, YouTube, Safari, а также другие разделы ОС.
Для тех, кто ожидает скорейшего процесса оптимизации новой операционной системы, результаты будут не очень приятными. Несмотря на заметные улучшения, вторая бета версия iOS 10 работает значительно медленнее уже стабильной девятой версии. Это особенно заметно на модели iPhone 5s, где приложения открываются со значительной задержкой. iPhone 6s заметно лучше справился с поставленной задачей.
Снижение производительности новой ОС связано с увеличением количества функций. В обновленной версии увеличилось количество служб и сервисов, которые работают в фоновом режиме. Все эти факторы негативно отобразились на быстродействии iOS 10 beta 2. Неспроста эту операционную систему не поддерживает iPad mini, iPad touch 5G, iPhone 4s, но на них поддерживается iOS 9. Остается ожидать, что корпорация Apple будет продолжать оптимизировать десятую версию операционной системы. В соответствие с обещаниями компании, релиз новой ОС состоится в сентябре одновременно с презентацией смартфонов нового поколения.
10 новых фишек iOS 9
iOS 9 стала доступна лишь несколько дней назад, но уже больше половины мобильных пользователей Apple перешли на новую платформу. На первый взгляд, изменилось немногое – но это лишь на первый. После недели тестирования мы открыли для себя ряд новых возможностей iOS, которые упрощают жизнь пользователям.
1. Режим энергосбережения
Если при использовании iPhone вам едва хватает заряда до конца дня, то это обновление создано для вас.
Когда уровень зарядки опустится ниже 20% вы получите предложение активировать режим низкого энергопотребления, действующего путем отключения фоновых приложений, блокирования автозагрузки и отказа от визуальных эффектов – эта функция серьезно экономит заряд и автоматически отключается, когда вы доберетесь до розетки.
2. Поиск параметров в настройках
Хотите изменить какие-либо настройки, но не можете найти их? Разработчики iOS облегчили эту задачу – теперь вам достаточно ввести название требуемой функции в поисковой строке в меню настроек.
3. Шестизначный пароль
Наконец, разработчики Apple приняли дополнительные меры предосторожности. Отныне пароль на iPhone и iPad может состоять не из 4, а из 6 цифр – это означает более 1 000 000 возможных комбинаций (вместо 10 000 при четырехзначном коде).
Однако пока это не обязательное требование – вы можете продолжать пользоваться четырехзначным паролем на свой страх и риск 🙂
4. Выбор нескольких фотографий одним движением
Чрезвычайно удобная функция для активных пользователей Instagram, эдакий аналог «рамки» в десктопных ОС.
Теперь для выбора нескольких снимков вам не придется каждый раз тапать по экрану – вместо этого можно просто провести пальцем по тем фото, которые вы хотите удалить или переместить в другой альбом.
Кроме того, в iOS 9 имеющиеся снимки были автоматически рассортированы в новые папки: «Снимки экрана» и «Селфи».
5. Режим чтения
Часто читаете с экрана мобильных устройств? Теперь в режиме чтения браузера Safari появилось больше шрифтов и настроек на любой вкус.
6. Лучший друг Siri
С каждым обновлением голосовой помощник Siri все больше совершенствуется. Теперь она может распознавать только ваш голос, для чего потребуется несколько раз произнести «Привет, Siri». Увы, в случае глубокой простуды Siri не распознает ваш голос (проверено), так что требуемые действия придется выполнять без помощника.
7. Новая клавиатура-трекпад
Нажмите и удерживайте двумя пальцами клавиатуру на iPad, чтобы превратить ее в трекпад для более быстрой навигации и редактирования текста.
8. Кнопка «назад»
После открытия уведомления вы можете вернуться в предыдущее приложение, нажав кнопку » Назад к … » в левом верхнем углу экрана.
9. Новый вид многозадачности
При многозадачности эскизы открытых приложений теперь отображаются внахлест, а не бок о бок, что экономит место на экране и позволяет быстрее выбрать нужное окно.
10. Не отрываясь от просмотра
Новая особенность позволяет смотреть видео или делать видеозвонки FaceTime, параллельно используя другое приложение.
Установить iOS 9.0.2 прямо сейчас могут все пользователи iPhone, iPad и iPod touch. Для этого необходимо перейти в меню Настройки → Основные → Обновление ПО.
swift — iOS 9 и iOS 10 CoreData одновременно
CoreData для iOS9 и iOS10 одновременно
Для тех, кому это может понадобиться:
Это немодифицированный шаблон приложения Master-Detail из последней версии Xcode7 (для iOS9) Май 2016 г. Я обновил его с помощью последней версии Xcode (версия 8.2.1)
С помощью этого шаблона вы можете разработать приложение, использующее CoreData, совместимое с iOS9 и iOS10, по крайней мере, на данный момент (май 2017 г. )
AppDelegate.swift
// // AppDelegate.swift // мусор // // Создано Маркусом 22.05.17. // Copyright © 2017 Маркус. Все права защищены. // импортировать UIKit импортировать CoreData @UIApplicationMain класс AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate { переменное окно: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Точка переопределения для настройки после запуска приложения. пусть splitViewController = self.window!.rootViewController как! Уисплитвиевконтроллер пусть navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] как! UINavigationController navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem splitViewController.delegate = я пусть masterNavigationController = splitViewController. viewControllers[0] как! UINavigationController пусть контроллер = masterNavigationController.topViewController как! Мастервиевконтроллер контроллер.managedObjectContext = self.managedObjectContext вернуть истину } func applicationWillResignActive(_ приложение: UIApplication) { // Отправляется, когда приложение собирается перейти из активного в неактивное состояние. Это может происходить при определенных типах временных прерываний (таких как входящий телефонный звонок или SMS-сообщение) или когда пользователь выходит из приложения, и оно начинает переход в фоновое состояние. // Используйте этот метод, чтобы приостановить текущие задачи, отключить таймеры и снизить частоту кадров OpenGL ES. Игры должны использовать этот метод для приостановки игры. } func applicationDidEnterBackground(_ приложение: UIApplication) { // Используйте этот метод для освобождения общих ресурсов, сохранения пользовательских данных, аннулирования таймеров и сохранения достаточного количества информации о состоянии приложения, чтобы восстановить ваше приложение до его текущего состояния в случае, если оно будет остановлено позже. // Если ваше приложение поддерживает фоновое выполнение, этот метод вызывается вместо applicationWillTerminate: когда пользователь завершает работу. } func applicationWillEnterForeground (_ приложение: UIApplication) { // Вызывается как часть перехода из фона в неактивное состояние; здесь вы можете отменить многие изменения, сделанные при входе в фон. } func applicationDidBecomeActive(_ приложение: UIApplication) { // Перезапустить все задачи, которые были приостановлены (или еще не запущены), пока приложение неактивно. Если приложение ранее работало в фоновом режиме, при необходимости обновите пользовательский интерфейс. } func applicationWillTerminate(_ приложение: UIApplication) { // Вызывается, когда приложение вот-вот завершится. Сохраните данные, если это необходимо. См. также приложениеDidEnterBackground:. // Сохраняет изменения в контексте управляемого объекта приложения перед завершением работы приложения. self.saveContext() } // MARK: - Разделить вид func splitViewController(_ splitViewController: UISplitViewController, свернуть вторичный вторичныйViewController:UIViewController, на первичныйViewController:UIViewController) -> Bool { охранять пусть вторичныйAsNavController = вторичныйViewController как? UINavigationController иначе {вернуть ложь} охранять пусть topAsDetailController =secondaryAsNavController. topViewController как? DetailViewController иначе {вернуть false} если topAsDetailController.detailItem == ноль { // Возвращаем true, чтобы указать, что мы обработали коллапс, ничего не делая; вторичный контроллер будет отброшен. вернуть истину } вернуть ложь } // MARK: - Базовый стек данных ленивый var applicationDocumentsDirectory: URL = { // Каталог, который приложение использует для хранения файла хранилища Core Data. Этот код использует каталог с именем «com.senbei.trash» в каталоге поддержки приложений документов приложения. let urls = FileManager.default.urls (для: .documentDirectory, в: .userDomainMask) возвращаемые URL[urls.count-1] }() ленивый вар управляемыйObjectModel: NSManagedObjectModel = { // Модель управляемого объекта для приложения. Это свойство не является необязательным. Неспособность приложения найти и загрузить свою модель является фатальной ошибкой. пусть modelURL = Bundle.main.url (для ресурса: «мусор», withExtension: «momd»)! вернуть NSManagedObjectModel (contentsOf: modelURL)! }() ленивый вар персистентсторекоординатор: NSPersistentStoreCoordinator = { // Координатор постоянного хранилища для приложения. Эта реализация создает и возвращает координатор, добавив в него хранилище для приложения. Это свойство является необязательным, поскольку существуют допустимые условия ошибки, которые могут привести к сбою создания хранилища. // Создаем координатор и сохраняем пусть координатор = NSPersistentStoreCoordinator (managedObjectModel: self.managedObjectModel) let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite") var failureReason = "Произошла ошибка при создании или загрузке сохраненных данных приложения." делать { попробуйте coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil) } ловить { // Сообщаем обо всех полученных ошибках. var dict = [Строка: AnyObject]() dict[NSLocalizedDescriptionKey] = "Не удалось инициализировать сохраненные данные приложения" как AnyObject? dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject? dict[NSUnderlyingErrorKey] = ошибка как NSError пусть wrapError = NSError (домен: "YOUR_ERROR_DOMAIN", код: 9999, информация о пользователе: dict) // Замените это кодом для правильной обработки ошибки. // abort() заставляет приложение генерировать журнал сбоев и завершать работу. Вы не должны использовать эту функцию в отгрузочном приложении, хотя она может быть полезна во время разработки. NSLog("Неразрешенная ошибка \(wrappedError), \(wrappedError.userInfo)") прервать() } координатор возвращения }() ленивый вар управляемыйObjectContext: NSManagedObjectContext = { // Возвращает контекст управляемого объекта для приложения (который уже привязан к координатору постоянного хранилища для приложения). Это свойство является необязательным, поскольку существуют допустимые условия ошибки, которые могут привести к сбою создания контекста. пусть координатор = self.persistentStoreCoordinator var manageObjectContext = NSManagedObjectContext (concurrencyType: .mainQueueConcurrencyType) управляемыйObjectContext.persistentStoreCoordinator = координатор вернуть управляемый объектконтекст }() // MARK: - Поддержка сохранения основных данных функция saveContext () { если manageObjectContext. hasChanges { делать { попробуйте manageObjectContext.save() } ловить { // Замените эту реализацию кодом для правильной обработки ошибки. // abort() заставляет приложение генерировать журнал сбоев и завершать работу. Вы не должны использовать эту функцию в отгрузочном приложении, хотя она может быть полезна во время разработки. пусть nserror = ошибка как NSError NSLog("Неразрешенная ошибка \(nserror), \(nserror.userInfo)") прервать() } } } }
MasterViewController.swift
// // MasterViewController.swift // мусор // // Создано Маркусом 22.05.17. // Copyright © 2017 Маркус. Все права защищены. // импортировать UIKit импортировать CoreData класс MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate { вар detailViewController: DetailViewController? = ноль вар управляемыйObjectContext: NSManagedObjectContext? = ноль переопределить функцию viewDidLoad() { super. viewDidLoad() // Выполните любую дополнительную настройку после загрузки представления, как правило, из пера. self.navigationItem.leftBarButtonItem = self.editButtonItem let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:))) self.navigationItem.rightBarButtonItem = кнопка добавления если позволить разделить = self.splitViewController { пусть контроллеры = split.viewControllers self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController } } переопределить func viewWillAppear (_ анимированный: Bool) { self.clearsSelectionOnViewWillAppear = self.splitViewController!.isCollapsed super.viewWillAppear (анимированный) } переопределить функцию didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Удаляем любые ресурсы, которые можно воссоздать. } func insertNewObject(_ отправитель: AnyObject) { пусть контекст = self. fetchedResultsController.managedObjectContext let entity = self.fetchedResultsController.fetchRequest.entity! let newManagedObject = NSEntityDescription.insertNewObject (forEntityName: entity.name!, into: context) // При необходимости настройте новый управляемый объект. // Обычно вы должны использовать методы доступа, но здесь использование KVC позволяет избежать необходимости добавления пользовательского класса в шаблон. newManagedObject.setValue(Date(), forKey: "timeStamp") // Сохраняем контекст. делать { попробуйте context.save() } ловить { // Замените эту реализацию кодом для правильной обработки ошибки. // abort() заставляет приложение генерировать журнал сбоев и завершать работу. Вы не должны использовать эту функцию в отгрузочном приложении, хотя она может быть полезна во время разработки. //print("Неразрешенная ошибка \(ошибка), \(error.userInfo)") прервать() } } // MARK: - Переходы переопределить функцию подготовки (для перехода: UIStoryboardSegue, отправитель: Any?) { если segue. identifier == "showDetail" { если позволить indexPath = self.tableView.indexPathForSelectedRow { пусть объект = self.fetchedResultsController.object (в: indexPath) let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController контроллер.detailItem = объект controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem controller.navigationItem.leftItemsSupplementBackButton = true } } } // MARK: - Табличное представление переопределить func numberOfSections (в tableView: UITableView) -> Int { вернуть self.fetchedResultsController.sections?.count ?? 0 } переопределить функцию tableView (_ tableView: UITableView, раздел numberOfRowsInSection: Int) -> Int { let sectionInfo = self.fetchedResultsController.sections![раздел] вернуть sectionInfo.numberOfObjects } переопределить функцию tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { пусть ячейка = tableView. dequeueReusableCell (withIdentifier: «Cell», для: indexPath) пусть объект = self.fetchedResultsController.object(at: indexPath) как! NSManagedObject self.configureCell (ячейка, withObject: объект) ячейка возврата } переопределить функцию tableView (_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // Вернуть false, если вы не хотите, чтобы указанный элемент был редактируемым. вернуть истину } переопределить функцию tableView (_ tableView: UITableView, зафиксировать редактированиеStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { если editStyle == .delete { пусть контекст = self.fetchedResultsController.managedObjectContext context.delete(self.fetchedResultsController.object(at: indexPath) as! NSManagedObject) делать { попробуйте context.save() } ловить { // Замените эту реализацию кодом для правильной обработки ошибки. // abort() заставляет приложение генерировать журнал сбоев и завершать работу. Вы не должны использовать эту функцию в отгрузочном приложении, хотя она может быть полезна во время разработки. //print("Неразрешенная ошибка \(ошибка), \(error.userInfo)") прервать() } } } func configureCell (_ ячейка: UITableViewCell, объект withObject: NSManagedObject) { //cell.textLabel!.text = object.value(forKey: "timeStamp")!.description cell.textLabel!.text = (object.value(forKey: "timeStamp")! as AnyObject).description } // MARK: - Получен контроллер результатов //var fetchedResultsController: NSFetchedResultsController { var fetchedResultsController: NSFetchedResultsController{ если _fetchedResultsController != ноль { вернуть _fetchedResultsController! } //пусть fetchRequest = NSFetchRequest() //let fetchRequest = NSFetchRequest (entityName: "Event") //другая альтернатива пусть fetchRequest:NSFetchRequest = NSFetchRequest(entityName: "Event") // Отредактируйте имя объекта соответствующим образом. let entity = NSEntityDescription.entity (forEntityName: «Event», in: self.managedObjectContext!) fetchRequest.entity = сущность // Установите подходящий размер пакета. fetchRequest.fetchBatchSize = 20 // Измените ключ сортировки соответствующим образом. пусть sortDescriptor = NSSortDescriptor (ключ: «timeStamp», по возрастанию: false) fetchRequest.sortDescriptors = [дескриптор сортировки] // Отредактируйте путь ключа имени раздела и имя кеша, если это необходимо. // nil для имени раздела key path означает "нет разделов". let aFetchedResultsController = NSFetchedResultsController (fetchRequest: fetchRequest, manageObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: «Master») aFetchedResultsController.delegate = сам _fetchedResultsController = aFetchedResultsController делать { попробуйте _fetchedResultsController!.performFetch() } ловить { // Замените эту реализацию кодом для правильной обработки ошибки. // abort() заставляет приложение генерировать журнал сбоев и завершать работу. Вы не должны использовать эту функцию в отгрузочном приложении, хотя она может быть полезна во время разработки. //print("Неразрешенная ошибка \(ошибка), \(error.userInfo)") прервать() } вернуть _fetchedResultsController! } //var _fetchedResultsController: NSFetchedResultsController? = ноль var _fetchedResultsController: NSFetchedResultsController ? func controllerWillChangeContent (_ контроллер: NSFetchedResultsController ) { self.tableView.beginUpdates() } контроллер func(_ контроллер: NSFetchedResultsController , didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, для типа: NSFetchedResultsChangeType) { тип переключателя { случай .insert: self.tableView.insertSections (IndexSet (целое число: sectionIndex), с: .fade) случай .удалить: self. tableView.deleteSections (IndexSet (целое число: sectionIndex), с: .fade) дефолт: возвращаться } } контроллер func(_ контроллер: NSFetchedResultsController , didChange anObject: Any, at indexPath: IndexPath?, для типа: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { тип переключателя { случай .insert: tableView.insertRows(в: [newIndexPath!], с: .fade) случай .удалить: tableView.deleteRows(в: [indexPath!], с: .fade) случай .обновление: self.configureCell(tableView.cellForRow(at: indexPath!)!, withObject: anObject as! NSManagedObject) случай .переместить: tableView.moveRow(at: indexPath!, to: newIndexPath!) } } func controllerDidChangeContent (_ контроллер: NSFetchedResultsController ) { self.tableView.endUpdates() } /* // Реализация вышеуказанных методов для обновления табличного представления в ответ на отдельные изменения может повлиять на производительность, если одновременно вносится большое количество изменений. Если это окажется проблемой, вместо этого вы можете просто реализовать controllerDidChangeContent:, который уведомляет делегата о том, что все изменения разделов и объектов были обработаны. func controllerDidChangeContent (контроллер: NSFetchedResultsController) { // В самом простом и эффективном случае перезагрузить табличное представление. self.tableView.reloadData() } */ }
DetailViewController.swift
// // DetailViewController.swift // мусор // // Создано Маркусом 22.05.17. // Copyright © 2017 Маркус. Все права защищены. // импортировать UIKit класс DetailViewController: UIViewController { Слабая переменная @IBOutletDescriptionLabel: UILabel! var detailItem: AnyObject? { сделалSet { // Обновить вид. self.configureView() } } функция configureView() { // Обновить пользовательский интерфейс для элемента сведений. если пусть подробно = self.detailItem { если пусть label = self.detailDescriptionLabel { //label. text = detail.value(forKey: "timeStamp")!.description label.text = (detail.value(forKey: "timeStamp")! as AnyObject).description } } } переопределить функцию viewDidLoad() { super.viewDidLoad() // Выполните любую дополнительную настройку после загрузки представления, как правило, из пера. self.configureView() } переопределить функцию didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Удаляем любые ресурсы, которые можно воссоздать. } }
Модель данных является исходной из шаблона, а также раскадровки. Оба там не модифицированы.
Подробное сравнение Apple Maps на iOS10 и iOS9
На этой неделе вышла новая iOS 10. Конечно, для нас самое интересное — это обновление Apple Maps. Она лучше предыдущей версии? Ознакомьтесь с нашим подробным пошаговым сравнением.
Хорошо. Начнем с самого начала. Я открыл приложение Apple Maps и искал Париж. Разница видна с первого взгляда. iOS 10 добавляет новую информационную вкладку в нижней части экрана, на которой отображается информация, изображения, отзывы и другие параметры, связанные с местом, которое вы ищете. Чуть выше вкладки справа вы можете увидеть небольшую иконку с информацией о погоде в реальном времени. Я должен сказать, что это действительно круто, полезно и интуитивно понятно. Также были перемещены значки «Информация» и «Мое местоположение». Ранее занимавшие много места в нижней части экрана, значки были перемещены в правый верхний угол, что имеет гораздо больше смысла. Глядя на саму карту, различий не так уж и много. Шрифты и цвета кажутся очень похожими с одним отличием, размер названия города намного больше, просто оно выглядит намного лучше.
Мы также можем увидеть значительные изменения в том, как представлен трафик. Маленькие точки в iOS 9 оказались нечитаемыми. В iOS10 дизайнеры Apple пошли по пути Google Maps и представили транспортные потоки в виде разноцветных полос. Когда вы нажимаете на значок события, он становится больше, а подробности отображаются на вкладке данных внизу. Это уменьшило количество кликов по сравнению с iOS 9. Просто и круто.
При увеличении видно, что дизайн карты не трогали. Опять же, когда вы нажимаете на любой значок, он становится больше, и появляется вкладка данных.
Вы можете пролистать его и получить красиво представленную информацию. iOS 9 слева также предлагал некоторую информацию, но представленную в более олдскульном стиле.
Теперь давайте перейдем к навигации. iOS 10, наконец, позволяет вам планировать маршрут из другого источника, кроме вашего местоположения, что было одной из отсутствующих функций iOS 9, и для меня это означает, что iOS 10 становится зрелой навигационной службой. Параметры режима транспортировки были перемещены сверху вниз экрана, что делает их легко доступными на больших экранах iPhone. Uber и Lyft наконец-то были интегрированы в приложение, что было долгожданной функцией для многих пользователей.
Большая зеленая кнопка для запуска маршрута показывает, что приложение было разработано специально для водителей. Это видно везде. Шрифты больше и читабельнее. Данные о маршруте, включая расчетное время в пути, расстояние и время прибытия, перемещены в нижнюю часть экрана. Мне не совсем понятна идея поставить еще и большую красную кнопку для завершения маршрута. Он просто смотрит на то, как вы пытаетесь заставить вас хотеть подтолкнуть его.
Инструкции по вождению короче, но шрифты намного крупнее и очень хорошо читаются. Мне это и вправду нравится.
В iOS 10 удалена возможность переключения между режимами 3D- и 2D-карты, теперь это полностью автоматизировано. Когда вы едете быстрее, приложение переходит в 3D-режим (с перспективой и видимым горизонтом), а когда вы замедляетесь, карта плавно переходит в 2D-режим. Я должен сказать, что это работает очень хорошо, и я бы все равно не стал менять его вручную, но я ожидаю, что у некоторых пользователей могут быть свои предпочтения в этом вопросе.
Параметр сведений о маршруте также разработан специально для водителей благодаря крупным шрифтам и значкам. iOS 10 удалила прошлые маневры из списка, что также имеет большой смысл.
Кроме того, обзор маршрута стал намного нагляднее.