【问题标题】:No visible @interface for 'RTCPeerConnection' declares the selector 'setLocalDescription:''RTCPeerConnection' 没有可见的@interface 声明选择器'setLocalDescription:'
【发布时间】:2017-02-05 03:17:04
【问题描述】:

我有点困惑在这里需要做什么才能将 webRTC 包含到我的应用程序中。我在 webRTC 网站上关注了这个tutorial,首先将 webRTC 添加到我的 IOS 应用程序中。一切都很顺利,直到我遇到这些错误。不幸的是,我在网上找不到任何关于这些错误或如何在 IOS 上包含 webRTC 的信息。

最终目标是拥有跨平台的视频通话服务。

.h

#import "RTCPeerConnectionDelegate.h"
#import "RTCSessionDescriptionDelegate.h"
...

<RTCPeerConnectionDelegate, RTCSessionDescriptionDelegate>

.m

    #import "RTCICEServer.h"
    #import "RTCPeerConnectionFactory.h"
    #import "RTCMediaStream.h"
    #import "RTCVideoCapturer.h"
    #import "RTCPeerConnection.h"
    #import "RTCAudioSource.h"
    #import "RTCAudioTrack.h"
    #import "RTCMediaConstraints.h"
    #import "RTCSessionDescription.h"
    #import "RTCPair.h"
    #import "RTCEAGLVideoView.h"
    #import "RTCICECandidate.h"



    //The code below is for the webRTC

RTCICEServer *iceServer;
RTCMediaConstraints *constraints;
RTCPeerConnection *peerConnectionRTC;

- (void) setUpVideoCall{
    //Set up for my TURN and STUN servers
    iceServer = [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:@""]
                                                   username:@""
                                                   password:@""];


    NSMutableArray *iceServers = [[NSMutableArray alloc] init];
    [iceServers addObject: iceServer];



    //Creating the RTCPeerConnection
    // Enable SSL globally for WebRTC in our app
    [RTCPeerConnectionFactory initializeSSL];
    RTCPeerConnectionFactory *pcFactory = [[RTCPeerConnectionFactory alloc] init];


    // Create the peer connection using the ICE server list and the current class as the delegate
    peerConnectionRTC = [pcFactory peerConnectionWithICEServers: iceServers
                                                                       constraints:nil delegate:self];



    //Use this code when the call is ended or the app closes
    //[RTCPeerConnectionFactory deinitializeSSL];


    RTCMediaStream *localStream = [pcFactory mediaStreamWithLabel:@"uniqueStreamLabel"];
    RTCAudioTrack *audioTrack = [pcFactory audioTrackWithID:@"audio0"];
    [localStream addAudioTrack:audioTrack];





    // Find the device that is the front facing camera
    AVCaptureDevice *device;
    for (AVCaptureDevice *captureDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] ) {
        if (captureDevice.position == AVCaptureDevicePositionFront) {
            device = captureDevice;
            break;
        }
    }

    // Create a video track and add it to the media stream
    if (device) {
        RTCVideoSource *videoSource;
        RTCVideoCapturer *capturer = [RTCVideoCapturer capturerWithDeviceName:device.localizedName];
        videoSource = [pcFactory videoSourceWithCapturer:capturer constraints:nil];
        RTCVideoTrack *videoTrack = [pcFactory videoTrackWithID: @"videoId" source:videoSource];
        [localStream addVideoTrack:videoTrack];
    }

    [peerConnectionRTC addStream:localStream];





    constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:
    @[
      [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
      [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]
      ]
optionalConstraints: nil];

    //[peerConnectionRTC createOfferWithConstraints:constraints];






}































//The two delaget methods below are for the RTCSessionDescriptionDelegate
- (void)peerConnection:(RTCPeerConnection *)peerConnection didCreateSessionDescription:(RTCSessionDescription *)sdp error:(NSError *)error;{

    [peerConnection setLocalDescription:sdp];

}


- (void)peerConnection:(RTCPeerConnection *)peerConnection
didSetSessionDescriptionWithError:(NSError *)error;{
    if (peerConnection.signalingState == RTCSignalingHaveLocalOffer) {
        RTCSessionDescription *remoteDesc = [[RTCSessionDescription alloc] initWithType:@"offer" sdp: @"sdp"];
        [peerConnection setRemoteDescription:remoteDesc];
    }


    // If we have a local offer we should signal it
    if (peerConnection.signalingState == RTCSignalingHaveLocalOffer) {

        RTCSessionDescription *remoteDesc = [[RTCSessionDescription alloc] initWithType:@"answer" sdp:sdp];
        [peerConnection setRemoteDescription:remoteDesc];

    } else if (peerConnection.signalingState == RTCSignalingHaveRemoteOffer) {
        // If we have a remote offer we should add it to the peer connection
        [peerConnection createAnswerWithConstraints:constraints];
    }


    // If we have a local offer OR answer we should signal it
    if ((peerConnection.signalingState == RTCSignalingHaveLocalOffer) | RTCSignalingHaveLocalPrAnswer ) {
        // Send offer/answer through the signaling channel of our application
    } else if (peerConnection.signalingState == RTCSignalingHaveRemoteOffer) {
        // If we have a remote offer we should add it to the peer connection
        [peerConnection createAnswerWithConstraints:constraints];
    }
}



- (void)peerConnection:(RTCPeerConnection *)peerConnection
       gotICECandidate:(RTCICECandidate *)candidate
{
    RTCICECandidate *candidate = [[RTCICECandidate alloc] initWithMid:SDP_MID
                                                                index:SDP_M_LINE_INDEX
                                                                  sdp:SDP_CANDIDATE];
    [self.rtcPeerConnection addICECandidate:candidate];
}



RTCEAGLVideoView *renderView;
- (void)peerConnection:(RTCPeerConnection *)peerConnection addedStream:(RTCMediaStream *)stream
{
    // Create a new render view with a size of your choice
    renderView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    [stream.videoTracks.lastObject addRenderer:self.renderView];

    // RTCEAGLVideoView is a subclass of UIView, so renderView
    // can be inserted into your view hierarchy where it suits your application.
}







//More RTC delagate methods below that i need

- (void)peerConnection:(RTCPeerConnection *)peerConnection iceConnectionChanged:(RTCICEConnectionState)newState{

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection iceGatheringChanged:(RTCICEGatheringState)newState{

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection removedStream:(RTCMediaStream *)stream{

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection signalingStateChanged:(RTCSignalingState)stateChanged{

}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel{

}

- (void)peerConnectionOnRenegotiationNeeded:(RTCPeerConnection *)peerConnection{

}

感谢任何帮助,文档或教程等信息非常有帮助!谢谢!

【问题讨论】:

  • 你的教程链接链接到图片,你能更新一下吗

标签: ios objective-c webrtc


【解决方案1】:

您收到编译错误,因为使用最新的 libjingle 版本,peerconnection apis 发生了变化。例如设置远程描述更改为下面的api

    [peerconnection setRemoteDescriptionWithDelegate:<#(id<RTCSessionDescriptionDelegate>)#> sessionDescription:<#(RTCSessionDescription *)#>]

您可以查看 google 提供的 apprtc demo 应用程序,将 webrtc apis 集成到您的应用程序中。

【讨论】:

  • 哦,所以我关注的教程已经过时了?
  • 是的。确实如此。
  • 好的,谢谢!您是否知道任何包含最新版本 webRTC 的教程?您是如何让 webRTC 与您的项目一起工作的?
  • 等一下,当this 问题引用了与我相同的教程并且问题只有 11 个月大时,我的教程怎么会过时?
  • 通常,libjingle API 也会随着每个 chrome 版本更新(有时)。 Chrome 版本通常每两个月发布一次。这些 API 更改发生在 chrome 54 中,我猜是 2016 年 10 月发布的。您可以自己构建 webrtc 的静态库/框架,如果您不想使用 pod,可以将其链接到您的项目中。您可以在此处查看webrtc.org/native-code/ios 了解构建步骤。这还创建了一个示例 apprtc 演示(已在我的答案中提供)应用程序,您可以参考它进行集成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 2021-09-22
相关资源
最近更新 更多