ViewController.swift可能无法正确加载

时间:2015-08-12 14:24:14

标签: swift uiviewcontroller xcode6 opentok

我正在使用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")
    }
}

}

1 个答案:

答案 0 :(得分:0)

您需要仔细考虑转换的逻辑。

在您提供的代码中,您基本上会说:"当订阅者的流被销毁,取消发布并取消订阅流,然后转换回菜单"。

首先,你应该注意你要清理哪种状态。按原样,您假设其他参与者将离开,然后在session:streamDestroyed:方法中进行清理和转换。相反,使用该方法仅清理订户。同样,在sessionDidDisconnect:方法中清理发布者。通过清理,我基本上分别意味着调用UnsubscribeToStream()UnPublishToSession()方法。

接下来,您应该考虑触发结束通话所需的问题。假设另一个参与者将首先离开对于简单的情况是可以的,但它是一个更好的设计,为这个离散动作制作一个方法,以便您可以从多个地方调用它。就方法需要做什么而言,它实际上就像调用session.disconnect()一样简单。这将触发清理发布者和订阅者的上述方法。现在,你完全错过断开连接,这就是当你回到"视频"时,你没有开始订阅的原因。 view(设置调用的所有代码仅从sessionDidConnect:方法内部调用)。

最后,需要触发segue。在我看来,您应该在sessionDidDisconnect:方法结束时,在您清理出版商之后执行此操作。