Вступление
ReplayKit — это новый фреймворк, который был представлен вместе с iOS 9. Он позволяет разработчикам игр давать игрокам возможность легко записывать и делиться игровым процессом. В дополнение к записи и обмену, ReplayKit также включает в себя полнофункциональный пользовательский интерфейс, который игроки могут использовать для редактирования своих видеоклипов.
Записи, производимые ReplayKit, имеют высокое разрешение и создаются с минимальным энергопотреблением и потерей производительности. Функции ReplayKit доступны для каждого устройства с системой на кристалле A7, A8 или A9 (каждое устройство, поддерживающее Metal), работающей под управлением iOS 9 или более поздней версии.
Предпосылки
Это руководство требует, чтобы вы работали с Xcode 7+ в OS X Yosemite или более поздней версии. Если вы хотите протестировать пример проекта на устройстве, то вам также необходимо устройство с поддержкой ReplayKit. Вам также необходимо скачать стартовый проект с GitHub .
1. Инициирование записей
Запись игрового процесса с помощью ReplayKit начинается с класса RPScreenRecorder
и sharedRecorder()
доступных для вашего приложения. Этот рекордер отвечает за проверку способности устройства записывать, запускать, останавливать и отбрасывать записи, а также дополнительно включать микрофон устройства, позволяющий игрокам добавлять свои собственные голосовые комментарии к звуку игры.
Откройте стартовый проект, который вы загрузили с GitHub, и перейдите на GameViewController.swift . В верхней части этого файла добавьте оператор импорта для инфраструктуры ReplayKit.
1
|
import ReplayKit
|
Затем реализуйте метод startRecording(_:)
в классе GameViewController
. Этот метод вызывается, когда пользователь нажимает кнопку « Начать запись» .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
func startRecording(sender: UIButton) {
if RPScreenRecorder.sharedRecorder().available {
RPScreenRecorder.sharedRecorder().startRecordingWithMicrophoneEnabled(true, handler: { (error: NSError?) -> Void in
if error == nil { // Recording has started
sender.removeTarget(self, action: «startRecording:», forControlEvents: .TouchUpInside)
sender.addTarget(self, action: «stopRecording:», forControlEvents: .TouchUpInside)
sender.setTitle(«Stop Recording», forState: .Normal)
sender.setTitleColor(UIColor.redColor(), forState: .Normal)
} else {
// Handle error
}
})
} else {
// Display UI for recording being unavailable
}
}
|
Давайте пройдемся по этому методу шаг за шагом. Мы RPScreenRecorder
экземпляру RPScreenRecorder
доступному для нашего приложения, через метод sharedRecorder()
и проверяем, доступна ли запись для устройства.
Если запись доступна, мы начинаем запись, вызывая метод startRecordingWithMicrophone(_:handler:)
для объекта общего записывающего устройства. Параметры для этого метода — логическое значение, указывающее, хотите ли вы использовать микрофон устройства, и обработчик завершения. Обработчик завершения имеет доступ к необязательному объекту ошибки, который возвращается вам платформой ReplayKit, если что-то пойдет не так. Если инфраструктура не выдавала ошибку, мы настраиваем цель и внешний вид кнопки, чтобы пользователь мог остановить запись, когда будет готов.
Создайте и запустите свое приложение и опробуйте приложение, нажав зеленую кнопку. Вы увидите, что система частиц в сцене генерирует частицы, пока нажата зеленая кнопка. Если вы нажмете Начать запись , вы должны увидеть следующее предупреждение:
Обратите внимание, что это предупреждение будет появляться каждый раз, когда вы начинаете запись в своем приложении. Однако, как только пользователь выберет один из этих параметров, его предпочтения будут запомнены, и ни одно из этих предупреждений не будет отображаться в течение следующих восьми минут.
После выбора одного из этих параметров в предупреждении кнопка « Начать запись» должна превратиться в красную кнопку « Остановить запись» .
2. Остановка, удаление и редактирование записей
Теперь, когда наше приложение способно запускать записи ReplayKit, пришло время узнать, как обрабатывать эти записи, когда закончите. stopRecording(_:)
метод stopRecording(_:)
в классе GameViewController
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
func stopRecording(sender: UIButton) {
RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void in
if previewController != nil {
let alertController = UIAlertController(title: «Recording», message: «Do you wish to discard or view your gameplay recording?», preferredStyle: .Alert)
let discardAction = UIAlertAction(title: «Discard», style: .Default) { (action: UIAlertAction) in
RPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in
// Executed once recording has successfully been discarded
})
}
let viewAction = UIAlertAction(title: «View», style: .Default, handler: { (action: UIAlertAction) -> Void in
self.presentViewController(previewController!, animated: true, completion: nil)
})
alertController.addAction(discardAction)
alertController.addAction(viewAction)
self.presentViewController(alertController, animated: true, completion: nil)
sender.removeTarget(self, action: «stopRecording:», forControlEvents: .TouchUpInside)
sender.addTarget(self, action: «startRecording:», forControlEvents: .TouchUpInside)
sender.setTitle(«Start Recording», forState: .Normal)
sender.setTitleColor(UIColor.blueColor(), forState: .Normal)
} else {
// Handle error
}
}
}
|
Еще раз, давайте пройдемся по этому методу шаг за шагом. Мы вызываем метод stopRecordingWithHandler(_:)
для общего объекта рекордера. В этом обработчике завершения мы проверяем, успешно ли завершена запись, проверяя, существует ли previewController
.
Мы создаем UIAlertController
с двумя действиями: одно для UIAlertController
записи и одно для просмотра записи. Если пользователь решает отказаться от записи, мы вызываем discardRecordingWithHandler(_:)
. Обратите внимание, что этот метод может быть успешно вызван только после завершения записи . Если вы вызываете этот метод во время выполнения записи, ошибка не выдается, но данные записи также не удаляются.
Если пользователь выбирает просмотр записи, мы представляем previewController
, экземпляр класса RPPreviewController
, переданный нам методом stopRecordingWithHandler(_:)
где пользователь может просматривать, редактировать и делиться своей записью. Контроллер предварительного просмотра является единственным объектом, который имеет доступ к видеофайлу, созданному ReplayKit, и отвечает за сохранение / совместное использование этой записи.
Наконец, мы возвращаем кнопку обратно в исходное состояние, чтобы можно было сделать другую запись, если пользователь захочет.
Создайте и запустите приложение снова и начните запись. После того как вы нажмете кнопку « Остановить запись» , вы должны увидеть следующее предупреждение:
Если вы затем нажмете на опцию View , будет представлен следующий контроллер вида.
На этом экране вы можете отредактировать видео и сохранить его в списке камер вашего устройства, нажав кнопку « Сохранить» . Вы также можете поделиться им, нажав кнопку в левом нижнем углу.
Обратите внимание, что во время написания этого учебника, либо из-за ошибки, либо из-за ошибки в инфраструктуре ReplayKit, подтверждения не будет после сохранения записи в списке камер.
3. Исключая элементы интерфейса
Возможно, вы заметили, что верхняя и нижняя кнопки также видны на записях, сделанных приложением. Они включены в финальное видео. Когда ReplayKit записывает ваше приложение, оно записывает все в основном экземпляре UIWindow
вашего приложения. К счастью, ReplayKit автоматически исключает любые входящие уведомления и пользовательский ввод из записи.
Чтобы исключить элементы пользовательского интерфейса из записи, вам необходимо поместить их в отдельный экземпляр UIWindow
. Посмотрим, как это работает. Добавьте свойство buttonWindow
типа UIWindow!
, в класс GameViewController
.
1
|
var buttonWindow: UIWindow!
|
Затем замените текущую реализацию метода addButtons(_:)
класса GameViewController
следующей реализацией:
1
2
3
4
5
6
7
8
9
|
func addButtons(buttons: [UIButton]) {
self.buttonWindow = UIWindow(frame: self.view.frame)
self.buttonWindow.rootViewController = HiddenStatusBarViewController()
for button in buttons {
self.buttonWindow.rootViewController?.view.addSubview(button)
}
self.buttonWindow.makeKeyAndVisible()
}
|
В addButtons(_:)
мы создаем новый объект UIWindow
, добавляем к нему кнопки и делаем его видимым. Обратите внимание, что класс HiddenStatusBarViewController
— это пользовательский класс, который я добавил в стартовый проект. Это гарантирует, что строка состояния остается скрытой в новом окне.
Наконец, замените реализацию метода stopRecording(:_)
на следующую реализацию:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
func stopRecording(sender: UIButton) {
RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void in
if previewController != nil {
let alertController = UIAlertController(title: «Recording», message: «Do you wish to discard or view your gameplay recording?», preferredStyle: .Alert)
let discardAction = UIAlertAction(title: «Discard», style: .Default) { (action: UIAlertAction) in
RPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in
// Executed once recording has successfully been discarded
})
}
let viewAction = UIAlertAction(title: «View», style: .Default, handler: { (action: UIAlertAction) -> Void in
self.buttonWindow.rootViewController?.presentViewController(previewController!, animated: true, completion: nil)
})
alertController.addAction(discardAction)
alertController.addAction(viewAction)
print(self.buttonWindow.rootViewController)
self.buttonWindow.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
sender.removeTarget(self, action: «stopRecording:», forControlEvents: .TouchUpInside)
sender.addTarget(self, action: «startRecording:», forControlEvents: .TouchUpInside)
sender.setTitle(«Start Recording», forState: .Normal)
sender.setTitleColor(UIColor.blueColor(), forState: .Normal)
} else {
// Handle error
}
}
}
|
Единственное отличие состоит в том, что мы заставляем контроллер представления в новом, самом верхнем окне обрабатывать все презентации. Это гарантирует, что все отображается правильно и с пользовательским интерфейсом можно взаимодействовать.
Запустите ваше приложение еще раз и сделайте новую запись. Вы увидите, что кнопки больше не видны на видео:
4. Делегатские протоколы
Хотя этот учебник не используется, существует два протокола и всего четыре метода, связанных с ReplayKit. Давайте посмотрим, как вы можете использовать их.
Протокол RPScreenRecorderDelegate
определяет следующие методы:
-
screenRecorder(_:didStopRecordingWithError:previewViewController:)
: этот метод вызывается при возникновении ошибки во время записи. Если ReplayKit сможет восстановиться после этой ошибки и завершить запись, вам также будет предоставлен контроллер предварительного просмотра, который вы можете представить своему пользователю. -
screenRecorderDidChangeAvailability(_:)
: этот метод вызывается всякий раз, когда запись становится доступной или недоступной из-за другого действия. Это может произойти, например, при подключении или отключении от AirPlay.
Протокол RPPreviewViewControllerDelegate
определяет следующие методы:
-
previewViewControllerDidFinish(_:)
вызывается, как только пользовательRPPreviewViewController
экземплярRPPreviewViewController
. -
previewViewController(_:didFinishWithActivityTypes:)
вызывается одновременно сpreviewViewControllerDidFinish(_:)
, но предоставляет дополнительный параметрUIActivity
.
Обратите внимание, что если вы реализуете любой из методов RPPreviewViewControllerDelegate
, то вы несете ответственность за увольнение контроллера предварительного просмотра в соответствующее время.
5. Важные замечания
В заключение я расскажу вам несколько ключевых моментов, которые следует учитывать при работе с ReplayKit.
- Для каждого приложения может быть сохранена только одна запись. Как только вы начинаете новую запись, если предыдущая запись существует, она автоматически удаляется и больше не доступна.
- Откажитесь от записи как можно скорее. Чтобы гарантировать, что локальное хранилище устройства не будет заполнено ненужными видеоданными, отмените записи, как только вы узнаете, что пользователь не сможет или не сможет получить доступ к их записи на более позднем этапе. В этом уроке мы следовали этой наилучшей практике, отбрасывая запись, как только мы знали, что пользователь не хочет ее просматривать.
- Отображение индикаторов записи. Как и в этом уроке, показ индикатора записи имеет важное значение для хорошего взаимодействия с пользователем при использовании ReplayKit, особенно при использовании микрофона устройства.
- Тщательно выберите элементы пользовательского интерфейса, которые следует исключить из записей. При выборе элементов интерфейса для размещения в отдельном окне выберите любые элементы, которые не важны или отвлекают от самого игрового процесса. Это включает в себя такие вещи, как индикаторы записи, виртуальные элементы управления и кнопки меню.
- У вас нет прямого доступа к финальному видеофайлу. Только ReplayKit содержит ссылку на записи вашего приложения в хранилище и делает их видимыми для пользователя через
RPPreviewViewController
. В целях конфиденциальности записи ReplayKit никогда не доступны напрямую вашему приложению. Например, если вы хотите загрузить запись игрового процесса на свои собственные серверы, вам нужно будет создать расширение общего доступа, которое будет отображаться в общем списке, который представлен контроллером предварительного просмотра. - ReplayKit поддерживает родительский контроль. Даже если ваше приложение работает на совместимом устройстве, а другие приложения не работают в фоновом режиме, запуск записи по-прежнему можно предотвратить из-за родительского контроля. Это означает, что вам всегда нужно проверять, доступна ли запись видео.
- И наконец, даже несмотря на то, что Apple ориентировала ReplayKit на разработчиков игр, чтобы позволить геймерам делиться игровым процессом, ничто не мешает вам использовать ReplayKit в обычном приложении. ReplayKit доступен для каждого приложения, созданного с помощью Xcode 7 и iOS 9 SDK. Если вы используете его в своем приложении, я призываю вас использовать эту замечательную платформу.
Вывод
Теперь вам должно быть удобно использовать новую платформу ReplayKit для создания записей экрана вашего приложения, которые могут быть отредактированы и доступны вашим пользователям. В целом, ReplayKit — это очень компактная, но мощная инфраструктура, которая позволяет разработчикам легко создавать записи в своих приложениях, которые будут доступны пользователям.
Как всегда, обязательно оставляйте любые комментарии или отзывы в комментариях ниже.