我正在使用xcode 6和swift来制作带有视频聊天功能的应用 - 使用OpenTok。 我有2个场景“菜单”和“视频”。从菜单我使用:
self.performSegueWithIdentifier("StreamScene", sender: self)
在一个按钮内去“视频”viewcontroller。我第一次加载我的APP一切都很完美,但是当我从“视频”导航回“菜单”,然后再次从“菜单”导航到“视频”时它无法正常工作我无法看到订阅者到我的会话,但当我关闭我的APP但仍然让视频会话运行并再次启动我的应用程序并导航到“视频”viewcontroller它工作 - 这是因为我的ViewControler可能无法正确加载?我还使用perfomrSegueWithIdentifier进行导航。
来自视频viewcontroller的代码
import UIKit
//Api key
private let ApiKey = "45309032"
//Session ID
private let SessionID = HttpPost.SessionId
//Token
private let Token = HttpPost.Token
let SubscribeToSelf = false
class ViewController: UIViewController, OTSessionDelegate, OTSubscriberKitDelegate, OTPublisherDelegate {
@IBOutlet weak var DoctorDeclienBtn: UIButton!
var Session : OTSession?
var Publisher : OTPublisher?
var Subscriber : OTSubscriber?
var http = HttpPost()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
// Step 2: As the view comes into the foreground, begin the connection process.
//ConnectToSession()
println("Session ID " + SessionID)
println("Token " + Token)
// Do any additional setup after loading the view, typically from a nib.
// Step 1: As the view is loaded initialize a new instance of OTSession
if(HttpPost.Role == "0")
{
DoctorDeclienBtn.hidden = true
}
ConnectToSession()
}
@IBAction func GoBackBtn(sender: AnyObject) {
self.performSegueWithIdentifier("a", sender: self)
DisconnectSession()
}
@IBAction func DoctorDeclineBtn(sender: AnyObject) {
http.HttpPostVideoEnded("access_token=" + HttpPost.AccessToken, URL: "http://95.85.53.176/nhi/api/app/consultation/end/", completionHandler: {(EndSuccess: Int32) -> () in
if(EndSuccess == 1)
{
if let session = self.Session
{
var Error : OTError?
session.disconnect(&Error)
if let error = Error
{
}
}
}
})
}
// MARK: - OpenTok Methods
/**
* Asynchronously begins the session connect process. Some time later, we will
* expect a delegate method to call us back with the results of this action.
*/
func ConnectToSession ()
{
Session = OTSession(apiKey: ApiKey, sessionId: SessionID, delegate: self)
if let session = self.Session
{
var Error : OTError?
session.connectWithToken(Token, error: &Error)
if let error = Error
{
}
}
}
/**
* Sets up an instance of OTPublisher to use with this session. OTPubilsher
* binds to the device camera and microphone, and will provide A/V streams
* to the OpenTok session.
*/
func PublishToSession()
{
Publisher = OTPublisher(delegate: self)
var Error : OTError?
Session?.publish(Publisher, error: &Error)
if let error = Error
{
//Some message
}
//The resolutuon of current device
var sizeRect = UIScreen.mainScreen().applicationFrame
var width = sizeRect.size.width
var height = sizeRect.size.height
Publisher!.view.frame = CGRect(x: width-(width/4), y: height * (4/5), width: width/4, height: height/3)
view.addSubview(Publisher!.view)
}
//Unpublish to session
func UnPublishToSession()
{
Publisher = OTPublisher(delegate: self)
var Error : OTError?
Session?.unpublish(Publisher, error: &Error)
if let error = Error
{
//Some message
}
Publisher!.view.removeFromSuperview()
self.Publisher = nil
}
/**
* Instantiates a subscriber for the given stream and asynchronously begins the
* process to begin receiving A/V content for this stream. Unlike doPublish,
* this method does not add the subscriber to the view hierarchy. Instead, we
* add the subscriber only after it has connected and begins receiving data.
*/
func SubscribeToStream(stream : OTStream) {
if let session = self.Session {
Subscriber = OTSubscriber(stream: stream, delegate: self)
var Error : OTError?
session.subscribe(Subscriber, error: &Error)
if let error = Error {
}
}
}
func DisconnectSession()
{
if let session = self.Session
{
var Error : OTError?
session.disconnect(&Error)
if let error = Error
{
NSLog("Disconnect failed")
}
}
}
/**
* Cleans the subscriber from the view hierarchy, if any.
*/
func UnsubscribeStream() {
if let subscriber = self.Subscriber {
var Error : OTError?
Session?.unsubscribe(Subscriber, error: &Error)
if let error = Error {
}
subscriber.view.removeFromSuperview()
self.Subscriber = nil
}
}
// MARK: - OTSession delegate callbacks
func sessionDidConnect(session : OTSession) {
NSLog("sessionDidConnect (\(session.sessionId))")
// Step 2: We have successfully connected, now instantiate a publisher and
// begin pushing A/V streams into OpenTok.
PublishToSession()
}
func sessionDidDisconnect(session : OTSession) {
NSLog("Session disconnected (\( session.sessionId))")
UnPublishToSession()
self.performSegueWithIdentifier("a", sender: self)
}
func session(session: OTSession, streamCreated stream: OTStream) {
NSLog("session streamCreated (\(stream.streamId))")
// Step 3a: (if NO == subscribeToSelf): Begin subscribing to a stream we
// have seen on the OpenTok session.
if Subscriber == nil && !SubscribeToSelf{
SubscribeToStream(stream)
}
}
func session(session: OTSession, streamDestroyed stream: OTStream) {
NSLog("session streamDestroyed (\(stream.streamId))")
if Subscriber?.stream.streamId == stream.streamId {
UnsubscribeStream()
}
DisconnectSession()
}
func session(session: OTSession, connectionCreated connection : OTConnection) {
NSLog("session connectionCreated (\(connection.connectionId))")
}
func session(session: OTSession, connectionDestroyed connection : OTConnection) {
NSLog("session connectionDestroyed (\(connection.connectionId))")
}
func session(session: OTSession, didFailWithError error: OTError) {
NSLog("session didFailWithError (%@)", error)
}
// MARK: - OTSubscriber delegate callbacks
func subscriberDidConnectToStream(subscriberKit: OTSubscriberKit) {
NSLog("subscriberDidConnectToStream (\(subscriberKit))")
var sizeRect = UIScreen.mainScreen().applicationFrame
var width = sizeRect.size.width
var height = sizeRect.size.height
if let view = Subscriber?.view {
view.frame = CGRect(x: 0, y: 0, width: width, height: height + 20)
self.view.addSubview(view)
self.view.sendSubviewToBack(view)
}
}
func subscriber(subscriber: OTSubscriberKit, didFailWithError error : OTError) {
NSLog("subscriber %@ didFailWithError %@", subscriber.stream.streamId, error)
}
// MARK: - OTPublisher delegate callbacks
func publisher(publisher: OTPublisherKit, streamCreated stream: OTStream) {
NSLog("publisher streamCreated %@", stream)
// Step 3b: (if YES == subscribeToSelf): Our own publisher is now visible to
// all participants in the OpenTok session. We will attempt to subscribe to
// our own stream. Expect to see a slight delay in the subscriber video and
// an echo of the audio coming from the device microphone.
if Subscriber == nil && !SubscribeToSelf{
SubscribeToStream(stream)
}
}
func publisher(publisher: OTPublisherKit, streamDestroyed stream: OTStream) {
NSLog("publisher streamDestroyed %@", stream)
if Subscriber?.stream.streamId == stream.streamId {
UnsubscribeStream()
}
}
func publisher(publisher: OTPublisherKit, didFailWithError error: OTError) {
NSLog("publisher didFailWithError %@", error)
}
func showAlert(message: String) {
// show alertview on main UI
dispatch_async(dispatch_get_main_queue()) {
let al = UIAlertView(title: "OTError", message: message, delegate: nil, cancelButtonTitle: "OK")
}
}
}
答案 0 :(得分:0)
您需要仔细考虑转换的逻辑。
在您提供的代码中,您基本上会说:"当订阅者的流被销毁,取消发布并取消订阅流,然后转换回菜单"。
首先,你应该注意你要清理哪种状态。按原样,您假设其他参与者将离开,然后在session:streamDestroyed:
方法中进行清理和转换。相反,使用该方法仅清理订户。同样,在sessionDidDisconnect:
方法中清理发布者。通过清理,我基本上分别意味着调用UnsubscribeToStream()
和UnPublishToSession()
方法。
接下来,您应该考虑触发结束通话所需的问题。假设另一个参与者将首先离开对于简单的情况是可以的,但它是一个更好的设计,为这个离散动作制作一个方法,以便您可以从多个地方调用它。就方法需要做什么而言,它实际上就像调用session.disconnect()
一样简单。这将触发清理发布者和订阅者的上述方法。现在,你完全错过断开连接,这就是当你回到"视频"时,你没有开始订阅的原因。 view(设置调用的所有代码仅从sessionDidConnect:
方法内部调用)。
最后,需要触发segue。在我看来,您应该在sessionDidDisconnect:
方法结束时,在您清理出版商之后执行此操作。