2017-02-20 2 views
0

Мне нужно разрешить пользователям начинать потоковое видео в прямом эфире своим друзьям, нажав на дополнительную кнопкуCameraButton в течение ~ 1,5 секунд. Однако в настоящее время они вынуждены удерживать его все время, и в тот момент, когда они удаляют свой палец с дополнительного камере, CameraView отменяется.Я хочу, чтобы прямой поток запускался с помощью 1,5-секундного крана, но мой код требует, чтобы пользователи удерживали кнопку всего потока.

Я работаю с чьим-то старым кодом, который я только что переделал из Swift 2.2 в Swift 3, и я вижу, что они сделали, но когда я немного изменяю его, чтобы получить минимальное значение для longtap gesture, я получаю фатальные ошибки.

Как любой из вас изменит код, чтобы использовать 1,5-секундный longTap вместо того, чтобы удерживать его на неопределенный срок? В строке 58 у меня есть код для добавления minimumDuration для longTap, но добавление его вызывает всевозможные ошибки, как при отпускании кнопки, CameraView по-прежнему отменяется, даже несмотря на то, что прямой эфир запущен.

import UIKit 
import AVFoundation 

protocol CameraViewDelegate { 
func startStopRecordingVideo(_ isStart: Bool) 
func startStopStream(_ isStart: Bool) 
func cancelCameraView() 
func changeCamera() 
func chooseVideo() 
} 

class CameraView: UIView, UIGestureRecognizerDelegate { 

@IBOutlet weak var flashBtn: UIButton! 
@IBOutlet weak var screenView: UIView! 
@IBOutlet weak var shootBtn: UIButton! 
@IBOutlet weak var changeCameraBtn: UIButton! 
@IBOutlet weak var cancelBtn: UIButton! 
@IBOutlet weak var alphaView: UIView! 
@IBOutlet weak var shootBtnContainerView: UIView! 

var delegate : CameraViewDelegate? 
var isRecording : Bool = false 
var isStreaming: Bool = false 

var circleLayer: CAShapeLayer? 
var timer: Timer? 

//MARK: SYSTEMS METHODS 

class func instanceFromNib() -> CameraView { 
    return UINib(nibName: "View", bundle: nil).instantiate(withOwner: nil,  options: nil)[0] as! CameraView 
} 

override func awakeFromNib() { 
    layoutIfNeeded() 
    shootBtnContainerView.layer.cornerRadius =  shootBtnContainerView.frame.size.width/2 
    shootBtn.layer.cornerRadius = shootBtn.frame.size.width/2 

    let tap = UITapGestureRecognizer(target: self, action: #selector(doubleTapped)) 
    tap.numberOfTapsRequired = 2 
    shootBtn.addGestureRecognizer(tap) 

    let hideTap = UITapGestureRecognizer(target: self, action: #selector(hideTapped)) 
    hideTap.delegate = self 
    alphaView.addGestureRecognizer(hideTap) 

    let hold = UILongPressGestureRecognizer(target: self, action: #selector(longTap)) 
    shootBtn.addGestureRecognizer(hold) 
    //hold.minimumPressDuration = 1.5 

    if Defaults.sharedDefaults.userKnowAboutCamera { 
     alphaView.isHidden = true 
    } 

    let alert = UIAlertController(title: "Testing!", message: nil, preferredStyle: .alert) 
    let action = UIAlertAction(title: "Thank You", style: .default, handler: nil) 
    alert.addAction(action) 

} 

//MARK: - CIRcLE ANIMATION 

func createCirclePath() { 
    let circlePath = UIBezierPath(arcCenter: shootBtnContainerView.center, radius: shootBtnContainerView.frame.size.width/2, startAngle: 0.0, endAngle: CGFloat(.pi * 2.0), clockwise: true) 

    circleLayer = CAShapeLayer() 
    circleLayer!.path = circlePath.cgPath 
    circleLayer!.fillColor = UIColor.clear.cgColor 
    circleLayer!.strokeColor = UIColor.red.cgColor 
    circleLayer!.lineWidth = 3.0; 

    circleLayer!.strokeEnd = 0.0 

    layer.addSublayer(circleLayer!) 
} 

func animateCircle(_ duration: TimeInterval) { 
    circleLayer?.removeFromSuperlayer() 
    createCirclePath() 
    circleLayer!.strokeEnd = 0.0 
    let animation = CABasicAnimation(keyPath: "strokeEnd") 
    animation.duration = duration 
    animation.fromValue = 0 
    animation.toValue = 1 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    circleLayer!.strokeEnd = 1.0 
    circleLayer!.add(animation, forKey: "animateCircle") 
} 


// SHOW HIDE ALPHA VIEW 

func showHideAlphaView(_ isHide: Bool){ 
    Defaults.sharedDefaults.userKnowAboutCamera = true 
    var alpha: Float = 0.0 
    if isHide { alpha = 0.0 } else { alpha = 0.6 } 

    UIView.animate(withDuration: 1.5, animations: { 
     self.alphaView.alpha = CGFloat(alpha) 
     }, completion: nil) 
} 

// ACTIONS 

func hideTapped(){ 
    showHideAlphaView(true) 
} 

func doubleTapped() { 
    delegate?.chooseVideo() 
} 

func longTap(_ sender: UILongPressGestureRecognizer) { 
    print("tapping") 
    if sender.state == .began { 
     SSContact.shared.isStreaming(public: true, to: nil, verification: { (error) in 
      if error != nil { 
       print(error!.localizedDescription) 
      } 
     }, live: { (live, views) in 
      print("Live: \(live) :: With \(views) Views!") 
     }) 
     isRecording = !isRecording 
     delegate?.startStopRecordingVideo(isRecording) 
     isStreaming = !isStreaming 
     delegate?.startStopStream(isStreaming) 
    } else if sender.state == .ended { 
     SSContact.shared.stopStreaming() 
     isRecording = !isRecording 
     delegate?.startStopRecordingVideo(isRecording) 
     isStreaming = !isStreaming 
     delegate?.startStopStream(isStreaming) 
     delegate?.cancelCameraView() 
    } 
} 

func updateTimer() { 
    isRecording = !isRecording 
    delegate?.startStopRecordingVideo(isRecording) 
    timer?.invalidate() 
} 

@IBAction func shootVideo(_ sender: AnyObject) { 
    if !isRecording{ 
     timer = Timer.scheduledTimer(timeInterval: 20.0, target: self, selector: #selector(CameraView.updateTimer), userInfo: nil, repeats: true) 
     animateCircle(20) 
    } else { 
     timer?.invalidate() 
     circleLayer?.removeAnimation(forKey: "animateCircle") 
     circleLayer!.strokeEnd = 0.0 
    } 
    isRecording = !isRecording 
    delegate?.startStopRecordingVideo(isRecording) 
} 

@IBAction func cancelPressed(_ sender: AnyObject) { 
    delegate?.cancelCameraView() 
} 

@IBAction func changeCameraPressed(_ sender: AnyObject) { 
    delegate?.changeCamera() 
} 

@IBAction func flashBtnPressed(_ sender: AnyObject) { 
    let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)! 
    if (device.hasTorch) { 
     do { 
      try device.lockForConfiguration() 
      if device.torchMode == .on { 
       device.torchMode = .off 
       flashBtn.setImage(UIImage(named: "Flash"), for: UIControlState()) 
      } else { 
       flashBtn.setImage(UIImage(named: "NoFlash"), for: UIControlState()) 
       do { 
        try device.setTorchModeOnWithLevel(1.0) 
       } catch { 
        print(error.localizedDescription) 
       } 
      } 
      device.unlockForConfiguration() 
     } catch { 
      print(error.localizedDescription) 
     } 
    } 
} 

@IBAction func loadVideoPressed(_ sender: AnyObject) { 

} 
} 
+0

Посмотрите на ваш 'метод longTap' для' UILongPressGestureRecognizer', вы говорите, 'если sender.state == .ended' в основном остановить потоковое, поэтому всякий раз, когда пользователь отпускает контакт остановится : – Pierce

ответ

0

Посмотрите на ваш метод longTap для UILongPressGestureRecognizer, вы говорите if sender.state == .ended в основном остановить потоковое, поэтому всякий раз, когда пользователь отпускает на ощупь он остановится:

func longTap(_ sender: UILongPressGestureRecognizer) { 

    if sender.state == .began { 
     // Start the stream 
    } else if sender.state == .ended { 
     SSContact.shared.stopStreaming() 
     isRecording = !isRecording 
     delegate?.startStopRecordingVideo(isRecording) 
     isStreaming = !isStreaming 
     delegate?.startStopStream(isStreaming) 
     delegate?.cancelCameraView() 
    } 

} 

Я хотел бы предложить, возможно, имея метод, который управляет началом и останавливая поток на основе вашего isRecording булево, и изменение способа isRecording объявляется использовать didSet:

var isRecording: Bool = false { 
    didSet{ 
     // Manage the stream based on how the variable is set 
     self.manageStream(start: isRecording) 
    } 
} 


func manageStream(start: Bool) { 

    if start { 
     // Start the stream 
     SSContact.shared.isStreaming(public: true, to: nil, verification: { (error) in 
      if error != nil { 
       print(error!.localizedDescription) 
      } 
     }, live: { (live, views) in 
      print("Live: \(live) :: With \(views) Views!") 
     }) 
     isRecording = !isRecording 
     delegate?.startStopRecordingVideo(isRecording) 
     isStreaming = !isStreaming 
     delegate?.startStopStream(isStreaming) 
    } 
    else { 
     // Stop the stream 
     SSContact.shared.stopStreaming() 
     isRecording = !isRecording 
     delegate?.startStopRecordingVideo(isRecording) 
     isStreaming = !isStreaming 
     delegate?.startStopStream(isStreaming) 
     delegate?.cancelCameraView() 
    } 

} 

Теперь у ожно использовать longPress распознаватель, чтобы начать и остановить потоковую:

func longTap(_ sender: UILongPressGestureRecognizer) { 

    isRecording = !isRecording 

} 

Можно даже изменить продолжительность печати, как, скажем, вы хотите минимальную длительность нажмите, чтобы быть намного меньше, чтобы повернуть поток от в отличие от поворачивая его на:

func longTap(_ sender: UILongPressGestureRecognizer) { 

    isRecording = !isRecording 
    if isRecording { 
     // Make the minimum duration zero so they just need to tap to turn it off 
     sender.minimumPressDuration = 0 
    } else { 
     // Make the minimum duration back to 1.5 seconds so they have to hold to turn it on 
     sender.minimumPressDuration = 1.5 
    } 

} 
+0

У меня это работает!Придется внести небольшие коррективы в код, чтобы он соответствовал всему, но теперь он стал гладко, как свисток. Благодаря! –

+0

@ JustinHodges - Конечно! Удачи – Pierce

0

Ваш UILongPressGestureRegonizer сек цель longTap(_:). Этот метод будет выполняться всякий раз, когда распознаватель жестов запускает событие. Давайте рассмотрим вашу реализацию этого метода, то:

func longTap(_ sender: UILongPressGestureRecognizer) { 
    print("tapping") 
    if sender.state == .began { 
     // ... 
     delegate?.startStopStream(isStreaming) 
    } else if sender.state == .ended { 
     SSContact.shared.stopStreaming() 
     // ... 
    } 
} 

я заменил некоторый код с // ... сосредоточиться на том, что здесь имеет значение. Как вы можете видеть, UILongPressGestureReconizer может иметь несколько состояний (также см. API Reference). В вашем коде вы обрабатываете два из них: .began и .ended.

Состояние распознавателей жестов будет .began, как только ваш жест будет распознан (то есть, длительное нажатие было выполнено пользователем). В этой ветке if вы начинаете запись с камеры, а также ваш поток. С другой стороны, в вашей ветке .ended вы останавливаете свой поток. Состояние будет .ended, когда жест заканчивается (т. Е. Когда пользователь поднимает палец, когда длинное нажатие заканчивается).

Если вы хотите, чтобы поток продолжался после длительного нажатия, просто удалите ветвь .ended.

Смежные вопросы