2016-09-30 55 views
5

我在我的SpriteKit遊戲中實現了ReplayKit,但由於所有操作均在GameViewController之內完成,因此錄製按鈕顯得太早。請參閱我下面GameViewController類:如何在SpriteKit中啓動ReplayKit屏幕錄製SKScene類

class GameViewController: UIViewController, RPPreviewViewControllerDelegate { 

var videoRecButton: UIButton! 
var videoRecImage: UIImage! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    let skView = self.view as? SKView 

    if skView?.scene == nil { 
     skView?.showsFPS = true 
     skView?.showsNodeCount = true 
     skView?.showsPhysics = true 
     skView?.ignoresSiblingOrder = false 

     //starting the game with the Poster Scene 
     let posterScene = PosterScene(size: skView!.bounds.size) 
     posterScene.scaleMode = .aspectFill 
     skView?.presentScene(posterScene) 
    } 

    videoRecButton = UIButton(type: .custom) 
    videoRecImage = UIImage(named:"videoRecButton.png") 

    videoRecButton.frame = CGRect(x:0, y: 0, width: (videoRecImage?.size.width)!, height: (videoRecImage?.size.height)!) 
    videoRecButton.setImage(videoRecImage, for: .normal) 
    videoRecButton.addTarget(self, action:#selector(self.videoRecButtonClicked), for: .touchUpInside) 
    self.view.addSubview(videoRecButton) 
} 

func videoRecButtonClicked() { 
    print("Button Clicked") 
    startRecording() 
} 

func startRecording() { 
    let recorder = RPScreenRecorder.shared() 

    recorder.startRecording{ [unowned self] (error) in 
     if let unwrappedError = error { 
      print(unwrappedError.localizedDescription) 
     } else { 

      self.videoRecButton.addTarget(self, action:#selector(self.stopRecording), for: .touchUpInside) 
     } 
    } 
} 

func stopRecording() { 
    let recorder = RPScreenRecorder.shared() 

    recorder.stopRecording { [unowned self] (preview, error) in 
     self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Start", style: .plain, target: self, action: #selector(self.startRecording)) 

     if let unwrappedPreview = preview { 
      unwrappedPreview.previewControllerDelegate = self 
      self.present(unwrappedPreview, animated: true) 
     } 
    } 
} 

func previewControllerDidFinish(_ previewController: RPPreviewViewController) { 
    dismiss(animated: true) 
} 

override var shouldAutorotate: Bool { 
    return true 
} 

override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 
    if UIDevice.current.userInterfaceIdiom == .phone { 
     return .allButUpsideDown 
    } else { 
     return .all 
    } 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Release any cached data, images, etc that aren't in use. 
} 

override var prefersStatusBarHidden: Bool { 
    return true 
} 
} 
  1. 我如何可以調用startRecordingstopRecording功能從從SKScene繼承像GameScene類的類?

  2. 如何啓用,禁用並隱藏GameScene類中的videoRecButton按鈕?

UPDATE

基於從crashoverride777一個放在下面的代碼的答案在我的SKScene類,但與記錄的視頻的預覽會出現在導航控制器之前,只需幾秒鐘後,畫面記錄。錄製的視頻只是一個黑屏,取消和保存按鈕無響應。

func startRecording() { 
    let recorder = RPScreenRecorder.shared() 

    if #available(iOS 10.0, *) { 
     recorder.startRecording{ [unowned self] (error) in 
      if let unwrappedError = error { 
       print(unwrappedError.localizedDescription) 
      } else { 

       self.stopRecording() 

      } 
     } 
    } else { 
     // Fallback on earlier versions 
    } 
} 

func stopRecording() { 
    let recorder = RPScreenRecorder.shared() 

    recorder.stopRecording { [unowned self] (preview, error) in 
     self.view?.window?.rootViewController?.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Start", style: .plain, target: self, action: #selector(self.startRecording)) 

     if let unwrappedPreview = preview { 
      unwrappedPreview.previewControllerDelegate = self 
      self.view?.window?.rootViewController?.present(unwrappedPreview, animated: true) 
     } 
    } 

} 

func previewControllerDidFinish(_ previewController: RPPreviewViewController) { 
    view?.window?.rootViewController?.dismiss(animated: true) 
} 

我創建了一個錄音按鈕:

let videoRecButtonSprite = SKSpriteNode(imageNamed: "videoButton") 
videoRecButtonSprite.position = CGPoint(x: self.frame.width/15, y: self.frame.height - self.frame.height/12) 
self.addChild(videoRecButtonSprite) 

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 

    for touch: AnyObject in touches { 
     let location = touch.location(in: self) 
     if videoRecButtonSprite.contains(location){ 
      startRecording() 
     } 
    } 
} 

回答

3

在GameViewController你不應該建立自己的按鈕,直接在您的SKScene創建它。在SpriteKit遊戲中使用GameViewController進行用戶界面不是很好的做法。

有很多關於如何在SpriteKit中創建按鈕的教程。

關於ReplayKit,您可以直接在您想要的SKScene中使用它,只需要獲取已經存在的代碼並將其移動到相關的場景。

呈現預覽視圖控制器在SKScene你可以說這

view?.window?.rootViewController?.present(unwrappedPreview, animated: true) 

我也注意到你停止錄音後您呈現視圖控制器。你確定你想要這樣做?通常,您可以在遊戲菜單中的單獨按鈕中查看錄製內容。

這裏是一般的代碼。我也建議你看看蘋果示例遊戲DemoBots。

我個人使用一個Singleton類來管理錄音,這樣一來,管理者就可以更輕鬆地調用所有的方法來處理不同的場景。要開始創建一個新的swift文件並添加此代碼。

class ScreenRecoder: NSObject { 

     /// Shared instance 
     static let shared = ScreenRecorder() 

     /// Preview controller 
     var previewController: RPPreviewViewController? 

     /// Private singleton init 
     private override init() { } 
} 

比開始記錄添加此方法到ScreenRecorder類。

func start() { 
    let sharedRecorder = RPScreenRecorder.shared() 

    // Do nothing if screen recording is not available 
    guard sharedRecorder.isAvailable else { return } 

    // Stop previous recording if necessary 
    if sharedRecorder.isRecording { 
     stopScreenRecording() 
    } 

    print("Starting screen recording") 

    // Register as the recorder's delegate to handle errors. 
    sharedRecorder.delegate = self 

    // Start recording 
    if #available(iOS 10.0, *) { 
     #if os(iOS) 
      sharedRecorder.isMicrophoneEnabled = true 
      //sharedRecorder.isCameraEnabled = true // fixme 
     #endif 

     sharedRecorder.startRecording { [unowned self] error in 
      if let error = error as? NSError, error.code != RPRecordingErrorCode.userDeclined.rawValue { 
       print(error.localizedDescription) 
       // Show alert 
       return 
      } 
     } 
    } else { 
     // Fallback on earlier versions 
     sharedRecorder.startRecording(withMicrophoneEnabled: true) { error in 
      if let error = error as? NSError, error.code != RPRecordingErrorCode.userDeclined.rawValue { 
       print(error.localizedDescription) 
       // Show alert 
       return 
      } 
     } 
    } 
} 

要停止錄製呼叫此。您注意到我並未實際顯示預覽,我只是將其存儲起來供以後使用。這是通常的做法。

func stop() { 
    let sharedRecorder = RPScreenRecorder.shared() 

    // Do nothing if screen recording is not available 
    guard sharedRecorder.isAvailable else { return } 

    // Stop recording 
    sharedRecorder.stopRecording { [unowned self] (previewViewController, error) in 
     if let error = error { 
      // If an error has occurred, display an alert to the user. 
      print(error.localizedDescription) 
      // Show alert 
      return 
     } 

     print("Stop screen recording") 

     if let previewViewController = previewViewController { 
      // Set delegate to handle view controller dismissal. 
      previewViewController.previewControllerDelegate = self 

      /* 
      Keep a reference to the `previewViewController` to 
      present when the user presses on preview button. 
      */ 
      self.previewViewController = previewViewController 
     } 
    } 
} 

在符合ReplayKit委託的ScreenRecorder類中創建2個擴展。

預覽控制器代表

/// RPPreviewViewControllerDelegate 
extension ScreenRecorder: RPPreviewViewControllerDelegate { 

    /// Preview controller did finish 
    func previewControllerDidFinish(_ previewController: RPPreviewViewController) { 
      previewController.dismiss(animated: true, completion: nil) 
    } 
} 

和記錄代表

extension ScreenRecorder: RPScreenRecorderDelegate { 

     /// Screen recoder did stop with error 
     func screenRecorder(_ screenRecorder: RPScreenRecorder, didStopRecordingWithError error: Error, previewViewController: RPPreviewViewController?) { 

     // Display the error the user to alert them that the recording failed. 
     let error = error as NSError 
     if error.code != RPRecordingErrorCode.userDeclined.rawValue { 
      print(message: error.localizedDescription) 
      // show alert 
     } 

     // Hold onto a reference of the `previewViewController` if not nil. 
     if let previewViewController = previewViewController { 
      self.previewViewController = previewViewController  
     } 
     } 

     /// Screen recoder did change availability 
     func screenRecorderDidChangeAvailability(_ screenRecorder: RPScreenRecorder) { 
      // e.g update your button UI etc 
      // you can use something like delegation to pass something to your SKScenes 
    } 
} 

最後創建呈現預覽的方法。最好你通過菜單上的遊戲按鈕來調用它。

func showPreview() { 
    guard let previewViewController = previewViewController else { return } 

    print("Showing screen recording preview") 

    // `RPPreviewViewController` only supports full screen modal presentation. 
    previewViewController.modalPresentationStyle = .fullScreen 

    let rootViewController = UIApplication.shared.keyWindow?.rootViewController 
    rootViewController?.present(previewViewController, animated: true, completion:nil) 
} 

現在,你可以在任何地方,你想叫你的項目

ScreenRecorder.shared.start() 
ScreenRecorder.shared.stop() 
ScreenRecorder.shared.showPreview() // call stop before calling this 

此代碼是非常直出DemoBots的方法。

我覺得處理的屏幕錄製的最好的方式是通過在主菜單中創建一個自動錄製按鈕。使用UserDefaults保存它的開/關狀態。如果開啓,則在遊戲開始時調用startRecording,並在遊戲結束時調用停止記錄。如果用戶想要,您可以在菜單上顯示遊戲中的預覽按鈕以觀看錄製內容。

希望這有助於

+0

謝謝。我剛剛更新了這個問題 – iGetIt

+0

爲什麼您想要導航控制器來顯示屏幕錄製?只需直接提供重放套件視圖控制器即可。你不是真的應該在SpriteKit中使用UIKit。我會更新我的答案,給我像2-3分鐘 – crashoverride777

+0

更新我的答案與完整的代碼示例屏幕錄製。希望這可以幫助。保持我張貼 – crashoverride777

0

DemoBots是很難的。請記得導入ReplayKit,RPPreviewViewControllerDelegate,RPScreenRecorderDelegate。你可以將你的最終代碼發佈到GitHub上嗎?crashoverride777。這是我寫的,我不能預覽顯示:

func startRecording() { 
    let sharedRecorder = RPScreenRecorder.shared() 

    // Do nothing if screen recording is not available 
    guard sharedRecorder.isAvailable else { return } 

    // Stop previous recording if necessary 
    if sharedRecorder.isRecording { 
     stopScreenRecording() 
    } 

    print("Starting screen recording") 

    // Register as the recorder's delegate to handle errors. 
    sharedRecorder.delegate = self 

    // Start recording 
    sharedRecorder.isMicrophoneEnabled = true 
    //sharedRecorder.isCameraEnabled = true // fixme 


    sharedRecorder.startRecording { error in 
     if let error = error as NSError?, error.code != RPRecordingErrorCode.userDeclined.rawValue { 
      print(error.localizedDescription) 
      // Show alert 
      return 
     } 
    } 
} 

func stopScreenRecording() { 
    let sharedRecorder = RPScreenRecorder.shared() 

    // Do nothing if screen recording is not available 
    guard sharedRecorder.isAvailable else { return } 

    // Stop recording 
    sharedRecorder.stopRecording { [unowned self] (previewViewController, error) in 
     if let error = error { 
      // If an error has occurred, display an alert to the user. 
      print(error.localizedDescription) 
      // Show alert 
      return 
     } 

     print("Stop screen recording") 

     if let previewViewController = previewViewController { 
      // Set delegate to handle view controller dismissal. 
      previewViewController.previewControllerDelegate = self 

      /* 
      Keep a reference to the `previewViewController` to 
      present when the user presses on preview button. 
      */ 
      self.previewController = previewViewController 
     } 
    } 
} 

func previewControllerDidFinish(_ previewController: RPPreviewViewController) { 
    view?.window?.rootViewController?.dismiss(animated: true) 
}